技能授权

优质
小牛编辑
133浏览
2023-12-01

1.1. 符合 RFC6749 的 OAuth2.0

若琪智能家居技能授权支持符合 RFC6749 的 OAuth2.0 授权方式,目前只支持 AuthorizationCode Flow。

 +----------+
 | Resource |
 |   Owner  |
 |          |
 +----------+
      ^
      |
     (B)
 +----|-----+          Client Identifier      +---------------+
 |         -+----(A)-- & Redirection URI ---->|               |
 |  User-   |                                 | Authorization |
 |  Agent  -+----(B)-- User authenticates --->|     Server    |
 |          |                                 |               |
 |         -+----(C)-- Authorization Code ---<|               |
 +-|----|---+                                 +---------------+
   |    |                                         ^      v
  (A)  (C)                                        |      |
   |    |                                         |      |
   ^    v                                         |      |
 +---------+                                      |      |
 |         |>---(D)-- Authorization Code ---------'      |
 |  Client |          & Redirection URI                  |
 |         |                                             |
 |         |<---(E)----- Access Token -------------------'
 +---------+       (w/ Optional Refresh Token)

上面这个图中的步骤解释:

(A) 客户端通过重定向用户的浏览器到授权页面启动授权流程。客户端会提供它的 client id,请求的授权范围,客户端状态码,和一个授权服务器会在授权完成后将浏览器重定向至URI。

(B) 授权服务器认证了用户之后,确认用户确实授权了这个客户端的访问请求。

(C) 假设用户授权了访问请求,授权服务器将浏览器重定向到之前的回调 URI,回调的 URI 包含一个授权码和之前客户端提供的本地状态码。

(D) 客户端通过在前一个步骤中获得的授权码从授权服务器请求 AccessToken。发起请求时,客户端会使用预定的认证方式认证客户端的身份,并提供获取授权码的回调 URI 作为验证。

(E) 授权服务器认证客户端,并验证授权码,保证回调 URI 与步骤 (C) 中获取授权码的回调 URI 相同。如果合法,授权服务器将一个 AccessToken 和一个可选的 RefreshToken 返回给客户端。

1.2. 基本接口

接入 OAuth2.0 需要实现两个接口:

1.3. AuthorizationCode 颁发

智能家居 Skill 需要提供 Authorization 页面供用户授权若琪使用他们的设备。若琪会构建一个在 Query 结构中包含以下参数的 URI,然后将用户重定向至这个授权页面:

  • response_type: 值为 code
  • client_id: 若琪所使用的标识
  • redirect_uri: 回调地址https://homebase.rokid.com/oauth/callback
  • scope: 授权的范围
  • state: 用来保持授权请求和授权回调状态的值,当授权完成后需要将这个参数附加在回调里。

举个例子,若琪 App 会将用户的浏览器定向到下面这个 URL 上,

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

授权服务需要校验这个请求的参数是否合法的。如果是合法的请求,则授权服务需要对用户进行认证并获得用户的授权许可。 获得了用户的授权许可后,授权服务需要将用户使用 HTTP 重定向至指定的回调 URI。

1.4. Authorization Response

在获得了用户的授权后,授权服务需要颁发一个授权代码并使用包含以下参数的重定向 URI 将参数传递至若琪服务。

  • code: 必须,一个由授权服务颁发的授权代码。推荐最长只有 10 分钟的寿命,并且不能使用多次。
  • state: 必须,授权请求中的 state 参数

举个例子,授权服务将客户端重定向至以下地址:

HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA
          &state=xyz

1.5. AccessToken 接口

若琪服务会使用在请求体中包含以下参数的 HTTP 请求至 Token Endpoint 获取 AccessToken:

  • grant_type: 必须,值为 authorization_code,如果是刷新 Token 则为 refresh_token
  • code: 如果是通过 authorization_code 获取 access token 则为必须,授权过程中颁发的授权代码
  • refresh_token: 如果是通过 refresh_token 获取 access token 则为必须,同 access token 一起获得的 refresh token
  • client_id: 必须,若琪所使用的标识
  • client_secret: 可选,如果使用 HTTP Basic Auth 则该参数会包含在 HTTP Authorization Header 中

举个例子,若琪在获得了授权代码后,会使用以下 HTTP 请求获取 AccessToken:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

1.6. AccessToken Response

  • access_token: 必须,由授权服务颁发的 access token
  • expires_in: 可选,AccessToken 的寿命,以秒为单位,如果 access_token 会过期则应该必须提供
  • refresh_token: 可选,用来通过以 refresh_tokengrant_type 请求 AccessToken 接口获取新的 AccessToken 的 token

一个成功的返回例子:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "example_parameter": "example_value"
}

1.7. 预注册参数


参数名类型注释
authorizationEndpointURL授权地址
tokenEndpointURL获取 token 的地址
clientIdstring代表若琪的 id
clientSecretstring获取 token 时的密钥
scopestring授权时申请的权限范围
clientAuthTypeenum: 'basic-auth', 'body'clientSecret 需要以哪种方式提供给授权服务

1.8. 其他授权方式

如果通过「语控引擎接入」,授权部分无需通过 OAuth 2.0 协议,请参考:基于 JWT 签名的服务端授权