跳至主要內容

Protected App — 非 SDK 驗證 (Authentication) 整合

Protected App 的設計目的是將 驗證 (Authentication) 層從你的應用程式中分離,消除 SDK 整合 的複雜性。我們負責驗證 (Authentication),讓你專注於核心功能。使用者驗證後,Protected App 會從你的伺服器提供內容。

Protected App 如何運作

Protected App 由 Cloudflare 提供支援,運行於全球邊緣網路,確保你的應用程式具有低延遲與高可用性。

Protected App 維護會話狀態與使用者資訊。如果使用者尚未驗證,Protected App 會將其導向登入頁面。驗證後,Protected App 會將使用者的請求包裝上驗證與使用者資訊,然後轉發至來源伺服器。

此流程可用下方流程圖表示:

保護你的來源伺服器

來源伺服器可以是 Logto Protected App 不擁有的實體或虛擬設備,是你的應用程式內容所在。類似於內容傳遞網路(CDN)伺服器,Protected App 管理驗證流程並從來源伺服器取得內容。因此,若使用者能直接存取來源伺服器,將可繞過驗證,應用程式將不再受保護。

因此,保護來源連線非常重要,可防止攻擊者在未經驗證下發現並存取你的來源伺服器。常見做法如下:

  1. HTTP 標頭驗證 (HTTP Header Validation)
  2. JSON Web Token (JWT) 驗證

HTTP 標頭驗證 (HTTP Header Validation)

你可以使用 HTTP 基本驗證 (HTTP Basic Authentication) 來保護你的來源伺服器。

每個來自 Protected App 的請求都會包含以下標頭:

Authorization: Basic base64(appId:appSecret)

只要驗證此標頭,即可確認請求來自 Protected App,並拒絕未包含此標頭的請求。

若你使用 Nginx 或 Apache,可參考以下指南在來源伺服器實作 HTTP 基本驗證:

  1. Nginx:設定 HTTP 基本驗證
  2. Apache:驗證 (Authentication) 與授權 (Authorization)

若需在應用程式內檢查標頭,可參考 Cloudflare 提供的 HTTP Basic Authentication 範例,學習如何使用 HTTP Basic 機制限制存取。

JSON Web Token (JWT) 驗證

另一種保護來源伺服器的方法是使用 JSON Web Token (JWT)。

每個經驗證的 Protected App 請求都會包含以下標頭:

Logto-ID-Token: <JWT>

此 JWT 稱為 ID 權杖 (ID Token),由 Logto 簽署並包含使用者資訊。驗證此 JWT 可確認請求來自 Protected App,並拒絕未包含此標頭的請求。

權杖以 JWS 權杖格式加密並簽署。

驗證步驟如下:

  1. 驗證 JWT
  2. 驗證 JWS 簽章
  3. 權杖的簽發者 (Issuer) 為 https://<your-logto-domain>/oidc(由你的 Logto 驗證伺服器簽發)
const express = require('express');
const jwksClient = require('jwks-rsa');
const jwt = require('jsonwebtoken');

const ISSUER = 'https://<your-logto-domain>/oidc';
const CERTS_URL = 'https://<your-logto-domain>/oidc/jwks';

const client = jwksClient({
jwksUri: CERTS_URL,
});

const getKey = (header, callback) => {
client.getSigningKey(header.kid, function (err, key) {
callback(err, key?.getPublicKey());
});
};

const verifyToken = (req, res, next) => {
const token = req.headers['Logto-ID-Token'];

// 確認請求包含 Logto-ID-Token 標頭
if (!token) {
return res
.status(403)
.send({ status: false, message: 'missing required Logto-ID-Token header' });
}

jwt.verify(token, getKey, { issuer: ISSUER }, (err, decoded) => {
if (err) {
return res.status(403).send({ status: false, message: 'invalid id token' });
}

req.user = decoded;
next();
});
};

const app = express();

app.use(verifyToken);

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000);

取得驗證狀態與使用者資訊

若你需要取得應用程式的驗證狀態與使用者資訊,也可以使用 Logto-ID-Token 標頭。

若你只需解碼權杖,可參考以下程式碼:

const express = require('express');

const decodeIdToken = (req, res, next) => {
const token = req.headers['Logto-ID-Token'];

if (!token) {
return res.status(403).send({
status: false,
message: 'missing required Logto-ID-Token header',
});
}

const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid ID token');
}

const payload = parts[1];
const decodedPayload = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));
const claims = JSON.parse(decodedPayload);

req.user = claims;
next();
};

const app = express();

app.use(decodeIdToken);

app.get('/', (req, res) => {
res.json(req.user);
});

app.listen(3000);

自訂 ID 權杖宣告 (Claims)

預設情況下,Logto-ID-Token 標頭包含標準 OIDC 宣告(如 subnameemail)。若要包含 擴充宣告(如角色或組織資料),需同時設定下列兩項:

  1. 租戶開關:於 Console > Custom JWT > ID 權杖 (ID token) 啟用該宣告。
  2. Protected App 權限範圍 (Scopes):於 Protected App 設定中,在 ID 權杖宣告 (ID token claims) > Additional scopes 選擇對應範圍。

只有在 Custom JWT 啟用宣告且 Protected App 選擇對應範圍時,擴充宣告才會包含於轉發的 ID 權杖中。完整擴充範圍與宣告請參閱 自訂 ID 權杖

權限範圍 (Scope)宣告 (Claims)
custom_datacustom_data
identitiesidentities, sso_identities
rolesroles
urn:logto:scope:organizationsorganizations, organization_data
urn:logto:scope:organization_rolesorganization_roles

取得原始主機

若你需要取得用戶端請求的原始主機,可使用 Logto-Hostx-forwarded-host 標頭。

自訂驗證規則

預設情況下,Protected App 會保護所有路由。若需自訂驗證規則,可於 Console 設定「自訂驗證規則」欄位。

支援正則表達式,以下為兩種情境範例:

  1. 僅保護 /admin/privacy 路由:^/(admin|privacy)/.*
  2. 排除 JPG 圖片不進行驗證:^(?!.*\.jpg$).*$

本地開發

Protected App 設計用於搭配你的來源伺服器運作。若來源伺服器未公開存取,可使用 ngrokCloudflare Tunnels 等工具將本地伺服器暴露至網際網路。

過渡至 SDK 整合

Protected App 旨在簡化驗證流程。若你希望獲得更高控制與自訂性,決定轉換為 SDK 整合,可在 Logto 建立新應用程式 並設定 SDK 整合。為順利過渡,你可重複使用 Protected App 的應用程式設定。Protected App 在 Logto 中實際上是一種「傳統網頁應用程式 (Traditional Web App)」,你可於應用程式設定中找到「AppId」與「AppSecret」。過渡完成後,即可將 Protected App 從應用程式中移除。

Protected App:幾個點擊即可建立應用程式驗證 (Authentication),無需寫程式碼。

Protected App 的設計動機

建立驗證 (Authentication) 系統的最快方式