Reference
Endpoints, scopes, claims, token lifetimes, rules and errors.
Discovery
The issuer is https://id.warpulse.com. The discovery document is at https://id.warpulse.com/.well-known/openid-configuration.
Endpoints
| Endpoint | URL | Use |
|---|---|---|
| Discovery | https://id.warpulse.com/.well-known/openid-configuration | Everything below, and the supported algorithms, as JSON. |
| Authorization | https://id.warpulse.com/auth | Send the browser here to start a sign-in. |
| Token | https://id.warpulse.com/token | Trade a code or a refresh token for tokens. |
| Userinfo | https://id.warpulse.com/me | Send the access token as a Bearer token to read the claims of the scopes you were given. |
| JWKS | https://id.warpulse.com/jwks | The public keys that sign ID tokens. Cache them, and re-read them when you meet an unknown key id. |
| Revocation | https://id.warpulse.com/token/revocation | End a token you hold. |
| Introspection | https://id.warpulse.com/token/introspection | Web apps only, and only for tokens issued to that app. |
| End session | https://id.warpulse.com/session/end | Sign the person out of PulseID. The post_logout_redirect_uri must be one you registered. |
Scopes
Every app can ask for openid profile email. A verified web app can also ask for offline_access. Any other scope, such as one for PulseID's own account API, is refused with invalid_scope.
| Scope | Available to | What it gives |
|---|---|---|
openid | All apps | Sign-in itself: the ID token, with sub, amr and auth_time. |
profile | All apps | name, updated_at and pulse_number. |
email | All apps | email and email_verified. |
offline_access | Verified web apps only | A refresh token. |
Claims
The ID token carries the claims of the scopes you were given, so you do not need to call the userinfo endpoint for the basics. The userinfo endpoint returns sub and the email and profile claims. amr and auth_time are only in the ID token.
| Claim | Scope | Notes |
|---|---|---|
sub | openid | The id of the PulseID account. Stable for that account. |
amr | openid | How the person proved who they are, for example pwd and otp, or hwk for a passkey. |
auth_time | openid | When the person last proved who they are, in Unix seconds. |
email | email | The email address of the account. |
email_verified | email | true or false. |
name | profile | The display name. Left out when the person has not set one. |
updated_at | profile | When the profile last changed, in Unix seconds. |
pulse_number | profile | The Pulse number as a JSON number. Left out when the person has none. |
An ID token also has the usual iss, aud, exp and iat, and your nonce when you sent one. It is signed with ES256.
Token lifetimes
| Token | Lifetime | Notes |
|---|---|---|
| Authorization code | 60 seconds | Works once. |
| Access token | 10 minutes | Opaque. For the userinfo endpoint. |
| ID token | 10 minutes | A signed JWT. You get it with the code exchange. |
| Refresh token | 30 days | Verified web apps only. Replaced by a new one on every use. Never lasts past 30 days from the sign-in it came from. Using an old one again ends the grant. |
Every token also stops working when the person's PulseID sign-in session ends, which is 30 days after they signed in at the most.
Rules
- PKCE S256 required. Every app sends a
code_challengewithcode_challenge_method=S256and a matchingcode_verifierat the token endpoint. There is no plain method. - The code flow only (
response_type=code). There is no implicit, hybrid or device flow. prompt=consentis needed to receiveoffline_access. Send it with the scope.offline_accessis silently removed for unverified apps and for public apps. There is no error and no refresh token.- A web app authenticates at the token endpoint with its client ID and secret over HTTP Basic. A public app sends its client ID and has no secret.
- Redirect URIs and post-logout redirect URIs must be https, with no fragment, no wildcard and no user name or password in them. An app may have up to 10 of each.
- An app cannot ask for a
resource. A request with one fails withinvalid_target.
Errors
| Error | Where | Cause |
|---|---|---|
invalid_client | Token endpoint, status 401 | A wrong or missing secret, a secret that was revoked or has expired, an app with no live secret, an app id that does not exist, a deleted app, a paused app, or an app whose organization is paused. |
| This app is paused | A page at the authorization endpoint, status 403 | WarPulse paused the app or its organization. The person is not sent back to your app, and tokens already issued stop working. While it lasts, a token request answers invalid_client. |
invalid_client | A page at the authorization endpoint, status 400 | The app id does not exist, or the app was deleted. |
invalid_scope | The authorization request, returned to your redirect URI | A scope your app may not have, such as pulseid:account. offline_access is not an error: it is removed. |
invalid_target | The authorization request, returned to your redirect URI | The request has a resource parameter. |
invalid_grant | Token endpoint, status 400 | A code that is unknown, used, or older than 60 seconds, a code_verifier or redirect_uri that does not match, or a refresh token that was already used. |