Javascript
集成 Authok
安装依赖
# npm
npm i --save @authok/authok-spa-js
# yarn
yarn add @authok/authok-spa-js
Authok SPA SDK 安装后, 在应用入口导入:
import createAuthokClient from '@authok/authok-spa-js';
通过 CDN 引入
<script src="https://cdn.authok.cn/js/authok-spa-js/1.19.7/authok-spa-js.production.js"></script>
创建 JavaScript 应用
创建基础 HTML页面
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>SPA SDK 示范</title>
<link rel="stylesheet" type="text/css" href="/css/main.css" />
</head>
<body>
<h2>SPA 认证示范</h2>
<p>欢迎!</p>
<button id="btn-login" disabled="true" onclick="login()">登录</button>
<button id="btn-logout" disabled="true" onclick="logout()">退登</button>
</body>
</html>
应用目录结构
.
├── index.html
├── auth_config.json
└── public
├── css
│ └── main.css
└── js
└── app.js
引入SDK
在 body
底部引入.
index.html
<body>
<!-- other HTML -->
<!-- add the lines below existing code -->
<script src="https://cdn.authok.cn/js/authok-spa-js/1.19.7/authok-spa-js.production.js"></script>
<script src="js/app.js"></script>
</body>
配置
auth_config.json
{
"domain": "YOUR_DOMAIN",
"clientId": "YOUR_CLIENT_ID"
}
创建Server
npm init -y
安装依赖
npm i express
安装 nodemon
以便修改代码后马上热更新:
npm i -D nodemon
打开 package.json
文件进行修改:
package.json
{
// ...
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
// ...
}
npm start
会正常启动应用npm run dev
会使用nodemon
启动应用, 此时会监听文件变化.
创建 server.js
server.js
const express = require("express");
const { join } = require("path");
const app = express();
// Serve static assets from the /public folder
app.use(express.static(join(__dirname, "public")));
// Endpoint to serve the configuration file
app.get("/auth_config.json", (req, res) => {
res.sendFile(join(__dirname, "auth_config.json"));
});
// Serve the index page for all other requests
app.get("/*", (_, res) => {
res.sendFile(join(__dirname, "index.html"));
});
// Listen on port 3000
app.listen(3000, () => console.log("Application running on port 3000"));
初始化SDK
public/js/app.js
let authok = null;
const fetchAuthConfig = () => fetch("/auth_config.json");
// ..
const configureClient = async () => {
const response = await fetchAuthConfig();
const config = await response.json();
authok = await createAuthokClient({
domain: config.domain,
client_id: config.clientId
});
};
添加一个 window.onload
回调用于初始化应用:
public/js/app.js
// ..
window.onload = async () => {
await configureClient();
// 更新UI状态
updateUI();
}
const updateUI = async () => {
const isAuthenticated = await authok.isAuthenticated();
document.getElementById("btn-logout").disabled = !isAuthenticated;
document.getElementById("btn-login").disabled = isAuthenticated;
};
登录
public/js/app.js
// ..
const login = async () => {
await authok.loginWithRedirect({
redirect_uri: window.location.origin
});
};
更新 app.js
的 window.onload
函数:
public/js/app.js
// ..
window.onload = async () => {
// ..
updateUI();
const isAuthenticated = await authok.isAuthenticated();
if (isAuthenticated) {
return;
}
// NEW - 检查 code 和 state 参数
const query = window.location.search;
if (query.includes("code=") && query.includes("state=")) {
// 处理登录状态
await authok.handleRedirectCallback();
updateUI();
// 使用 replaceState 方法进行重定向 并移除 查询参数
window.history.replaceState({}, document.title, "/");
}
};
// ..
退登
public/js/app.js
const logout = () => {
authok.logout({
returnTo: window.location.origin
});
};
读取用户信息
index.html
<body>
<!-- ... -->
<div class="hidden" id="gated-content">
<p>
<strong>您已已登录</strong>.
</p>
<label>
Access token:
<pre id="ipt-access-token"></pre>
</label>
<label>
用户信息:
<pre id="ipt-user-profile"></pre>
</label>
</div>
<!-- .. existing script tags .. -->
</body>
修改 app.js
文件的 updateUI() 方法:
public/js/app.js
// ...
const updateUI = async () => {
const isAuthenticated = await authok.isAuthenticated();
document.getElementById("btn-logout").disabled = !isAuthenticated;
document.getElementById("btn-login").disabled = isAuthenticated;
// NEW - add logic to show/hide gated content after authentication
if (isAuthenticated) {
document.getElementById("gated-content").classList.remove("hidden");
document.getElementById(
"ipt-access-token"
).innerHTML = await authok.getTokenSilently();
document.getElementById("ipt-user-profile").textContent = JSON.stringify(
await authok.getUser()
);
} else {
document.getElementById("gated-content").classList.add("hidden");
}
};
// ..