跳至內容
文件 · 任何 OIDC 程式庫

快速入門:任何 OIDC 程式庫

Usher 是標準的 OpenID Connect 提供者。如果你使用的語言有經過認證的 OIDC 客户端,你就已經具備所需的一切:將它指向你環境的探索文件,並使用搭配 PKCE 的授權碼流程。

設定

設定值
簽發者https://<handle>.usherid.com
探索 URLhttps://<handle>.usherid.com/.well-known/openid-configuration
流程授權碼(response_type=code)
PKCE必要,code_challenge_method=S256
範圍openid profile email offline_access
客户端驗證按 token_endpoint_auth_methods_supported 中列出的方式

你環境的代號顯示在 Usher Console 中簽發者的旁邊。開發環境會取得隨機代號,例如 wise-otter-42;正式環境則使用你選擇的代號。正式環境也可以改用你自己的網域,例如 login.acme.com:只要你以 CNAME 記錄將該網域指向 Usher,它就會成為該環境的簽發者。

讀取探索文件

你的客户端需要的每個端點和密鑰都列在這裡。請讓你的程式庫讀取它,而不是把 URL 寫死在程式碼中。

終端機
curl -s https://acme.usherid.com/.well-known/openid-configuration | jq
回應(節錄)
{
  "issuer": "https://acme.usherid.com",
  "authorization_endpoint": "https://acme.usherid.com/api/auth/oauth2/authorize",
  "token_endpoint": "https://acme.usherid.com/api/auth/oauth2/token",
  "userinfo_endpoint": "https://acme.usherid.com/api/auth/oauth2/userinfo",
  "jwks_uri": "https://acme.usherid.com/api/auth/jwks",
  "introspection_endpoint": "https://acme.usherid.com/api/auth/oauth2/introspect",
  "revocation_endpoint": "https://acme.usherid.com/api/auth/oauth2/revoke",
  "end_session_endpoint": "https://acme.usherid.com/api/auth/oauth2/end-session",
  "scopes_supported": ["openid", "profile", "email", "offline_access"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
  "code_challenge_methods_supported": ["S256"]
}

流程

將用户送往授權端點

產生一個隨機的 PKCE 驗證器,連同一個隨機的 state,保存在只有這個瀏覽器的工作階段才能存取的地方(短效的 httpOnly Cookie 就很適合)。然後帶著 response_type=code、你的 client_id 和 redirect_uri、上述範圍、state,以及驗證器的 S256 code_challenge 進行重新導向。

讓他們登入

接下來交給 Lobby:它會指出你的 App、提供你環境允許的登入方式,並在第一次時徵求同意。

檢查回呼

Usher 會帶著 code 和 state 重新導向到你的 redirect_uri。除非 state 與你儲存的相符,否則請拒絕該回應。授權碼只能使用一次,有效期為五分鐘。

用授權碼換取權杖

從你的伺服器,將授權碼和 PKCE 驗證器 POST 到權杖端點:

權杖請求
curl -s -X POST https://acme.usherid.com/api/auth/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=authorization_code \
-d code="$CODE" \
-d redirect_uri=https://app.acme.example/callback \
-d code_verifier="$CODE_VERIFIER"

驗證 ID 權杖

以 jwks_uri 的密鑰檢查它的簽名,並確認 iss 是你的簽發者、aud 是你的客户端 ID,且 exp 是未來的時間。你的程式庫會替你完成這些檢查;請確認這項功能沒有被關閉。

在 Node.js 中

openid-client 會完成上述所有步驟,包括驗證:

openid-client
import * as client from 'openid-client'

// discovery: every endpoint and key comes from the issuer
const config = await client.discovery(
  new URL('https://acme.usherid.com'),
  process.env.USHER_CLIENT_ID!,
  process.env.USHER_CLIENT_SECRET!,
)

// 1. send them to the Lobby, with PKCE (S256) and a state to check later
const codeVerifier = client.randomPKCECodeVerifier()
const state = client.randomState()
const url = client.buildAuthorizationUrl(config, {
  redirect_uri: 'https://app.acme.example/callback',
  scope: 'openid profile email offline_access',
  code_challenge: await client.calculatePKCECodeChallenge(codeVerifier),
  code_challenge_method: 'S256',
  state,
})
// keep codeVerifier and state in a short-lived httpOnly cookie, then redirect to url

// 2. back at /callback: swap the code for tokens
const tokens = await client.authorizationCodeGrant(config, new URL(request.url), {
  pkceCodeVerifier: codeVerifier,
  expectedState: state,
})
const { sub, email, name } = tokens.claims()!

在其他語言中

以下這些廣泛使用的程式庫都支援標準 OpenID Connect,不需要任何 Usher 專屬的設定就能搭配 Usher 使用:

語言程式庫
PythonAuthlib
Gocoreos/go-oidc 搭配 golang.org/x/oauth2
JavaSpring Security OAuth 2.0 Client
.NETMicrosoft.AspNetCore.Authentication.OpenIdConnect
Rubyomniauth_openid_connect
PHPjumbojett/openid-connect-php

保持登入

使用 offline_access 範圍時,權杖回應會包含重新整理權杖。當舊的存取權杖到期時,搭配 grant_type=refresh_token 使用它來取得新的存取權杖。重新整理權杖會輪替:每次使用都會傳回新的權杖,舊的則會失效。

登出

先清除你自己的工作階段,然後帶著 post_logout_redirect_uri(如果有的話,再加上 id_token_hint)重新導向到 end_session_endpoint,讓 Lobby 也忘記這位用户。