你自己的 API
App 可以请求访问你某个 API 的访问令牌。它会得到一个已签名的 JWT,其受众只有这个 API,你的 API 用环境公布的密钥即可校验,无需调用 Usher。用于一个 API 的令牌,拿到另一个 API 上毫无用处。
为 API 命名
在 Usher Console 中打开环境,然后前往 应用 → 你的 API → 添加 API。为它填写名称和标识符:标识符可以是一个 https:// 地址,例如 https://api.example.com,也可以是一个 URN,例如 urn:example:api:notes。标识符既是 App 请求的内容,也是令牌 aud 声明中写明的值(RFC 8707)。
然后把这个 API 分配给调用它的 App:在每个应用的 API 中设置。无论 App 请求什么,它都只能获得已分配给它的 API 的令牌。移除某个 API 后,它就不会再获得新的令牌;已经签发出去的令牌会在几分钟内过期。
请求令牌
App 在授权请求和令牌请求中加上 resource=<identifier>。移动 SDK 会替你完成这一步:
let usher = UsherClient(configuration: .init(
issuer: URL(string: "https://login.example.com")!,
clientID: "…",
redirectURI: URL(string: "com.example.notes:/oauth/callback")!,
resources: ["urn:example:api:notes"]))
var request = URLRequest(url: URL(string: "https://api.example.com/notes")!)
try await usher.authorize(&request) // Authorization: Bearer <a JWT for the Notes API>val usher = Usher.client(context, UsherConfiguration(
issuer = "https://login.example.com",
clientId = "…",
redirectUri = "com.example.notes:/oauth/callback",
resources = listOf("urn:example:api:notes")))如果 App 要调用你的两个 API,可以同时请求两者;这时令牌的受众会同时列出这两个 API。
在你的 API 中校验令牌
在信任令牌中的任何内容之前,先校验每个请求的令牌:
- 签名:根据环境发现文档中
jwks_uri所指的密钥进行校验。算法要从密钥中获取,绝不能从令牌的标头中读取。 iss必须与你的环境的颁发者完全一致。请在配置中固定这个值,绝不要从令牌中读取。aud必须包含你的 API 的标识符。(如果使用了openid范围,它还会列出环境的 userinfo 地址。)- 标头中的
typ必须是at+jwt,这样 ID 令牌就无法冒充访问令牌。 exp必须尚未过期。访问令牌的有效期为 10 分钟;SDK 会替你刷新。
在 Node.js 中,@usher/node 会完成以上所有检查:
import { createVerifier } from '@usher/node'
const usher = await createVerifier({
issuer: 'https://login.example.com',
audience: 'urn:example:api:notes',
})
const claims = await usher.accessToken(bearerToken) // throws if any check fails在 ASP.NET Core 中:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(o =>
{
o.Authority = "https://login.example.com"; // discovery and keys come from here
o.MapInboundClaims = false;
o.TokenValidationParameters = new()
{
ValidIssuer = "https://login.example.com",
ValidAudience = "urn:example:api:notes",
ValidTypes = ["at+jwt"],
};
});令牌包含哪些信息
| 声明 | |
|---|---|
sub | 用户本人。与 iss 一起,作为识别该用户的键。 |
client_id、azp | 发出请求的 App。 |
scope | 用户同意该 App 可以做的事情。 |
email、email_verified | 使用 email 范围时提供:用户的电子邮件地址,以及 Usher 是否已证实该地址属于此人。 |
sid | 用户的登录会话。 |
org | 使用 organization 范围时提供:用户当前所在的组织及其角色。 |
你已经认识的用户
如果你的 API 中已经有以前的账户,那么当某人第一次带着 Usher 令牌到来时,你可以找到他的账户:按 email 查找,但仅限 email_verified 为 true 的情况,并从那以后在他的账户上保存 iss 和 sub。此后,请按 iss 和 sub 查找,绝不要按电子邮件地址查找:电子邮件地址可能易主,而主体标识(subject)永远不会变。