> For the complete documentation index, see [llms.txt](https://authing.gitbook.io/authing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://authing.gitbook.io/authing/authentication/oauth2/oauth-authorization.md).

# 使用 OAuth 授权

Node.JS Demo 源码：https\://github.com/Authing/oauth-demo

## 使用 authorization\_code 模式

以下流程图列举了一种使用 OAuth 协议授权码模式的方式。

![授权码模式流程图](https://366491767-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdsKjoPVRBStTP-5zXe%2F-LjFZ71orMrFir62Nmov%2F-LjG43dLNtN7ORpo-3Au%2Fimage.png?alt=media\&token=7bee6276-05ad-46af-86f2-d54be14c200c)

### **1. 请求授权**

首先需要请求以下链接来获取 `authorization_code`

```
https://sso.authing.cn/authorize?app_id=5c7253efe21948de32723725&state=123456lkjljkf3&response_type=code&redirect_uri=https%3A%2F%2Fauthing.cn&scope=user
```

{% hint style="info" %}
此链接会重定向到 Authing 提供的认证授权页面，此时用户需要输入他的用户名密码或社会化登录手段进行登录。

> 你可以前往这个网址体验：<https://sample-sso.authing.cn/login>
> {% endhint %}

{% hint style="info" %}
请使用**浏览器**访问此链接！
{% endhint %}

#### 参数说明

| 参数             | 说明                                                                   |
| -------------- | -------------------------------------------------------------------- |
| app\_id        | 必须，创建 OAuth 应用后详情中的 `App ID`                                         |
| response\_type | 必须，授权的类型，在 `authorization_code 模式` 中值必须为 `"code"`                    |
| redirect\_uri  | 必须，授权成功后的回调地址，**必须**与控制台 **OAuth 应用配置的 `URL`** 一致，需要经过 urlencoded 编码 |
| state          | 一段随机字符串，主要用于防止跨站请求伪造攻击，它将原封不动地在 `redirect_uri` 中返回                   |
| scope          | 允许的授权的范围，暂时没有实现此字段的相关功能，可不传                                          |

### **2. 重定向并获取 `access_token`**

经过上一步之后，用户将会跳转到 Authing 提供的认证授权页面：

![](https://366491767-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdsKjoPVRBStTP-5zXe%2F-M-nASRx7eufQydto5bi%2F-M-nBZ0hwfwDgv9eztCQ%2Fimage.png?alt=media\&token=3ac39d3f-7468-4490-ad0a-7ee4594a8b7f)

当授权成功后，用户将会被重定向到以下链接：

```
{redirect_uri}?code=8cce9189ee40f6f8874a9d4618a2996ece7dd737&state=123456lkjljkf3
```

链接中带有 GET 请求参数 `code` 和 `state`。在 `redirect_uri` 的请求处理中，你应该检查 `state` 参数是否与你请求时一致，这样能确保请求不是来自第三方应用。然后，你应该使用 `POST` 请求`https://sso.authing.cn/token` 来获取 `access_token`，需要携带以下参数

| 参数                         | 说明                                                                   |
| -------------------------- | -------------------------------------------------------------------- |
| app\_id/client\_id         | 必须，创建 OAuth 应用后详情中的 `App ID`                                         |
| app\_secret/client\_secret | 必须，创建 OAuth 应用后详情中的 `App Secret`                                     |
| code                       | 必须，我们返回的 `code`                                                      |
| redirect\_uri              | 必须，授权成功后的回调地址，**必须**与控制台 **OAuth 应用配置的 `URL`** 一致，需要经过 urlencoded 编码 |
| grant\_type                | 必须，授权类型，在 `authorization_code 模式`中必须为 `"authorization_code"`         |

同时 `Content-Type` 为 `application/x-www-form-urlencoded`。

例如：

```
curl --request POST \
  --url https://sso.authing.cn/token \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data 'app_id=<APP_ID>&app_secret=<APP_SECRET>&grant_type=authorization_code&code=<CODE>&redirect_uri=<REDIRECT_URI>'    
```

返回：

```
{
  "access_token":"4331396b953d3de3bcf74c564455323d0989a9a0",
  "token_type":"Bearer",
  "expires_in":3599, // token 有效时间
  "refresh_token":"017888c6722e3433f3840a6708d9b79c23b310b8" // 可用此 token 来重新获取新的 token 而无需重新授权
}
```

### **3. 使用 `access_token` 请求 `userInfo`**

`GET https://users.authing.cn/oauth/user/userinfo?access_token=...`

或作为 `Authoriztion` 头：

`Authorization: Bearer { access_token }`

### **4. 刷新 `access_token`**

`access_token` 的有效时间只有 1 小时，`refresh_token` 的有效时间为 2 周，所以在申请 `access_token` 一小时以后，可通过 `POST` 请求`https://sso.authing.cn/token` 来重新获取 `access_token`，需要携带以下参数：

| 参数             | 说明                                          |
| -------------- | ------------------------------------------- |
| app\_id        | 必须，创建 OAuth 应用后详情中的 `App ID`                |
| app\_secret    | 必须，创建 OAuth 应用后详情中的 `App Secret`            |
| refresh\_token | 必须，之前获取 `access_token` 时返回的 `refresh_token` |
| grant\_type    | 必须，授权类型，在刷新 token 时必须为 `"refresh_token"`    |

返回的数据与第二步一样。

## implicit 模式

与 `authorization_code` 不同，`implicit 模式` 直接返回 `access_token`，少了验证 `authorization_code` 的步骤，且不能刷新 `access_token`。

下面 implicit 模式时序图中红框部分是与授权码模式不同的地方。

![implicit 模式](https://366491767-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdsKjoPVRBStTP-5zXe%2F-LjG7AIRfLA61GzDcOsQ%2F-LjG7CHFD82YAKcUFBAu%2Fimage.png?alt=media\&token=ead02ce4-091a-4284-8cf2-fa048948f71c)

### **1. 发起授权**

`https://sso.authing.cn/authorize?app_id=5c7253efe21948de32723725&state=123456lkjljkf3&response_type=token&redirect_uri=https%3A%2F%2Fauthing.cn&scope=user`

通过请求以上链接可直接获取 `access_token`。

参数说明

| 参数             | 说明                                                                   |
| -------------- | -------------------------------------------------------------------- |
| app\_id        | 必须，创建 OAuth 应用后详情中的 `App ID`                                         |
| response\_type | 必须，授权的类型，在 `implicit 模式` 中值必须为 `"token"`                             |
| redirect\_uri  | 必须，授权成功后的回调地址，**必须**与控制台 **OAuth 应用配置的 `URL`** 一致，需要经过 urlencoded 编码 |
| scope          | 允许的授权的范围，暂时没有实现此字段的相关功能，可不传                                          |

### **2. 重定向并返回 `access_token`**

`{redirect_uri}#access_token=9a617eb1dddc9fc7a480b0778173fd7f9db33938&state=123456lkjljkf3`

当授权成功后，将会重定向到如上的链接，在 `hash` 中携带 `access_token`。

### **3. 使用 `access_token` 请求 userInfo**

与 `authorization_code 模式` 的第三步一样。

`GET https://users.authing.cn/oauth/user/userinfo?access_token=...`

或作为 `Authoriztion` 头：

`Authorization: Bearer { access_token }`

## password 模式

此模式要求有用户名和密码，且必须使用 `POST` 请求

![password 模式](https://366491767-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LdsKjoPVRBStTP-5zXe%2F-LjG9r_piyo2c4Oi4sM8%2F-LjGAES0vT1dpoK10IpJ%2Fimage.png?alt=media\&token=7ed60687-8884-4bbb-91de-71c2acbbb80a)

### **1. 发起授权**

向以下这个地址发起 POST 请求：

`https://sso.authing.cn/token`

参数说明

| 参数          | 说明                                          |
| ----------- | ------------------------------------------- |
| app\_id     | 必须，创建 OAuth 应用后详情中的 `App ID`                |
| app\_secret | 必须，创建 OAuth 应用后详情中的 `App Secret`            |
| grant\_type | 必须，授权的类型，在 `password 模式` 中值必须为 `"password"` |
| username    | 必须，用户邮箱                                     |
| password    | 必须，用户密码                                     |

返回

```
{
  "access_token":"4331396b953d3de3bcf74c564455323d0989a9a0",
  "token_type":"Bearer",
  "expires_in":3599, // token 有效时间
  "refresh_token":"017888c6722e3433f3840a6708d9b79c23b310b8" // 可用此 token 来重新获取新的 token 而无需重新授权
}
```

### **2. 使用 `access_token` 请求 userInfo**

与 `authorization_code 模式` 的第三步一样。

`GET https://users.authing.cn/oauth/user/userinfo?access_token=...`

或作为 `Authoriztion` 头：

`Authorization: Bearer { access_token }`

## client\_credentials 模式

此模式用于获取对应 client 的所有用户信息，请谨慎使用，不支持刷新 token

### **1. 发起授权**

向以下这个地址发起 POST 请求：

`https://sso.authing.cn/token`

参数说明

| 参数          | 说明                                                              |
| ----------- | --------------------------------------------------------------- |
| app\_id     | 必须，创建 OAuth 应用后详情中的 `App ID`                                    |
| app\_secret | 必须，创建 OAuth 应用后详情中的 `App Secret`                                |
| grant\_type | 必须，授权的类型，在 `client_credentials 模式` 中值必须为 `"client_credentials"` |

返回

```
{
  "access_token":"4331396b953d3de3bcf74c564455323d0989a9a0",
  "token_type":"Bearer",
  "expires_in":3599, // token 有效时间
}
```

### **2. 使用 `access_token` 请求 userInfo**

与 `authorization_code 模式` 的第三步一样。

`GET https://users.authing.cn/oauth/user/userinfo?access_token=...`

或作为 `Authoriztion` 头：

`Authorization: Bearer { access_token }`

## **常见问题**

### **验证 access\_token 的 URL 地址**

## &#x20;验证 access\_token

<mark style="color:blue;">`GET`</mark> `https://sso.authing.cn/authenticate?access_token=`

#### Path Parameters

| Name          | Type   | Description      |
| ------------- | ------ | ---------------- |
| access\_token | string | access\_token 的值 |

{% tabs %}
{% tab title="200 " %}

```
{
  "state": 1,
  "isRevoked": false,
  "isDeleted": false,
  "_id": "5d60efdee3faa629cccc0dee",
  "id": "5d60efdee3faa629cccc0dee",
  "accessToken": "db8abb9e16de36f52da082a6dc9f20c378301fc8",
  "accessTokenExpiresAt": "2019-08-24T09:05:50.201Z",
  "scope": "user",
  "grantType": "implicit",
  "appId": "5d60e64f62554964c85b555e",
  "userOrClientId": "5cbecd1daee8f920472cb40a",
  "when": "2019-08-24T08:05:50.201Z",
  "iss": "https://sso.authing.cn",
  "sub": "5d60efdee3faa629cccc0dee",
  "aud": "5d60e64f62554964c85b555e",
  "exp": 1566637550201,
  "iat": 1566633950201,
  "user_id": "5d60efdee3faa629cccc0dee",
  "issued_to": "https://sso.authing.cn",
  "audience": "5d60e64f62554964c85b555e",
  "expires_in": 3360,
  "access_type": "offline"
}
```

{% endtab %}
{% endtabs %}

### **Token 有效时间**

> 所有模式的 `access_token` 有效时间都是 1 小时，能够使用 `refresh_token` 的模式中的 `refresh_token` 的有效时间为 2 周。

### **四种模式的区别**

> 关于这四种模式的应用场景和区别，建议浏览 [理解 OAuth2.0](http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html)，一般情况下只需开启 `authorization_code` 模式。
