Deine eigenen APIs
Eine App kann ein Access-Token für eine deiner APIs anfordern. Sie bekommt ein signiertes JWT, dessen Audience genau diese API ist und sonst nichts, und deine API prüft es mit den veröffentlichten Schlüsseln deiner Umgebung, ohne Usher aufzurufen. Ein Token für die eine API nützt bei einer anderen nichts.
Gib der API einen Namen
Öffne in Usher Console die Umgebung und dann Anwendungen → Deine APIs → API hinzufügen. Gib ihr einen Namen und einen Bezeichner: eine https://-Adresse wie https://api.example.com oder eine URN wie urn:example:api:notes. Der Bezeichner ist das, was die App anfordert und was im aud-Claim des Tokens steht (RFC 8707).
Gib die API dann den Apps, die sie aufrufen: unter APIs bei jeder Anwendung. Eine App bekommt nur Tokens für die APIs, die ihr zugewiesen sind, ganz gleich, was sie anfordert. Entfernst du eine API, werden für sie keine Tokens mehr ausgestellt; die bereits ausgegebenen laufen innerhalb weniger Minuten ab.
Fordere sie an
Die App fügt ihrer Autorisierungsanfrage und ihren Token-Anfragen resource=<identifier> hinzu. Die mobilen SDKs erledigen das für dich:
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")))Eine App, die zwei deiner APIs aufruft, kann beide auf einmal anfordern; die Audience des Tokens nennt dann beide.
Prüfe es in deiner API
Prüfe das Token jeder Anfrage, bevor du irgendetwas darin vertraust:
- Die Signatur, mit den Schlüsseln unter der
jwks_uriim Discovery-Dokument deiner Umgebung. Nimm den Algorithmus aus dem Schlüssel, nie aus dem Header des Tokens. issist genau der Issuer deiner Umgebung. Leg ihn in deiner Konfiguration fest; lies ihn nie aus dem Token.audenthält den Bezeichner deiner API. (Mit dem Scopeopenidsteht dort außerdem die Userinfo-Adresse deiner Umgebung.)typim Header istat+jwt, damit sich ein ID-Token nicht als Access-Token ausgeben lässt.expist nicht überschritten. Access-Tokens gelten 10 Minuten; die SDKs erneuern sie für dich.
In Node.js erledigt @usher/node all das:
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 failsIn 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"],
};
});Was im Token steht
| Claim | |
|---|---|
sub | Die Person. Zusammen mit iss der Schlüssel, unter dem du sie speicherst. |
client_id, azp | Die App, die angefragt hat. |
scope | Was die App laut Zustimmung der Person tun darf. |
email, email_verified | Mit dem Scope email: die Adresse der Person und ob Usher bestätigt hat, dass sie ihr gehört. |
sid | Ihre Anmeldesitzung. |
org | Mit dem Scope organization: ihre aktive Organisation und Rolle. |
Menschen, die du schon kennst
Hat deine API schon Konten aus der Zeit davor, kannst du das Konto einer Person finden, wenn sie zum ersten Mal mit einem Usher-Token kommt: Such sie anhand von email, aber nur, wenn email_verified den Wert true hat, und speichere ab dann iss und sub an ihrem Konto. Danach findest du sie über iss und sub, nie über die E-Mail-Adresse: Eine Adresse kann den Besitzer wechseln, ein Subject nie.