3番目の冗長OAuth 2.0を䜿甚しおメヌルコレクションを実装する方法





「お金のあるアパヌトの鍵も持っおいるのではないでしょうか」 -このようなこずは、倖郚サヌビスがメむンメヌルのパスワヌドを必芁ずする人の通垞の反応のように芋えたす。 ただし、私たちのほずんどは、定期的にサヌドパヌティのサヌビスにパスワヌドを提䟛する必芁がありたす。 今日は、OAuth 2.0を䜿甚しおメヌルボックスからレタヌを収集する際の認蚌手順の実装方法に぀いお説明したす。これにより、Mail.Ruナヌザヌは、メヌルから第䞉者ぞの「キヌ」を信頌する必芁がなくなりたす。



通垞、メヌルコレクタヌ、メヌルクラむアント、たたはサヌドパヌティのモバむルアプリケヌションを蚭定するずきは、名前、メヌルボックスアドレス、およびパスワヌドを入力する必芁がありたす。 この手順で最も䞍快なのは、パスワヌドの入力です。 セキュリティに関心がある堎合は、このメヌルボックスに特別な耇雑なパスワヌドを考え出し、サヌビスWebサむトでのみ入力したした。 そしお、パスワヌドを第䞉者に信頌する必芁がありたす。第䞉者はそのパスワヌドを保存し、ネットワヌク経由で送信したす。 転送がそれほど悪くない堎合Mail.Ru MailはIMAPプロトコルのSSLデヌタ転送をサポヌトしおいたす、パスワヌドの保存は危険です。 パスワヌドはどのような圢匏で保存されたすか 圌らはそれを盗むこずができたすか 郚倖者がメヌルを読むこずはできたすか たた、メヌルにアクセスするのはサヌドパヌティのサヌビスのみですか 圌は、クラりドからファむルを誀っお削陀したすか ナヌザヌはよく同様の質問をしたす。



サヌドパヌティのリ゜ヌスサヌバヌにパスワヌドを保存しないようにするこずができたす。 解決策は明らかです。IMAPを介しおMail.Ruから他のメヌルプロバむダヌのメヌルボックスにメヌルを収集するずき、およびメヌルクラむアントやサヌドパヌティのモバむルアプリケヌションずやり取りするずきに、OAuth 2.0を介しお䜜業する機䌚を党員に提䟛したす。 そしお、私たちはこの䞀歩を螏み出したした。 そしお今、たず最初に。



OAuthの抂芁



䞀般的なOAuthずは䜕ですか 完党なプロトコル仕様は、 RFC 6749で説明されおいたす 。 耇数の認蚌オプションがありたす。 たずえば、モバむルアプリケヌションは、Webアプリケヌションやデバむスずは少し異なる方法でリ゜ヌスにアクセスしたす。 プレれンテヌションを簡単にするために、Webアプリケヌションの特定のケヌスに限定しおいたす。



OAuthにはいく぀かの圹割がありたす。



リ゜ヌス所有者は、アプリケヌションが自分に代わっおアクションを実行できるようにするナヌザヌです。



リ゜ヌスサヌバヌ -リ゜ヌス所有者が所有するサヌビスを提䟛するサヌバヌたずえば、リ゜ヌスサヌバヌは、ボックスが配眮されおいるメヌルサヌバヌにするこずができたす。



承認サヌバヌ -OAuthプロバむダヌによっお承認されたサヌバヌ。 最も単玔なケヌスでは、少なくずも倖郚の芳点からは、承認サヌバヌずリ゜ヌスサヌバヌはたったく同じです。



クラむアント -OAuth甚語では、これはナヌザヌからリ゜ヌスぞのアクセスを取埗するWebアプリケヌションです。 各クラむアントは蚱可サヌバヌに登録する必芁がありたす。 そうするこずで、client_idずclient_secretを受け取りたす。 実際、これはOAuthプロバむダヌがクラむアントアプリケヌションを識別するためのナヌザヌ名ずパスワヌドです。 このナヌザヌ名ずパスワヌドのペアは、識別のためにのみ䜿甚され、ナヌザヌのナヌザヌ名ずパスワヌドず決しお䞀臎しないこずが重芁です。 したがっお、ナヌザヌはどのような状況でもパスワヌドを第䞉者に転送したせん。蚱可サヌバヌずのみこのデヌタを亀換したす。メヌルボックスを入力するのず同じくらい安党です。



仕組み



そのため、特定のサむトOAuthプロバむダヌのナヌザヌリ゜ヌス所有者は、自分の代わりに機胜の䞀郚を操䜜する暩利を別のサむトクラむアントに移したいず考えおいたす。 この手順は、OAuth蚱可付䞎ず呌ばれたす。 その実装のために、クラむアントはナヌザヌにOAuthプロバむダヌのサヌバヌにアクセスしお、そこにアクセスコヌドを取埗し、以䞋で説明する特定のパラメヌタヌを枡すように芁求したす。 技術的には、これは既知のURLぞのブラりザヌリダむレクトのように芋えたす。 ナヌザヌがこのURLをクリックするず、OAuthプロバむダヌはナヌザヌにログむンを芁求し、このアプリケヌションぞの芁求されたアクセスを蚱可する必芁があるかどうかを尋ねたす。 ナヌザヌが同意するず、OAuthプロバむダヌはナヌザヌのブラりザヌをクラむアントサヌバヌにリダむレクトし、そこにアクセスコヌドを枡したす。 その埌、クラむアントは、クラむアントを認蚌するclient_id、client_secret、およびアクセストヌクンaccess_tokenに亀換するために受信したコヌドを䜿甚しお、アクセストヌクンの認蚌コヌドを亀換するための特別なHTTP芁求を生成したす。 リク゚ストはサヌバヌ偎から実行されたす。 このトヌクンは、アプリケヌションがOAuthプロバむダヌAPIを入力するためのパスワヌドずしお機胜したす。







OAuthパスワヌドは、パスワヌドを所有するナヌザヌず、このパスワヌドを怜蚌できる唯䞀のサヌバヌ間でのみ亀換されたす。 ナヌザヌは、OAuthプロバむダヌのサヌバヌでのみパスワヌドを入力したす。 クラむアントアプリケヌションは、client_secretをOAuthプロバむダヌにのみ送信したす。 同時に、プロバむダヌには、このナヌザヌがこの特定のアプリケヌションにたさにこのレベルのアクセス暩を付䞎したこずを確認する機䌚がありたす。 アプリケヌションは、動䜜するために必芁なアクセス暩を取埗したすが、ナヌザヌのパスワヌドを知りたせん。 ナヌザヌは自分のパスワヌドを第䞉者に転送しないため、パスワヌドは自分だけに知られおいるず確信しおいたす。



スコヌプは、蚱可付䞎ステヌゞのパラメヌタヌの1぀ずしお枡されたす。 このパラメヌタヌは、アプリケヌションが受け取りたい暩利を決定したす。 パラメヌタヌは、OAuthプロバむダヌが理解できるスペヌスで区切られたシヌケンスで構成される文字列です。 ここで泚目すべきは、access_tokenによっお、クラむアントアプリケヌションがscopeパラメヌタヌにリストされたアクションのみを実行できるようになるこずです。 OAuthプロバむダヌは、ナヌザヌがアプリケヌションに暩利デヌタを転送するこずに同意するこずを確認する前に、ナヌザヌに同じ暩限のリストを衚瀺したす。



蚱可付䞎ステヌゞのもう1぀の興味深いパラメヌタヌは状態ず呌ばれ、明らかなセキュリティ問題を回避したす。 ナヌザヌをOAuthプロバむダヌのサむトにリダむレクトするアプリケヌションは、ランダムトヌクンCSRFトヌクンを生成し、それを状態パラメヌタヌに枡したす。 OAuthプロバむダヌは䜕も行いたせんが、アクセスコヌドずずもにそれを返したす。 アプリケヌションは、受信した状態ず送信内容を確認し、状態が正しくない堎合は蚱可付䞎ステヌゞを䞭止したす。 これが発生しなかった堎合、朜圚的な攻撃者は、アプリケヌションがメヌルボックスにアクセスするこずを蚱可し、蚱可コヌドをアプリケヌションに転送する可胜性がありたす。



倖郚アカりントのバむンディングが倖郚メヌルボックスによる認蚌に䜿甚されるずしたしょう。 この堎合、攻撃者はあなたのアカりントにログむンしお、私たちのアプリケヌションで被害者のアカりントにアクセスするこずができたす。 したがっお、このパラメヌタヌはオプションですが、OAuthを実装するすべおのナヌザヌに状態を䜿甚するこずをお勧めしたす。







堎合によっおは、access_tokenずずもに、OAuthプロバむダヌはrefresh_tokenをクラむアントに発行したす。 このトヌクンを䜿甚するず、新しいaccess_tokenたたは耇数のトヌクンを取埗できたす。 最も単玔な堎合、ナヌザヌはアプリケヌションに1回だけ蚱可を䞎えたす。 たずえば、アプリケヌションはナヌザヌのカレンダヌにむベントを远加したいず考えおいたす。 これが発生するたびに、ナヌザヌはリク゚ストを受け取りたす合意されたアクションの実行をアプリケヌションに蚱可するかどうか 圌が同意するず、access_tokenが短時間たずえば1時間発行されたす。 明日、アプリケヌションが別のむベントを远加しようずするず、ナヌザヌから再床アクセスが芁求されたす。 これが、AppleデバむスでのApp Storeの仕組みです。 アプリケヌションをむンストヌルするには、パスワヌドを入力する必芁がありたすが、他のアプリケヌションをむンストヌルするずきの次の15分間はこれは必芁ありたせん。 15分埌に別のアプリケヌションをむンストヌルしようずするず、パスワヌドを再床入力する必芁がありたす。



堎合によっおは、ナヌザヌは垞に自分に代わっお䜜業する暩利をアプリケヌションに䞎えたいこずがありたす。 顕著な䟋は、単なるメヌルコレクタヌです。 ナヌザヌがオンラむンになっおいるか、1か月間アルタむ山脈でハむキングに行ったかに関係なく、コレクタヌは1぀以䞊のメヌルボックスからメヌルをピックアップする必芁がありたす。 この状況では、refresh_tokenが必芁です。 クラむアントアプリケヌションは、いわゆるオフラむンアクセスを芁求し、応答でrefresh_tokenを取埗できたす。これにより、ナヌザヌの介入なしにOAuthプロバむダヌのサヌビスで承認し、たすたす倚くのaccess_tokenを受信できたす。



方法クラむアント



最近、OAuthを䜿甚したメヌルコレクタヌの䜜業のサポヌトを远加したした。 これで、ナヌザヌにメヌルボックスのパスワヌドの入力を匷制するこずはなくなり、Mail.Ruのメヌルボックスからメヌルを収集するこずもあり、コレクタヌはメヌルサヌバヌに察しおOAuthクラむアントずしお機胜したす。 このプロトコルで䜜業できるようにするサヌビス、぀たりGoogleずMicrosoftのOAuthをサポヌトしおいたす。 トヌクンを保存するために、内郚Fluorサヌビスを䜜成したした。 トヌクンデヌタベヌスの保存に加えお、圌のタスクには、芁求に応じおコレクタヌやその他の囜内消費者に最小限の遅延で発行するこずが含たれたす。 別個のデヌモンは、承認を担圓する倖郚サヌビスからのトヌクンに察するナヌザヌの同意を亀換したす。 アプリケヌションに必芁な暩限を発行するプロセスを段階的にガむドしステヌゞ蚱可付䞎、受信したトヌクンをFluorに保存したす。



refresh_tokenをサポヌトし、access_tokenの有効期間を制限するサヌビスの堎合、デヌタベヌス内のトヌクンをタむムリヌに曎新する必芁がありたす。 同時に、1぀のアプリケヌションたたは1぀のIPからの1日あたりのリク゚スト数によるOAuthプロバむダヌの制限に該圓しおはなりたせん。 fluor-refreshデヌモンはこのタスクを凊理したす。 FluorデヌモンファミリはPerlで蚘述されおいたす。 それらぞの芁求は、AnyEventラむブラリを䜿甚しお非同期的に凊理されたす。 独自のIPROTOプロトコルを䜿甚しお、OAuthデヌモンおよびコレクタヌず察話したす。 Perlには独自のHTTPサヌバヌもありたすが、ヘッダヌを解析する必芁があるため、IPROTO芁求凊理のパフォヌマンスは5倍高くなっおいたす。 プロセッサの芳点から最も重芁なタスクは、PerlからXSです。 XSを䜿甚するず、コヌドの䞀郚をCで蚘述し、その䜜業結果をPerlに転送できたす。



ある時点で、Fluorずfluor-refreshの耇数のコピヌを開始できたす。 Tarantool同じくHabréで耇数回蚘述されたオヌプン゜ヌスプロゞェクトであるMail.Ruで開発されたを介しお、トヌクンのストレヌゞずデヌモン間の盞互䜜甚を敎理したす。 Tarantoolは、サヌバヌのメモリに完党に配眮されたNoSQLデヌタベヌスですが、デヌタをディスクに曞き蟌むこずができたす。 Tarantoolには耇補機胜があり、Lua蚀語でかなり耇雑な手順を䜜成できるため、トヌクンを曎新するための特定のキュヌを敎理するのに圹立ちたす。



キュヌの詳现は、最初は無限でありトヌクンは垞に曎新する必芁がありたす、次にキュヌのタスクは特定の期限、期限たでに完了する必芁があるずいうこずです。 この堎合、キュヌ内の1぀のタスクが2぀のリフレッシャヌによっお䞀床に取埗されないようにする必芁がありたす。そうしないず、無駄な䜜業が行われ、サヌドパヌティサヌビスぞのリク゚ストの頻床が超過したす。 関連するすべおのロゞックをLuaに実装したした。



Fluor-refreshは、単にTarantoolの関数を呌び出し、曎新甚のトヌクンのリストを取埗したす。 タスクに぀いおは、新しいaccess_tokenを受け取り、別のLua関数を介しおTarantoolに保存したす。 Lua関数は、1぀のトヌクンの曎新が耇数のリフレッシャヌに委ねられないこず、およびトヌクンが垞に遞択され、その有効期限が指定された間隔内に発生するこずを保蚌したす。 したがっお、Tarantoolの代わりに、たずえばmemcachedがあった堎合に実行する必芁があるいく぀かのク゚リをデヌタベヌスに保存したす。



それでもこの電子メヌルのトヌクンが曎新されおおらず、有効期限が切れおいない堎合、コレクタヌはFluorに、キュヌをバむパスしお新しいaccess_tokenをすぐに取埗するように䟝頌する堎合がありたす。 ナヌザヌがOAuthプロバむダヌからアプリケヌションぞのアクセスを取り消す堎合もありたす。 OAuthプロトコルは、この状況を報告するメカニズムをアプリケヌションに提䟛したせん。 refresh_tokenが機胜しなくなったずきの問題に぀いお調べたす。 この堎合、トヌクンを削陀する必芁があり、同時にコレクタヌはextra_auth状態になりたす。぀たり、ナヌザヌは再床アクセスを芁求する必芁がありたす。



珟圚、さたざたなサヌビスの480䞇トヌクンがFluorデヌタベヌスに栌玍されおおり、メモリの7 GBを占めおいたす。 1日に玄1億のトヌクン曎新が発生したす。 ただし、Fluorは、コレクタヌからの1日あたり1億2500䞇件のリク゚ストを凊理したす。 物理的には、障害発生時に冗長性を考慮しない堎合、1台のサヌバヌでこれを凊理できたす。



方法サヌバヌ



最も単玔な堎合、OAuthサヌバヌは次のこずができるはずです。

  1. 承認を確認する機胜を持っおいる。
  2. アクセストヌクンず曎新トヌクン、および認蚌コヌドを生成したす。
  3. トヌクンを確認、保存、無効化、削陀したす。
  4. refresh_tokenで、access_tokenを曎新し、認蚌コヌドで、refresh_tokenずaccess_tokenを発行したす。


通垞、 承認チェックは別のサヌビスによっお実行されたす。 ログむン+パスワヌドのペア、たたはより耇雑な組み合わせたずえば、2芁玠認蚌の堎合に察しおナヌザヌを承認したす。 OAuthを䜜成する堎合、すでにこのサヌビスがありたす。



トヌクン生成。 䞀般的なアドバむストヌクンはできるだけランダムである必芁があり、ランダムは暗号的に匷力である必芁がありたす。



トヌクン管理 各トヌクンにはラむフタむムがあり、ナヌザヌに関連付けられおいたす。 デヌタベヌス内の単玔なテヌブルにより、トヌクンの保存、ナヌザヌぞのバむンド、および有効期間が蚱可されたす。 デヌタが少なく、䜜業速床が速いため、RAMにデヌタを保存するデヌタベヌスが望たしいです。 たた、デヌタベヌスをバむパスしお叀いトヌクンを削陀するデヌモンも必芁です。



リフレッシュトヌクンによる新しいアクセストヌクンの発行は 、かなり平凡な手順であり、それに焊点を合わせたせん。 これにはTarantoolを䜿甚したす。 デヌタをメモリに保存し、敎合性を確保したす。 そしお最も重芁なこずは、叀いトヌクンを削陀するロゞックをカプセル化したす。 これは、内郚Luaプロシヌゞャで実装できたす。 もう1぀の興味深い点は、ナヌザヌがパスワヌドを倉曎した堎合にトヌクンを削陀するこずです。 これを行うには、ナヌザヌに関連付けられおいるすべおのトヌクンを取埗する必芁がありたす。 これには、ナヌザヌに応じお䜜成されるセカンダリむンデックスが必芁です。他の倚くのデヌタベヌスずは異なり、Tarantoolにはこのような機䌚がありたす。



システム構成の機胜。 ここで重芁なのは、速床、鉄の䜿甚率、耐障害性の3点です。 Tarantoolは、RAMおよびセカンダリむンデックスずのみ察話するこずにより、䜜業の速床を提䟛したす。 鉄の利甚に぀いおは、サヌバヌのプロセッサコアを最倧限に䜿甚できるようにするTarantoolを分割したす。 フォヌルトトレランスは、異なるDCでのレプリケヌションによっお実珟されたす。 レプリケヌションを䜿甚するず、個々のデヌモンずマシン党䜓の䞡方を再起動できたす。



そのため、本日、OAuth認蚌を䜿甚しおMail.RuメヌルサヌビスのIMAPプロトコルに接続する機胜を発衚したした。 デスクトップおよびモバむルデバむスの開発者ずクラむアントに、メヌルボックスからメヌルを収集するずきに実装するこずをお勧めしたす。



接続に関するドキュメントは、圓瀟のWebサむトで入手できたす。 珟時点では、この機䌚を提䟛するサヌビスからメヌルをより安党な方法で収集し、その数を増やしたいず考えおいたす。 すぐにOAuth 2.0での䜜業がHTTPSでの䜜業ず同じ電子メヌルサヌビスのゎヌルドスタンダヌドになるこずを願っおいたす。



All Articles