Open Cloud は、クライアントが機密か公開かに応じて、OAuth 2.0 の認可フローを PKCE でサポートします。
- 機密クライアント は、バックエンドで安全に秘密を保存して回収できるウェブサイトなど、クレデンシャルを機密に保つことができるアプリです。
- 公開クライアント は、モバイルやウェブブラウザアプリなど、秘密を保持できないアプリです。
すべてのクライアントに対して OAuth 2.0 認可コードフローを PKCE で行い、公開クライアントに対してそれを要求します。
認可コードフローを実装するには、アプリは次のステップを実行します:
- コード検証機とコードチャレンジを生成(PKCE のみ)。これにより、クライアントの秘密ではなくリクエストにチャレンジを含めることができ、セキュリティが向上します。
- 適切なパラメータで GET 要求を認可エンドポイントに送信します。
- 認証コールバックを処理する。認可を得た後、アプリの作作品中に指定した URL にリダイレクトリクエストで Roblox からの認可コードを使用します。後で使用するための認証コードを解析します。
- トークンエンドポイントに認可コードで POST リクエストを送信します。成功すると、API 呼び出しを行うためのアクセストークンとリフレッシュトークンを受け取ります。
- アクセスしたいリソースに関する参照文書に基づいて OAuth 2.0 認証をサポートするオープンクラウド APIを呼び出します。
次のセクションでは、それぞれのステップをより深く説明します。
コードチャレンジを生成する (PKCE のみ)
認証プロセスを開始する前に、コード検証機からコードチャレンジを生成する必要があります。プログラミング言語の選択により、ライブラリや組み込み関数を使用してコード検証機を作成し、ハッシュを計算し、Base64 エンコードを行ってコードチャレンジを生成できます。
コード検証機を作成するときは、大文字と小文字の文字(A-Z、a-z)、デカルト式の数字(0-9)、ハイフン (-)、期間(.)、アンダースコア(_)、そしてタイルド(~)を含む、最低 43 文字、最大 128 文字の長さのコードを作成します。
次の例では、JavaScript を使用してコード検証機を作成し、SHA-256 ハッシュアルゴリズムを使用してコードチャレンジを生成する方法を示します:
Generate Code Challenge
const crypto = require('crypto');
// base64URL encode the verifier and challenge
function base64URLEncode(str) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// create sha256 hash from code verifier
function sha256(buffer) {
return crypto.createHash('sha256').update(buffer).digest(`base64`);
}
// create a random code verifier
var code_verifier = base64URLEncode(crypto.randomBytes(32));
// generate a challenge from the code verifier
var code_challenge = base64URLEncode(sha256(code_verifier));
PKCE の場合、後のステップでコード検証者とチャレンジ値の両方が必要です。
認可 URL を構築する
ユーザー認証プロセスを開始するには、必要なパラメータで認可 URLを構成します:
- client_id : アプリの登録後に取得されたアプリのクライアント ID。 登録するアプリ。
- redirect_uri : アプリのリダイレクト URI、アプリの再入りポイント。
- scope : スペース区切り列にアプリが必要なアクセス権を定義するリクエストされたスコープ。
- response_type : 認可コードフローを示すために code に設定します。 PKCE のみに必要
- code_challenge : コード検証機から生成されたコードチャレンジ。
- code_challenge_method : このパラメータ値を S256 に設定して、コードチャレンジが SHA-256 アルゴリズムを使用して変換され、最も広く支持され、安全なコードチャレンジ方法で変換されたことを示します。
- state : 不透明で安全なランダム値で、リクエストとコールバックの間の状態を維持します。 PKCE以外の場合に必要
- : アプリを登録後に取得されたアプリのクライアント秘密。PKCE で認証を使用している場合は、このパラメータを省略します。認可リクエスト URL は、以下の例のように形式化されている必要があります:
PKCE 認可 URL の例
https://apis.roblox.com/oauth/v1/authorize?client_id=7290610391231237934964&code_challenge=PLEKKVCjdD1V_07wOKlAm7P02NC-LZ_1hQfdu5XSXEI&code_challenge_method=S256&redirect_uri=https://example.com/redirect&scope=openid%20profile&response_type=code&state=abc123
ユーザーが URL を訪問すると、認証フローを通過します。成功すると、Roblox はユーザーを指定された redirect_uri にリダイレクトします。
認証コールバックを処理する
認可フローが成功すると、指定した GET の Roblox 認可サーバーからアプリに redirect_uri リクエストが送信されます。リクエストでは、code (認証コード) と state (以前に値を提供した場合) パラメータが受け取られます。
code パラメータには、アプリが認可サーバーからアクセストークンと交換できる認可コードが含まれています。ほとんどのバックエンドサーバー言語では、クエリパラメータをデコードしたオブジェクトにアクセスする標準的な方法があります。アクセストークンと交換するには、code パラメータを取得して使用する必要があります。
state パラメータは、最初に認可リクエストに提供した不透明な値です。このパラメータを使用して、認証プロセスの状態やコンテキストを維持できます。
たとえば、リダイレクト URI を https://example.com/redirect に指定した場合、次の URL で GET リクエストを受け取る可能性があります。
例のリダイレクト URL
https://example.com/redirect?code=10c45PNuquKnFJ6pUcy5-fHkghEM6lSegm-7hj9mVEprub1dSDuStuKK_EAUXY7AHTD63xcnmvxSLthp-C8g3jzIGZVzuXSd20Y2dEYI9hx0LZmPg95ME4z2K03UheiZbroyXUjYyB3ReoMqobzDVPzyx6IS8kj2Uu-11Xq_0JiTYxtDatuqXRNIAmJT8gMJmbSyOLOP_vnDvbeMUiBsqCRrkTGVbWSwYSc8sTVVE-535kYdqQOgNjH1ffCoZLGl8YYxLnpb2CXJlRQPrcjkA&state=6789
認証に失敗すると、アプリは GET 、 error 、 error_description 、 state (該当する場合) パラメータを含む指定のリダイレクト URLへのリクエストを受け取ります。
- error パラメータは、認証プロセス中に発生した特定の OAuth 2.0 エラーを示します。
- error_description パラメータは、エラーの詳細を追加します。
- state パラメータは、アプリが失敗の場合に状態を維持するのを助けます。
認可コードをアクセストークンに交換する
認証を解析したとき、code 、希望の Roblox リソースにアクセスするためにトークンに交換する:
受信した応答から適用可能なトークンを解析します。アクセストークンは 15分間有効です。リフレッシュトークンを安全に保管し、通常はサーバー側で、将来に新しいトークンを取得するために使用できます。
トークン終端レスポンスの例{"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6IlBOeHhpb2JFNE8zbGhQUUlUZG9QQ3FCTE81amh3aXZFS1pHOWhfTGJNOWMiLCJ0eXAiOiJKV11234.eyJzdWIiOiIyMDY3MjQzOTU5IiwiYWlkIjoiM2Q2MWU3NDctM2ExNS00NTE4LWJiNDEtMWU3M2VhNDUyZWIwIiwic2NvcGUiOiJvcGVuaWQ6cmVhZCBwcm9maWxlOnJlYWQiLCJqdGkiOiJBVC5QbmFWVHpJU3k2YkI5TG5QYnZpTCIsIm5iZiI6MTY5MTYzOTY5OCwiZXhwIjoxNjkxNjQwNTk4LCJpYXQiOjE2OTE2Mzk2OTgsImlzcyI6Imh0dHBzOi8vYXBpcy5yb2Jsb3guY29tL29hdXRoLyIsImF1ZCI6IjcyOTA2MTAzOTc5ODc5MzQ5Nj1234.BjwMkC8Q5a_iP1Q5Th8FrS7ntioAollv_zW9mprF1ats9CD2axCvupZydVzYphzQ8TawunnYXp0Xe8k0t8ithg","refresh_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwia2lkIjoidGpHd1BHaURDWkprZEZkREg1dFZ5emVzRWQyQ0o1NDgtUi1Ya1J1TTBBRSIsInR5cCI6IkpXVCJ9..nKYZvjvXH6msDG8Udluuuw.PwP-_HJIjrgYdY-gMR0Q3cabNwIbmItcMEQHx5r7qStVVa5l4CbrKwJvjY-w9xZ9VFb6P70WmXndNifnio5BPZmivW5QkJgv5_sxLoCwsqB1bmEkz2nFF4ANLzQLCQMvQwgXHPMfCK-lclpVEwnHk4kemrCFOvfuH4qJ1V0Q0j0WjsSU026M67zMaFrrhSKwQh-SzhmXejhKJOjhNfY9hAmeS-LsLLdszAq_JyN7fIvZl1fWDnER_CeDAbQDj5K5ECNOHAQ3RemQ2dADVlc07VEt2KpSqUlHlq3rcaIcNRHCue4GfbCc1lZwQsALbM1aSIzF68klXs1Cj_ZmXxOSOyHxwmbQCHwY7aa16f3VEJzCYa6m0m5U_oHy84iQzsC-_JvBaeFCachrLWmFY818S-nH5fCIORdYgc4s7Fj5HdULnnVwiKeQLKSaYsfneHtqwOc_ux2QYv6Cv6Xn04tkB2TEsuZ7dFwPI-Hw2O30vCzLTcZ-Fl08ER0J0hhq4ep7B641IOnPpMZ1m0gpJJRPbHX_ooqHol9zHZ0gcLKMdYy1wUgsmn_nK_THK3m0RmENXNtepyLw_tSd5vqqIWZ5NFglKSqVnbomEkxneEJRgoFhBGMZiR-3FXMaVryUjq-N.Q_t4NGxTUSMsLVEppkTu0Q6rwt2rKJfFGuvy3s12345","token_type": "Bearer","expires_in": 899,"id_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6IkNWWDU1Mi1zeWh4Y1VGdW5vNktScmtReFB1eW15YTRQVllodWdsd3hnNzgiLCJ0eXAiOiJKV11234.eyJzdWIiOiIyMDY3MjQzOTU5IiwibmFtZSI6ImxpbmtzZ29hdCIsIm5pY2tuYW1lIjoibGlua3Nnb2F0IiwicHJlZmVycmVkX3VzZXJuYW1lIjoibGlua3Nnb2F0IiwiY3JlYXRlZF9hdCI6MTYwNzM1NDIzMiwicHJvZmlsZSI6Imh0dHBzOi8vd3d3LnJvYmxveC5jb20vdXNlcnMvMjA2NzI0Mzk1OS9wcm9maWxlIiwibm9uY2UiOiIxMjM0NSIsImp0aSI6IklELnltd3ZjTUdpOVg4azkyNm9qd1I5IiwibmJmIjoxNjkxNjM5Njk4LCJleHAiOjE2OTE2NzU2OTgsImlhdCI6MTY5MTYzOTY5OCwiaXNzIjoiaHR0cHM6Ly9hcGlzLnJvYmxveC5jb20vb2F1dGgvIiwiYXVkIjoiNzI5MDYxMDM5Nzk4NzkzNDk2NCJ9.kZgCMJQGsariwCi8HqsUadUBMM8ZOmf_IPDoWyQY9gVX4Kx3PubDz-Q6MvZ9eU5spNFz0-PEH-G2WSvq2ljDyg","scope": "openid profile"}
リソースメソッドに電話をかける
必要なアクセストークンを持ったので、リソースメソッドに認証された呼び出しを行うために使用できます。アクセストークンをすべての API リクエストのヘッダに含めて、認可する。
たとえば、全体の認証フローを通過してアプリの機能が正しく機能しているかをテストし、アクセストークンで GET ユーザー情報エンドポイントにリクエストを送信して ユーザー情報をテストできます。このエンドポイントを呼び出す前に、openid または両方の openid および profile スコープがあることを確認してください。成功した場合、そのエンドポイントからの返答は次のようになります:
ユーザ情報の応答の例
{
"sub": "12345678",
"name": "Jane Doe",
"nickname": "robloxjanedoe",
"preferred_username": "robloxjanedoe",
"created_at": 1607354232,
"profile": "https://「www.roblox.com/users/12345678/profile」
}