自社アプリの利用者に、Manabu2 の ID とパスワードでサインインしてもらう方法です。パスワードは Manabu2 の画面で入力され、アプリを通りません。
全体の流れ
- アプリが PKCE のペアを生成する
- 利用者を Manabu2 のサインイン画面へ送る
- サインイン後、アプリに 認可コード が返ってくる
- アプリがそのコードを トークン に交換する
- トークンで API を呼ぶ
手順 1:PKCE のペアを生成する
サインインのたびに、ランダムな文字列(verifier)と、そのハッシュ(challenge)を作ります。
code_verifier = base64url(ランダムな 32〜64 バイト) // アプリ内に保持する code_challenge = base64url(sha256(code_verifier)) // これだけを送る state = base64url(ランダムな 16 バイト) // 保持し、戻りで照合する
送るのはハッシュだけなので、通信を傍受されてもコードを引き換えられません。state は、意図しないリクエストを弾くための値です。
手順 2:サインイン画面へ送る
GET https://manabu2.com/connect/authorize ?client_id=<登録したクライアント ID> &redirect_uri=<登録済みのリダイレクト URI(URL エンコード)> &response_type=code &scope=read%3Acatalog%20read%3Acontent%20read%3Aprogress%20write%3Aprogress &state=<手順 1 の state> &code_challenge=<手順 1 の challenge> &code_challenge_method=S256
ASWebAuthenticationSession、Android なら Chrome Custom Tabs です。
すでに Manabu2 にサインイン済みの利用者は、入力を求められることなくそのままアプリに戻ります。これがシングルサインオンです。
手順 3:戻ってきたコードを受け取る
acme://auth/callback?code=f5kIhYnGah1I…&state=<送った値>
state が送った値と一致することを確認してください。
一致しない場合は処理を中断し、コードを交換しないでください。
手順 4:コードをトークンに交換する
POST https://api.manabu2.com/api/v1/oauth/token Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &code=<受け取ったコード> &client_id=<クライアント ID> &redirect_uri=<手順 2 と同じ値> &code_verifier=<手順 1 の verifier>
JSON ボディでも送れます。レスポンスには accessToken、expiresAt、refreshToken、scopes、user が含まれます。
手順 5:API を呼ぶ
GET https://api.manabu2.com/api/v1/courses Authorization: Bearer <accessToken>
アクセストークンの有効期限は 1 時間です。
つまずきやすい 3 点
POST /api/v1/auth/refresh を呼ぶたびに新しいリフレッシュトークンが返り、古いものは無効になります。返ってきた新しい値を必ず保存してください。
http と https、ポート番号のいずれか 1 つでも違うと拒否されます。手順 2 と手順 4 でまったく同じ文字列を送る必要もあります。
POST /api/v1/lessons/{id}/quiz/submit は、呼ぶたびに新しい受験履歴を作ります。通信タイムアウト後の再送で、同じ提出が二重に記録されてしまいます。
Idempotency-Key: 9f1c2d4e-7a3b-4c11-9e55-2b8d0f6a1c37
同じキーで再送すると、最初の応答がそのまま返ります。受験履歴は修了証の発行条件に関わるため、ここは特に注意してください。
サードパーティ製アプリの確認画面
この画面から登録したアプリは、利用者が初めてサインインするときに確認画面を表示します。アプリ名と、要求している操作が日本語で表示され、利用者が許可・キャンセルを選びます。
自社で登録したアプリでも確認画面が出るのは、Manabu2 が書いたアプリではないためです。利用者にとっては「どのアプリに何を許可したか」が明示されることになります。