자체 API
앱은 직접 만든 API 중 하나를 위한 액세스 토큰을 요청할 수 있습니다. 앱이 받는 것은 대상(audience)이 그 API 하나뿐인 서명된 JWT이며, API는 Usher를 호출하지 않고 환경에 공개된 키로 이를 검증합니다. 한 API용 토큰은 다른 API에서 쓸 수 없습니다.
API 이름 정하기
Usher Console에서 환경을 열고 애플리케이션 → 자체 API → API 추가로 이동하세요. 이름과 식별자를 지정합니다. 식별자는 https://api.example.com과 같은 https:// 주소이거나 urn:example:api:notes와 같은 URN입니다. 식별자는 앱이 요청하는 값이자 토큰의 aud 클레임에 들어가는 값입니다(RFC 8707).
그런 다음 이 API를 호출하는 앱에 API를 연결하세요. 각 애플리케이션의 API에서 설정합니다. 앱은 무엇을 요청하든 연결된 API에 대해서만 토큰을 받습니다. API 연결을 제거하면 더 이상 토큰이 발급되지 않으며, 이미 발급된 토큰도 몇 분 안에 만료됩니다.
토큰 요청하기
앱은 인가 요청과 토큰 요청에 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")))두 개의 API를 호출하는 앱은 두 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 failsASP.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 | 토큰을 요청한 앱. |
scope | 사용자가 앱에 허용하기로 동의한 작업. |
email, email_verified | email 범위를 요청한 경우: 사용자의 이메일 주소와, Usher가 그 주소의 소유를 확인했는지 여부. |
sid | 사용자의 로그인 세션. |
org | organization 범위를 요청한 경우: 사용자의 활성 조직과 역할. |
이미 알고 있는 사용자
API에 이전부터 쓰던 계정이 있다면, 사용자가 Usher 토큰을 가지고 처음 들어올 때 기존 계정을 찾을 수 있습니다. email_verified가 true일 때만 email로 사용자를 찾고, 그때부터 계정에 iss와 sub을 저장해 두세요. 그 이후로는 이메일이 아니라 항상 iss와 sub으로 사용자를 찾으세요. 이메일 주소는 주인이 바뀔 수 있지만, 주체(subject)는 절대 바뀌지 않습니다.