跳转至

使用 Account Management API 手动关联 OAuth 提供方

Management API 提供了一种方式,让您能用自己的自定义界面来完成通常需要通过默认 /settings 页面才能完成的操作。

用于 OAuth 提供方的 Account Management API

用于 OAuth 提供方的 account management API 允许开发者编写自己的自定义代码,把社交或企业(OAuth)提供方关联到自己 Authany 项目下的用户账号上。开发者可以使用这个 API 创建自定义界面,让用户用它把一个或多个社交登录提供方关联到自己的账号。

用于 OAuth 提供方的 account management API 有 2 个端点,您的代码必须向它们发起 HTTP(s) POST 请求。以下是这两个端点的详细说明:

1. /api/v1/account/identification

使用这个端点发起把 OAuth 提供方关联到账号的流程。该端点要求在 Bearer Authorization 头中提供当前用户的有效访问令牌。

请求方法:

POST

请求头:

{
    "Authorization": "Bearer " + <ACCESS_TOKEN>
}

请求体:

{
    "identification": "oauth",
    "alias": "google",
    "redirect_uri": "http://localhost:3000/linkcallback",
    "exclude_state_in_authorization_url": false
}
  • identification:必填。值必须为 oauth。
  • alias:必填。您希望当前账号关联的 OAuth 提供方的别名。
  • redirect_uri:必填。您需要指定自己应用或网站的重定向 URI,用于接收 OAuth 回调。
  • exclude_state_in_authorization_url:可选。默认值为 false。当为 false 时,authorization_url 中会包含 state 参数,令牌会与该 state 参数绑定。当为 true 时,authorization_url 中不包含 state 参数,令牌不会与 state 绑定。如果您希望使用自己的 state,必须将该字段设为 true。

响应:

{
  "result": {
    "token": "oauthtoken_abc123xyz",
    "authorization_url": "https://www.google.com?client_id=client_id&redirect_uri=redirect_uri"
  }
}
  • token:您需要存储这个令牌。当终端用户返回您的应用后,需要提供这个令牌。
  • authorization_url:您必须把终端用户重定向到这个 URL,以继续授权码流程。如果 exclude_state_in_authorization_url 为 false,该 URL 中会包含 state 参数。

2. /api/v1/account/identification/oauth

从您的重定向 URI 调用这个端点,以完成关联 OAuth 提供方的流程。

请求方法:

POST

请求头:

{
    "Authorization": "Bearer " + <ACCESS_TOKEN>
}

请求体:

{
    "token": <TOKEN>,
    "query": <URL_QUERY>
}

响应:

{"result":{}}

在这个示例中,我们将以 Google 作为 OAuth 提供方进行关联。

步骤 1:用户登录(获取访问令牌)

account management API 需要用户有效的访问令牌才能工作。因此,您必须先对用户进行一次身份验证。

设置您的应用,让用户可以使用 Authany 登录并获取访问令牌。

有关您所使用的编程语言或框架的详细指南,请参见我们的开始使用部分。

现在您的应用已经能为用户获取有效的访问令牌,接下来您将向 /api/v1/account/identification 端点发起 HTTP(s) 请求,以发起 OAuth 提供方关联流程。

使用以下代码发送 HTTP(s) 请求:

app.get("/link", async (req, res) => {
    const endpoint = `<YOUR_AUTHGEAR_ENDPOINT>/api/v1/account/identification`;
    const accessToken = req.session.accessToken; //TODO Get access token for user here. The example retrieves the value stored in session cookies

    try {

        const initiateAccountLink = await axios.post(endpoint, 
        {
            "identification": "oauth",
            "alias": "google",
            "redirect_uri": `http://localhost:3000/linkcallback`,
            "exclude_state_in_authorization_url": false
        }, {
            headers: { "Authorization": "Bearer " + accessToken }
        });
        req.session.token = initiateAccountLink.data.result.token;

        res.send("linking initiated!"); // TODO Replace this link with Login with provider link instead
    } catch(error) {
        let errorInfo = error;
        if (error.response) {
            errorInfo = error.response.data;
        }
        res.send("An error occurred " + JSON.stringify(errorInfo));
    }

});

在上面的代码中,HTTP(S) 请求体中的 identification 类型为 oauth,因为我们要把一个新的 OAuth 提供方添加为用户账号的一个身份。alias 的值为 google,因为要添加的 OAuth 提供方是 Google。

redirect_uri 中的链接是示例应用中的一个页面,用于处理来自 OAuth 提供方的回调。我们将在下一步实现这个页面。

/api/v1/account/identification 端点的响应应如下所示:

{
  "result": {
    "token": "oauthtoken_abc123xyz",
    "authorization_url": "https://www.google.com?client_id=client_id&redirect_uri=redirect_uri"
  }
}

步骤 3:获取 OAuth 提供方的授权 URL

步骤 2 中 HTTP(s) 请求的响应包含一个 authorization_url 字段。该字段包含 OAuth 提供方的授权 URL。您的应用可以把用户重定向到 authorization_url,让他们在 OAuth 提供方的网站上完成授权。

用以下代码替换步骤 2 中写有 // TODO 的那一行,将 authorization_url 的值用在一个用户可以点击的超链接中:

res.send(`
    <a href="${initiateAccountLink.data.result.authorization_url}">Link Google Account</a>
    `);

步骤 4:完成账号关联

关联 OAuth 提供方的最后一步,是实现 OAuth 提供方在授权完成后会把用户重定向回去的那个回调 URL。您的应用将在这里向第二个端点(/api/v1/account/identification/oauth)发起 HTTP(S) 请求。

在这个示例中,我们将创建一个 "/linkcallback" 路由,用以下代码处理这个重定向:

app.get('/linkcallback', async (req, res) => {
    const endpoint = `<YOUR_AUTHGEAR_ENDPOINT>/api/v1/account/identification/oauth`;
    const accessToken = req.session.accessToken;
    const currentUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
    const queryParams = new URL(currentUrl).search;;

    try {
        const finishLink = await axios.post(endpoint, {
            "token": req.session.token,
            "query": queryParams,
        }, 
        {
            headers: { "Authorization": "Bearer " + accessToken }
        });

        res.send(JSON.stringify(finishLink.data));
    } catch(error) {
        let errorInfo = error;
        if (error.response) {
            errorInfo = error.response.data;
        }
        res.send("An error occurred " + JSON.stringify(errorInfo));
    }

});

以上代码把 token(上一次 HTTP(S) 请求响应中返回的值)以及 OAuth 提供方添加到重定向 URI 中的 query 参数,一起放在一个 HTTP(S) 请求中发送给完成端点。这两个参数都是必填的。

当 OAuth 提供方成功关联后,该端点的响应将如下所示:

{"result":{}}