指南:Node (Express)
步驟 1:從請求標頭中提取 Bearer 權杖
一個授權請求應包含一個 Authorization
標頭,其內容為 Bearer <access_token>
。從請求標頭中提取授權權杖:
// auth_middleware.ts
import { IncomingHttpHeaders } from 'http';
const extractBearerTokenFromHeaders = ({ authorization }: IncomingHttpHeaders) => {
const bearerTokenIdentifier = 'Bearer';
if (!authorization) {
throw new Error({ code: 'auth.authorization_header_missing', status: 401 });
}
if (!authorization.startsWith(bearerTokenIdentifier)) {
throw new Error({ code: 'auth.authorization_token_type_not_supported', status: 401 });
}
return authorization.slice(bearerTokenIdentifier.length + 1);
};
步驟 2:權杖驗證
為了示範,我們使用 jose 套件來驗證權杖的簽名、過期狀態和必要的宣告 (Claims)。
安裝 jose
作為你的依賴項
npm i jose --save
獲取 Logto 的 OIDC 配置
你將需要一個 JWK 公鑰集和權杖簽發者來驗證接收到的 JWS 權杖的簽名和來源。所有最新的 Logto 公共授權配置可以在 https://<your-logto-domain>/oidc/.well-known/openid-configuration
找到。
例如,呼叫 https://tenant-id.logto.app/oidc/.well-known/openid-configuration
。並在回應正文中找到以下兩個欄位:
{
"jwks_uri": "https://tenant-id.logto.app/oidc/jwks",
"issuer": "https://tenant-id.logto.app/oidc"
}
添加驗證中介軟體
Jose 的 jwtVerify
方法可以幫助你驗證權杖的 JWS 格式、權杖簽名、簽發者、受眾 (Audience) 和過期狀態。如果驗證失敗,將拋出異常。
注意:
如果你使用 基於角色的存取控制 (RBAC),也需要進行權限範圍 (Scope) 驗證。
// auth-middleware.ts
import { createRemoteJWKSet, jwtVerify } from 'jose';
//...
export const verifyAuthFromRequest = async (req, res, next) => {
// 提取權杖
const token = extractBearerTokenFromHeaders(req.headers);
const { payload } = await jwtVerify(
token, // 從請求標頭中提取的原始 Bearer 權杖
createRemoteJWKSet(new URL('https://<your-logto-domain>/oidc/jwks')), // 使用從 Logto 伺服器查詢的 jwks_uri 生成 jwks
{
// 權杖的預期簽發者,應由 Logto 伺服器簽發
issuer: 'https://<your-logto-domain>/oidc',
// 預期的受眾權杖,應為當前 API 的資源標示符
audience: '<your request listener resource indicator>',
}
);
// 如果你使用 RBAC
assert(payload.scope.includes('some_scope'));
// 自訂 payload 邏輯
userId = payload.sub;
return next();
};
將中介軟體應用於你的 API
import { verifyAuthFromRequest } from '/middleware/auth-middleware.ts';
app.get('/user/:id', verifyAuthFromRequest, (req, res, next) => {
// 自訂代碼
});
相關資源
使用 JWT 和 Logto 保護你的 Express.js API