アプリから外部アプリの情報を取得する時、アプリ側では外部アプリのログイン情報を入力する必要がありません。なぜこうしたことが可能なのでしょうか?
確かに普段はあまり意識しませんが、不思議ですよね。外部アプリで連携許可をするだけで、外部アプリの情報を取得できるようになります。この裏側にはOAuth2.0という仕組みがあります。
まずは結論から!
アプリに外部アプリのログイン情報を入力しなくても利用できる理由は、「OAuth2.0を利用することにより発行されたアクセストークンで認証しているため」です。
うーん。わからない。。。難しいですね。一つ一つ説明していきます。
今回は、馴染みの薄い言葉が連発されますので、最初に辞書的に内容を書いておきます。言葉の意味がわからなくなったときに戻って確認するといいかと思います。最初は読み飛ばしてOKです!
- OAuth2.0:アプリに外部サイトのログイン情報を伝えることなく、外部サイトの情報を利用できる仕組み(オーオースと読む)
- クライアント:外部アプリにアクセスしようとするアプリケーション。この記事ではアプリと表現している。
- リソースオーナー:外部アプリのユーザー
- 認可コード:アクセストークンを取得するための許可証。ランダムな文字列
- アクセストークン:アプリが外部アプリにアクセスするための合言葉。ランダムな文字列
- リフレッシュトークン:アクセストークンの有効期限が切れたときに、認可コードを利用せずにアクセストークンを再取得するための合言葉。ランダムな文字列
- 認可サーバー:アクセストークンとリフレッシュトークンを発行する係の人
- リソースサーバー:外部サイトの情報を発行する係の人
- client_id:外部アプリからアプリをみたときに識別する記号
- redirect_uri:認可コードの受け入れ窓口
- response_type:認可コードを受け取る際のキー
- state:クロスサイトリクエストフォージェリを防ぐために、クライアントアプリが利用する値
ユーザーからみた認証の流れ
まず、ユーザーが取る行動をイメージしてから裏側で行われている処理を確認します。大きく4つの工程があります。
- 外部アプリに飛ぶ
- 認証する
- アプリにリダイレクトされる
- 外部アプリの情報が取得できる
ここではマネーフォワードで三井住友銀行との連携を例にしてみていきます。
外部アプリに飛ぶ
連携しようとすると、外部アプリへ誘導されます。
認証する
外部アプリである三井住友銀行にアクセスすると、連携に同意するための認証が行われます。
アプリにリダイレクトされる
アプリの認証を開始したマネーフォワード側のページにリダイレクトされます。
外部アプリの情報が取得できる
三井住友銀行が保有している資産情報を取得できています。
先程の図をもう一度見てみましょう。かなりイメージがついたと思います!
OAuth2.0の仕組み
ユーザー側の流れがわかったところで、いよいよ本題!「なぜアプリ側に外部アプリのログイン情報を入力せずにデータを取得できるのか」をみていきます。
そのためには「なぜアプリ側に外部アプリのログイン情報を入力しない手法をとるのか」を考えないといけません。その理由は次のリスクがあるからです。
- アプリが外部アプリのID・パスワードの情報を保管しなければならず、情報漏えいのリスクが高まる
- 他の優れたセキュリティ対策があった場合でも、外部アプリはいつまでもID・パスワード形式をサポートし続けなければならなくなる
- 外部アプリのユーザーに対して、アプリが過度なアクセス権限を持つことになる
これらの問題を解決するため、OAuth2.0という仕組みを使って、ID・パスワードの代わりにアクセストークンを保存して外部アプリの情報を取得しています。
まずは先程の図解に、裏側の仕組みを追加したもので全体像をざっくりみてみます。
認可コードの取得
認可コードとは
まず、外部アプリに飛んでユーザーが認証する裏側の処理をみていきます。ユーザーが外部アプリの情報をアプリで使うことに同意すると「認可コード」を取得できます。認可コードとは「アクセストークンを取得するためのユーザーの同意書」みたいなものです。
外部アプリから情報を取得するためにはアクセストークンが必要になります。同意書である許可コードをアプリが持っていると、外部アプリはアクセストークンをアプリに対して発行できます。
認可コードの取得に必要な情報
外部アプリにアクセスして連携の認証をするときには次の情報を、同時に送っています。
- response_type
- client_id
- redirect_uri
- state
response_type
認可コードを受け取る際のキーです。形式が定められていてcodeであることが多いです。codeの場合はcode=”ah3eyr9p8auraij09wuf0ijf90wuaifa0w9″みたいな形で認可コードが返ってきます。
client_id
外部アプリがアプリを識別するための記号です。今回の例で言えば、三井住友銀行アプリが、マネーフォワードアプリに対して発行するものです。client_idによって「今回アクセスするアプリはマネーフォワードだな」と認識することができます。
client_idは外部アプリにアプリを登録するときに発行されます。
redirect_uri
redirect_uriは認可コードを受け取る際の窓口を決めています。外部アプリは認証が完了すると指定したuriに認可コードを送信します。
state
クロスサイトリクエストフォージェリ対策です。この時送信された値と、後のレスポンスの際に送られてきた値を照合することで、悪意のあるリクエストかをチェックします。
クロスサイトリクエストフォージェリがわからない方はこちらから
以下のイメージで、外部アプリにアクセスします。
https://accounts.secure.test.co.jp/public_api/authorize?response_type=code&client_id={アプリのclient_id}&redirect_uri={アプリのコールバックURL}&state={ランダムな文字列}
認可コードを使うメリット
認可コードを使うメリットを確認しておきます。
- client_idを送って、どのアプリからアクセスされているのか識別してセキュリティを高めている
- ユーザーのユーザーエージェントを経由せずにアクセストークンをアプリに直接送信することで、データ漏洩のリスクを下げている
ここまでの流れを整理しましょう。
- response_type・client_id・redirect_uriを外部アプリに送信
- ユーザーが認証
- 認証成功
- redirect_uriに認可コードが送られる
- ユーザーアプリの画面にリダイレクト
アクセストークンの取得
アクセストークンとは
ユーザーの同意が取れたので、次は認可コードを利用してアクセストークンを取得します。アクセストークンとは「アプリが外部アプリにアクセスするための合言葉」みたいなものです。
実際はランダムな文字列がわたってきて、この値を照合することで、ユーザーが連携の許可をしているかや、どのアプリからアクセスしているかを確認しています。
アクセストークンを取得することによってアプリから外部アプリの情報を取得することができるようになります。
アクセストークンの取得に必要な情報
アクセストークンを取得するためには以下の情報を外部アプリに送信します。
- content_type
- grant_type
- 認可コード
- client_id
- client_secret
content_type
データを送る形式です。application/x-www-form-urlencodedが用いられます。「エンコードされたurl形式で送信しますよ!」という意味になります。
a=1&b=1 → %20a%3D1%26b%3D1 みたいなイメージです。
grant_type
直訳で「許可タイプ」です。アクセストークンを取得する方法を決めます。次の方法があります。
- authorization_code→許可コードで初回取得
- refresh_token→リフレッシュトークンで再取得
client_secret
アプリを外部アプリに登録したときに発行されるパスワードです。
こうした設定で外部アプリにPOST送信します。
外部アプリから返却値
通信に成功すると外部アプリから2つの値が返却されます。
- access_token
- refresh_token
access_token
外部アプリから情報を取得する許可証です。有効期限がアプリごとに決められていて、24時間や6時間など比較的短い期間です。
refresh_token
アクセストークンの有効期限が切れた場合に再取得する許可証です。もし、リフレッシュトークンがない場合、認可コードの取得からやり直さなければなりません。そうなるとユーザーは6時間などの短い期間で認証作業をしなければならず、ストレスがたまります。
こうした不都合を解消するために、リフレッシュトークンも一緒に返却してアクセストークンを再取得しやすい仕組みになっています。
アクセストークンを使ってデータ取得
最後はアクセストークンを用いつつ、外部アプリにアクセスします。
外部アプリのリソースサーバーは、以下をチェックして問題なければ、データを送信します。
- 正しいアクセストークンか
- 有効期間が切れていないか
アクセストークンの有効期間が切れた場合
アクセストークンの有効期間が切れている場合、リソースサーバーはアプリに対してエラーを返します。
アプリは認可サーバーに対して、リフレッシュトークンを使って新しいアクセストークンを取得しにいきます。
リフレッシュトークンに問題なければ、認可サーバーから新たなアクセストークンが送信されます。
アプリは新たなアクセストークンを使って、外部アプリから情報を取得しにいきます。
まとめ
お疲れさまでした!最後にまとめていきます!
外部アプリの情報をアプリが持つことは次のリスクがありました。
- アプリが外部アプリのID・パスワードの情報を保管しなければならず、情報漏えいのリスクが高まる
- 他の優れたセキュリティ対策があった場合でも、外部アプリはいつまでもID・パスワード形式をサポートし続けなければならなくなる
- 外部アプリのユーザーに対して、アプリが過度なアクセス権限を持つことになる
このリスクを回避するために、OAuth2.0という仕組みを利用して「アプリに外部サイトのログイン情報を伝えることなく、外部サイトの情報を利用できる」ようになっています。
具体的には次のステップで認証され、データを取得しています。
- 認可コードを認可サーバーから取得
- アクセストークンを認可サーバーから取得
- アクセストークンを使ってリソースサーバーからデータを取得
大枠のみを説明して細かい部分は省略しましたので、詳しくはぜひ調べてみてください!!
コメント