Open Cloud 支持有无 PKCE 的 OAuth 2.0 授权流程,具体取决于您的客户端是机密类型还是公共类型。
- 机密客户端 是能够保持凭据机密的应用程序,例如能够在其后端安全存储和检索机密的网页。
- 公共客户端 是无法保持机密的应用程序,例如移动应用和网页浏览器应用。
我们建议对 所有 客户端使用带 PKCE 的 OAuth 2.0 授权码流程,并要求公共客户端使用它。
要实现授权码流程,您的应用程序执行以下步骤:
- 生成一个代码验证器和代码挑战(仅限 PKCE)。这使您能够在请求中包含挑战,而不是客户端密钥,从而提高安全性。
- 向授权端点发送包含适当参数的 GET 请求。
- 处理授权回调。在获得授权后,使用 Roblox 提供的授权码发送重定向请求到您在应用创建期间指定的 URL。解析授权码以供后续使用。
- 向令牌端点发送包含授权码的 POST 请求。如果成功,您将收到访问令牌和刷新令牌,以便进行 API 调用。
- 根据您想要访问的资源的参考文档,调用任何支持 OAuth 2.0 身份验证的 Open Cloud API。
以下部分对每一步进行更深入的描述。
生成代码挑战(仅限 PKCE)
在启动授权过程之前,您需要从代码验证器生成一个代码挑战。您可以使用库或所选编程语言中的内置函数来创建代码验证器,计算哈希,并执行 Base64 编码以生成代码挑战。
在创建代码验证器时,仅使用未保留的字符,包括大写和小写字母(A-Z,a-z)、十进制数字(0-9)、连字符(-)、句点(.)、下划线(_)和波浪号(~),最小长度为 43 个字符,最大长度为 128 个字符。
以下示例展示了如何使用 Javascript 创建代码验证器并使用 SHA-256 哈希算法生成代码挑战:
生成代码挑战
const crypto = require('crypto');
// base64URL 编码验证器和挑战
function base64URLEncode(str) {
return str.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
// 从代码验证器创建 sha256 哈希
function sha256(buffer) {
return crypto.createHash('sha256').update(buffer).digest(`base64`);
}
// 创建随机代码验证器
var code_verifier = base64URLEncode(crypto.randomBytes(32));
// 从代码验证器生成挑战
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 所需
- client_secret:在 注册您的应用程序 后获得的应用程序客户端密钥。如果您使用带有 PKCE 的身份验证,则省略此参数。 您的授权请求 URL 必须格式良好,如以下示例所示:
示例 PKCE 授权 URLhttps://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。
处理授权回调
当授权流程成功时,您的应用程序会从 Roblox 授权服务器接收到一个 GET 请求,地址为您指定的 redirect_uri。在请求中,您会接收到 code(授权码)和 state(如果您之前提供了值)参数。
code 参数包含一个授权码,应用程序可以用它向授权服务器兑换访问令牌。大多数后端服务器语言都有标准方法来访问查询参数作为解码对象。您需要获取 code 参数并用它来兑换访问令牌。
state 参数是您在授权请求中最初提供的一个不透明值。您可以使用此参数来保持授权过程的状态或上下文。
例如,如果您指定的重定向 URI 为 https://example.com/redirect,您可能会收到一个包含以下 URL 的 GET 请求。
示例重定向 URLhttps://example.com/redirect?code=10c45PNuquKnFJ6pUcy5-fHkghEM6lSegm-7hj9mVEprub1dSDuStuKK_EAUXY7AHTD63xcnmvxSLthp-C8g3jzIGZVzuXSd20Y2dEYI9hx0LZmPg95ME4z2K03UheiZbroyXUjYyB3ReoMqobzDVPzyx6IS8kj2Uu-11Xq_0JiTYxtDatuqXRNIAmJT8gMJmbSyOLOP_vnDvbeMUiBsqCRrkTGVbWSwYSc8sTVVE-535kYdqQOgNjH1ffCoZLGl8YYxLnpb2CXJlRQPrcjkA&state=6789
如果授权失败,您的应用程序会收到一个 GET 请求,地址为指定的重定向 URL,参数包括 error、error_description 和 state(如适用)。
- error 参数指示在授权过程中发生的特定 OAuth 2.0 错误。
- error_description 参数提供错误的其他详细信息。
- state 参数帮助您的应用程序在失败情况下保持状态。
用授权码兑换访问令牌
当您解析完授权 code 后,用它兑换访问令牌,以访问所需的 Roblox 资源:
通过向 令牌交换端点 发送 POST 请求来请求访问令牌和刷新令牌。请求必须包含授权码、客户端 ID 和代码验证器值(PKCE)或客户端密钥(非 PKCE),格式为 x-www-form-urlencoded。
从接收到的响应中解析适用的令牌。访问令牌有效期为 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.eyJzdWIiOiIyMDY3MjQzOTU5IiwibmFtZSI6ImxpbmtzZ29hdCIsIm5pZ2tuYW1lIjoibGlua3Nnb2F0IiwicHJlZmVycmVkX3VzZXJuYW1lIjoibGlua3Nnb2F0IiwiY3JlYXRlZF9hdCI6MTYwNzM1NDIzMiwicHJvZmlsZSI6Imh0dHBzOi8vd3d3LnJvYmxveC5jb20vdXNlcnMvMjA2NzI0Mzk1OS9wcm9maWxlIiwibm9uY2UiOiIxMjM0NSIsImp0aSI6IklELnltd3ZjTUdpOVg4azkyNm9qd1I5IiwibmJmIjoxNjkxNjM5Njk4LCJleHAiOjE2OTE2NzU2OTgsImlhdCI6MTY5MTYzOTY5OCwiaXNzIjoiaHR0cHM6Ly9hcGlzLnJvYmxveC5jb20vb2F1dGgvIiwiYXVkIjoiNzI5MDYxMDM5Nzk4NzkzNDk2NCJ9.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"
}