一、 前言
最近公司在做 tiktok 授权登录的需求, 其实对前端来说。这个活儿非常简单, 点一下按钮,调一下接口,剩下的都是后端干了,经常不知道里面的具体实现细节与原理,而且面试如果能把这里业务讲明白也是很加分的点, 对于我们自己来说也是很有意思的一件事, 所以在评审前,我就先一步用node将后端的这块逻辑给他掉通了,等他在开发的时候就可以来问我了
效果如下:

二、文档
因为tiktok在国内的使用是受限制的, 所以需要使用科学上网工具, 有需要的可以滴滴我, 然后最重要的就是看文档, 纯英文文档看着还是很容易犯困的, 可以下载一个 DeepL 的翻译浏览器插件, 还是非常好用, 点击链接查看文档
三、步骤
写代码之前先要搞明白我们要干的事。 以及步骤, 其实类似这种授权的,基本都是一个套路, 大致分为以下几个步骤
- 开发者平台上创建账号,获取 key 密钥 填写授权时候的一些信息与授权成功的回调地址
- 通过 key等参数 重定向到授权页面, 获取到授权成功的 code 等信息
- 通过 拿到的 code 等调用 token 接口登录, 获取到 access_token, access_token 非常重要,成功获取到 access_token 后,就有权限去调用后面接口了
- 我们调用一个 用户信息接口, 测试一下是否调用成功
四、代码


写代码前先在平台上新建 app manage 后面会用到, 注意回调地址 必须是 https 的地址, 拿到授权成功的 code 后会跳到这个回调到 https://kalodata.com/tiktok/ 这个地址,并且在地址上携带
新建一个express node 应用
js
npm init -y
npm i express node-fetch cookie-parser cors body-parser -S
基本框架如下:
js
const express = require("express");
const app = express();
const fetch = require("node-fetch");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const bodyParser = require("body-parser");
app.use(cookieParser());
app.use(cors());
app.listen(process.env.PORT || 5001);
app.use(bodyParser.urlencoded({ extended: true }));
const CLIENT_KEY = "zxxxxxxx";
const CLIENT_SECRET = "ddddddddd";
const SERVER_ENDPOINT_REDIRECT = "回调地址";
// 1、通过令牌获取 code
app.get("/oauth", (req, res) => {
//...
});
// 2、通过 code 去获取 access_token Fetch an access token using an authorization code
app.get("/tiktok", (req, res) => {
const { code, scopes, state } = req.query;
//...
});
// 3、通过access_token 获取用户信息
const getUserInfo = async (access_token) => {
//...
};
1. 通过令牌获取 code
js
app.get("/oauth", (req, res) => {
const csrfState = Math.random().toString(36).substring(2);
res.cookie("csrfState", csrfState, { maxAge: 60000 });
let url = "https://www.tiktok.com/v2/auth/authorize/";
// the following params need to be in `application/x-www-form-urlencoded` format.
url += `?client_key=${CLIENT_KEY}`;
url += "&scope=user.info.basic";
url += "&response_type=code";
url += `&redirect_uri=${SERVER_ENDPOINT_REDIRECT}`;
url += "&state=" + csrfState;
res.redirect(url);
});
打开浏览器输入 http://localhost:5001/oauth 调用这个接口时, 浏览器会进行重定向调转请求 https://www.tiktok.com/v2/auth/authorize/ 参数类型是application/x-www-form-urlencoded 格式, 需要注意的是 此授权接口,与下一个获取access_token接口需要保证一致。为了安全防止拦截误导, 需要增加一个 csrfState 校验, 通过state参数传递, 并在传递到的下一个接口内验证是否一致
2、通过 code 获取 access_token
js
const { code, scopes, state } = req.query;
let url = "https://open.tiktokapis.com/v2/oauth/token/";
const formData = new URLSearchParams();
formData.append("client_key", CLIENT_KEY);
formData.append("client_secret", CLIENT_SECRET);
formData.append("code", code);
formData.append("grant_type", "authorization_code");
formData.append("redirect_uri", SERVER_ENDPOINT_REDIRECT);
// data.append('code_verifier', 'Required for mobile app only'); APP 端使用
fetch(url, {
method: "POST",
body: formData.toString(),
headers: { "Content-Type": "application/x-www-form-urlencoded" },
})
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error("POST request failed");
})
.then(async (responseData) => {
if (responseData.access_token) {
console.log(responseData.access_token) // 获取到 access_token
}
})
.catch((error) => {
console.error(error);
});
这里需要注意回调回来的是线上地址, 需要手动将地址的 host 改成本地, localhost:5001/tiktok?code=xxx 在这个路由拿到回调回来的code 等参数, 可以在此验证 csrfstate, 调用 https://open.tiktokapis.com/v2/oauth/token/ 接口,构造 application/x-www-form-urlencoded 类型的参数进行请求,即可拿到 access_token
3、获取用户信息
获取用户信息有新旧两个版本, 我用的是 v2 的版本。这个地方需要注意的点还是比较多的,首先这个接口基于 OAuth 2.0 规范中的 Bearer Token 的授权类型, 其次请求成功后,得到的结果是一个 Gunzip 类型的压缩类型, 开始想通过解压没有发现很好的方式, 然后搜索时发现只需要 转化成 res.text() 即可, 解决链接
js
const getUserInfo = async (access_token) => {
const bearer_access_token = `Bearer ${access_token}`;
let url = `https://open.tiktokapis.com/v2/user/info/?fields=avatar_url,union_id,open_id,display_name`;
return fetch(url, {
method: "GET",
headers: {
Authorization: bearer_access_token,
},
})
.then((res) => res.text())
.catch((error) => {
console.log(error, "error");
});
};
五、总结
本文主要讲了实现tiktok登录授权的思路与接口的一些注意的点, 各种平台的授权机制都大体类似, 可以说一通百通, 很多时候作为前端我们是不会涉及到这些内容, 但是对于想要了解这里面的原理,又是绕不开点, 授权大体上经过两个步骤, 通过key 换 code, 通过 code 换取 access_token, 因为access_token 非常重要而且有有效期, 为了增加安全性和用户体验, 经常需要使用 refresh_token 去更新 access_token, refresh_token 一般拥有更长的有效期, 可以在 access_token 过期时自动更新, 既避免了用户频繁进行身份验证,又提高了系统的可用性和用户体验
tip: 直接拉长access_token 可以吗? 答: 是一种方式,但是不是最佳实践,会产生三个问题, 1、有效期延长意味着令牌存在更长的时间窗口用于滥用、泄漏、或被攻击者滥用 2、撤销和失效问题: 撤销权限或者设备丢失,想让access_token立刻失效将变得困难,并且用户权限更新等问题和反馈等问题将没有那么及时