本文介绍桌面和移动端的Native应用如何通过OAuth 2.0扮演登录用户访问阿里云API。
前提条件
Native应用扮演登录用户访问阿里云首先需要创建应用,为应用提供恰当的名称、OAuth范围、回调地址等关键信息。详情请参见创建应用。由于Native应用运行在非可信环境,无法有效保护应用密钥,因此Native应用不使用应用密钥。
应用创建成功之后,可以在云账号内直接扮演用户。
基本流程

用户通过浏览器登录Native应用。
Native应用重定向到阿里云OAuth 2.0服务并将URL返回给浏览器。
说明如果用户还未登录,则会进一步重定向到阿里云登录服务。
用户通过浏览器登录阿里云OAuth 2.0服务并申请授权码。
阿里云OAuth 2.0服务重定向到Native应用并返回授权码给浏览器。
浏览器通过Native应用使用授权码向阿里云OAuth 2.0服务申请代表用户身份的令牌。
阿里云OAuth 2.0服务向Native应用返回令牌。
Native应用通过获取的令牌向阿里云发起访问API的请求。
说明由于令牌可以代表用户身份,因此应用可以访问当前用户的资源。
Proof Key机制的原理
Native应用支持Proof Key机制,用于每次获取授权码以及用授权码换取访问令牌。
这一机制可以减轻针对授权码截获的攻击。
Native应用生成:
code_verifier,并保存好这个随机字符串。说明code_verifier是一个高熵值的随机字符串,其取值为:[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~",长度限制为:43~128个字符。应用根据
transform的方式选择生成code_challenge。应用在申请授权码的同时提交:code_challenge以及生成code_challenge的方式。code_challenge = transform(code_verifier, [Plain|S256])方式
取值
plain如果
transform的方式选择为plain,那么code_challenge与code_verifier的值相同。S256如果
transform的方式选择为S256,那么code_challenge等于code_verifier的SHA256哈希值。code_challenge=BASE64URL-Encode(SHA256(ASCII(code_verifier)))说明哈希算法的输入为
code_verifier的ASCII编码串,哈希算法的输出字符串需要进行BASE64-URL编码。code_challenge选择方式计算示例:如果应用采用方式为S256,生成
code_verifier的值为dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk,那么code_challenge为E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM。应用获取授权码后,在使用授权码换取访问令牌时,服务端通过计算判断是否颁发令牌。
授权码需包括
code_verifier,服务端按照应用选择的transform方式对code_verifier进行计算,将结果与code_challenge进行对比,如果一致则颁发访问令牌。
获取访问令牌
步骤一:Native应用通过浏览器将用户重定向到阿里云OAuth 2.0服务从而获取授权码。
授权码的请求地址:https://signin.aliyun.com/oauth2/v1/auth。
参数名称 | 是否必选 | 描述 |
client_id | 是 | 应用的身份ID。 |
redirect_uri | 是 | 创建应用的重定向URI之一。 |
response_type | 是 | 返回类型。根据OAuth 2.0协议,目前支持设置此参数的取值为code。 |
scope | 否 | 空格分隔的OAuth范围列表。如不指定此参数取值,则默认为应用的全部OAuth范围。 |
state | 否 | 应用通过state参数实现多种目的,例如:状态保持、作为nonce使用从而减少CSRF威胁等。state如果设置为任意字符串,阿里云OAuth 2.0服务会将请求中的state参数以及取值原样放到返回参数中以供后续使用。 |
code_challenge_method | 否 | 如果不指定此参数,则默认取值为plain。 |
code_challenge | 否 | 根据客户端指定的code_challenge_method,对随机生成的code_verifier进行转换和编码,转换的结果作为code_challenge参数的值在授权码请求中使用。 说明 如果不指定此参数,则无法使用Proof Key机制,在使用授权码换取令牌时也不需要指定相应的code_verifier,若授权码被截获可以直接被用于换取访问令牌。 |
prompt | 否 | 该参数用于指定服务器是否需要提示用户进行授权操作。 如果指定,会强制要求用户进行授权,即使该阿里云账号已经做过授权,也需要重新授权。如果不指定,则只在该阿里云账号第一次使用该应用时要求授权。 取值: |
请求示例
https://signin.aliyun.com/oauth2/v1/auth?
client_id=98989****
&redirect_uri=meeting%3A%2F%2Fauthorize%2F
&response_type=code
&scope=openid%20%2Fworksuite%2Fuseraccess
&state=123456****
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSst****
&code_challenge_method=S256返回参数
参数名称 | 描述 |
code | 授权码。 用来申请代表用户身份的令牌。 |
state | 请求参数中state的数值。 |
返回示例
GET HTTP/1.1 302 Found
Location: meeting://authorize/?code=ABAFDGDFXYZW888&state=123456**** 步骤二:Native应用使用授权码向阿里云OAuth 2.0服务申请代表用户身份的令牌。
换取访问令牌的请求地址:https://oauth.aliyun.com/v1/token。
参数名称 | 是否必选 | 描述 |
code | 是 | 步骤一请求返回值中的授权码。 |
client_id | 是 | 应用的身份ID。 |
redirect_uri | 是 | 重定向URL,需填入获取授权码(步骤一)请求中设置的参数。 |
grant_type | 是 | 根据OAuth 2.0协议, 取值为authorization_code。 |
code_verifier | 否 | 初始请求中生成的code_verifier,对应于授权码请求中的code_challenge参数。 |
请求示例
POST /v1/token HTTP/1.1
Host: oauth.aliyun.com
Content-Type: application/x-www-form-urlencoded
code=ABAFDGDFXYZW888&
client_id=98989****
redirect_uri=meeting://authorize/&
grant_type=authorization_code&
code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk 参数名称 | 描述 |
access_token | 访问令牌。访问令牌可以代表用户身份,应用使用此访问令牌来访问阿里云API。应用不需要理解访问令牌的含义,直接使用即可。 |
expires_in | 访问令牌的剩余有效时间,单位为秒。 |
token_type | 访问令牌的类型。取值为Bearer。 |
id_token | 身份令牌。id_token为OAuth签名的JWT(JSON Web Token)。如果初始请求的scope参数包含了openid,则返回身份令牌。 |
refresh_token | 刷新令牌。此参数可以直接使用,Native应用不需要指定访问令牌的值,可以直接获得刷新令牌。 |
返回示例
{
"access_token": "eyJraWQiOiJrMTIzNCIsImVuYyI6****",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "Ccx63VVeTn2dxV7ovXXfLtAqLLERA****",
"id_token": "eyJhbGciOiJIUzI1****"
} 获取新的访问令牌
换取访问令牌的请求地址:https://oauth.aliyun.com/v1/token。
参数名称 | 是否必选 | 描述 |
refresh_token | 是 | 用授权码换取访问令牌时获得的刷新令牌。 |
client_id | 是 | 应用的身份ID。 |
grant_type | 是 | 根据OAuth 2.0协议,取值为refresh_token。 |
请求示例
POST /v1/token HTTP/1.1
Host: oauth.aliyun.com
Content-Type: application/x-www-form-urlencoded
refresh_token=Ccx63VVeTn2dxV7ovXXfLtAqLLERAH****
client_id=98989****
grant_type=refresh_token参数名称 | 描述 |
access_token | 新的访问令牌。应用使用新的访问令牌来访问阿里云API。 |
expires_in | 访问令牌的剩余有效时间,单位为秒。 |
token_type | 访问令牌的类型。取值为Bearer。 |
返回示例
{
"access_token": "eyJraWQiOiJrMTIzNCIsImVuYyI6****",
"token_type": "Bearer",
"expires_in": 3600,
} 本次请求的返回值与用授权码换取访问令牌的返回值一致,但不包含refresh_token和id_token。
撤销刷新令牌
Native应用获取了刷新令牌后,在用户退出登录应用时或用户将自己的账号从应用中移除时,必须撤销刷新令牌。
撤销刷新令牌的请求地址:https://oauth.aliyun.com/v1/revoke。
参数名称 | 是否必选 | 描述 |
token | 是 | 需要撤销的刷新令牌。 |
client_id | 是 | 应用的身份ID。 |