oauth
oauth カテゴリの 7 個の API オペレーションを扱います。
| メソッド | パス | 説明 |
|---|---|---|
| GET | /.well-known/oauth-authorization-server | 認可サーバーメタデータ (RFC 8414) |
| GET | /.well-known/jwks.json | アクセストークンの公開鍵 |
| POST | /v1/oauth/authorize | 連携アプリを承認し、認可コードを発行します |
| POST | /oauth/token | コードの交換、またはリフレッシュ (RFC 6749) |
| POST | /oauth/revoke | 連携アプリをサインアウトします (RFC 7009) |
| GET | /v1/oauth/grants | 連携アプリ |
| DELETE | /v1/oauth/grants/{sid} | 連携アプリを削除します |
GET /.well-known/oauth-authorization-server
クライアントが認証情報を持つ前に読み取るため、定義上、公開されています。
authorization_endpoint が指すのはこの API ではなくダッシュボードです。認可のステップではユーザーのログインセッションを確認する必要があり、そのセッションはブラウザーにあります (docs/studio.md §8.1)。runlot_access_token_audience は RFC 8414 にはありません。リソースサーバーが必要とする aud を、食い違う可能性のある別の設定値ではなく発行元から知るために用意しています。
operationId oauthMetadata
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | メタデータドキュメント | object |
| 503 | このデプロイでは連携アプリのサインインが設定されていません | Error |
GET /.well-known/jwks.json
廃止されていないすべての署名鍵です。ローテーション中は 2 つが公開されます。これが鍵のセットである理由はまさにそこにあります。1 つの鍵だけをキャッシュした検証側は、もう一方の鍵で発行されたトークンを拒否してしまいます。キャッシュできるのは 1 分間だけです。古いコピーは新しいトークンを拒否します。
operationId oauthJwks
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | 鍵のセット | object |
POST /v1/oauth/authorize
ダッシュボードの /oauth/authorize 画面が、ユーザーのログインセッションを使って呼び出します。パーソナルアクセストークンは、スコープに関係なく拒否されます。認証情報が自らを、より長寿命の認証情報へ広げられてはならないためです。
画面が受け取ったクエリ文字列をそのまま転送するため、パラメーターにはこのドキュメントの camelCase ではなく OAuth 本来の名前を使います。
operationId oauthAuthorize
リクエストボディ: application/json ・ object
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | 承認されました。ブラウザーは redirect に送られます。 | object |
| 400 | — | — |
| 401 | — | — |
POST /oauth/token
JSON ではなくフォームエンコードです。RFC 6749 §4.1.3 に従い、すべてのクライアントライブラリがこの形式で送信します。
失敗時は、このドキュメントのエラーエンベロープではなく RFC 6749 §5.2 のボディを返します。この 2 つのエンドポイントは、runlot 独自の形式を解析できない汎用の OAuth クライアントが読み取るためです。
リフレッシュトークンはローテーションします。使用すると無効になり、次のトークンが返されます。クライアントごと・アドレスごとにレート制限があります (429)。
operationId oauthToken
リクエストボディ: application/x-www-form-urlencoded · object
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | 新しいアクセストークンと、次のリフレッシュトークン | OAuthTokenResponse |
| 400 | RFC 6749 §5.2 | OAuthError |
| 429 | このクライアントまたはこのアドレスからの試行が多すぎます | OAuthError |
| 503 | このデプロイでは連携アプリのサインインが設定されていません | OAuthError |
POST /oauth/revoke
フォームエンコードです。未知のトークンに対しても 200 を返します。RFC 7009 §2.2 が要求しているためで、ほかの応答を返すと、このエンドポイントがどのトークンが存在するかを探るオラクルになってしまうからです。
リフレッシュトークンを失効させると、ローテーションの 1 世代だけでなくグラント 全体が失効します。「Studio でサインアウト」すると、そのデバイスは連携アプリからも消えます (docs/studio.md §8.4)。クライアントごと・アドレスごとにレート制限があります (429)。
operationId oauthRevoke
リクエストボディ: application/x-www-form-urlencoded · object
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | 失効しました。またはトークンが未知でした。この 2 つは意図的に同じ応答です | — |
| 400 | RFC 6749 §5.2 | OAuthError |
| 429 | このクライアントまたはこのアドレスからの試行が多すぎます | OAuthError |
GET /v1/oauth/grants
現在このアカウントにアクセスできるものの一覧です (docs/studio.md §8.4)。失効したグラントは一覧に含まれません。無効な行を残す一覧では、読み手が自分で絞り込まなければ答えが得られなくなるためです。
POST /v1/oauth/authorize と同じ理由で、セッションのみ使用できます。
operationId listOAuthGrants
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 200 | グラント | object |
| 401 | — | — |
DELETE /v1/oauth/grants/{sid}
リフレッシュトークンはグラントとともに無効になり、アクセストークンは次のリクエストで sid のチェックによって無効になります。失効は cp-core のフィードを通じて Studio サービスにも届くため、貸し出されたモデルは、アクセストークンの 15 分を待たずにすぐに切り離されます。
そのユーザーのものではないグラントは 403 ではなく 404 になります。他人のグラント id が存在すると呼び出し元に伝えることが、グラント id の探索につながるためです。
operationId revokeOAuthGrant
| ステータスコード | 説明 | レスポンスボディ |
|---|---|---|
| 204 | 削除済み | — |
| 401 | — | — |
| 404 | — | — |