Discover the endpoints for your environment
Each environment publishes its own issuer, resource identifier, metadata, keys, clients, grants, and tokens. Discover endpoint addresses from metadata instead of constructing/oauth/* addresses.
Fetch these public metadata documents from the environment origin:
- OpenID Provider metadata:
/.well-known/openid-configuration - Authorization server metadata:
/.well-known/oauth-authorization-server - Protected resource metadata:
/.well-known/oauth-protected-resource - JSON Web Key Set (JWKS): use the
jwks_urireturned by provider metadata
api_origin with the test or production origin from the table when you target another environment.
Compare the supported client profiles
Perflo registers each client for one explicit profile and scope ceiling. Dynamic Client Registration (DCR) is unavailable, and every hosted web redirect uses Hypertext Transfer Protocol Secure (HTTPS).
A confidential backend-for-frontend remains the recommended browser architecture. A registered public single-page application can use the public browser profile directly.
Follow the authorization-code rules
Authorization-code clients use onlyresponse_type=code. Perflo accepts query and form_post response modes and rejects fragment responses.
Confidential clients must first create a PAR request. Their authorization request contains only the issued request_uri and client_id. Public browser and native clients send the direct code-flow parameters because the PAR endpoint does not enable browser cross-origin requests.
Every authorization-code request follows these rules:
- Send a PKCE
S256challenge and redeem the code with the matching verifier - Bind the code to the DPoP key with
dpop_jkt - Request the exact resource identifier for the current environment
- Use an exact registered redirect URI
- Send
noncewhen requestingopenid - Use only
prompt=login,prompt=consent,prompt=none, and optionalmax_age
nonce contains 1 to 64 Unicode scalar values and no control characters. Perflo returns it unchanged in the identity token. An empty or longer value fails.
The resource parameter contains the one exact environment resource from the discovery table. Foreign or multiple values fail, and refresh cannot switch the original resource.
The first authorization for a client always displays consent. prompt=consent displays it again, while prompt=none fails when prior authentication or consent is insufficient.
Request identity without exposing provider data
Theopenid scope is available only to authorization-code clients. It adds a five-minute ES256-signed identity (ID) token with these claims:
iss, pairwisesub,aud,exp, andiatauth_time, the returnednonce, andacr
urn:perflo:acr:provider-device records provider-device authentication or reuse. It does not claim multi-factor authentication (MFA).
Perflo does not expose a UserInfo endpoint or profile, email, address, phone, wallet, or provider claims. An ID token never authenticates a Perflo API request.
Handle tokens and revocation safely
Perflo issues environment-local tokens and codes with bounded lifetimes. Keep access and refresh tokens in client storage designed for credentials. Never include tokens in telemetry, error details, request addresses, or fixtures, and never record protocol codes in logs or fixtures.
Ordinary refresh does not rotate the refresh token. Confidential clients authenticate each refresh with
private_key_jwt, while every client proves possession of the original DPoP key.
An authenticated confidential client can submit its opaque refresh token to the revocation endpoint, which revokes the complete client grant. A human resource owner can revoke any public or confidential grant from the host-only account page. Unknown or already revoked values submitted to the protocol endpoint still return 200 without identity details.
Perflo access and refresh tokens are separate from upstream provider credentials. OAuth responses, browser pages, logs, and error details never expose provider access tokens, provider refresh tokens, or device identifiers.
Use device and service grants for different owners
The device profile creates a human-owned grant only after provider-device approval and consent. The client receives device and user codes, then polls no faster than the interval returned by the authorization server. Only local fake mode can complete account binding in this release. A service-account grant belongs only to its registered service resource owner. It cannot select, attach, or merge a human identity, and it never issues an ID token. A server that needs unattended access for a person must complete authorization code once and retain the resulting DPoP-bound refresh grant.Respect unavailable scopes and flows
purchases:execute is unavailable in this release. Perflo does not advertise, register, consent, or grant it, and a request for it returns invalid_scope.
Live provider-device adoption is unavailable in this release. Manage connected clients explains the local interaction and account controls without enabling live account binding.
Perflo also rejects these features:
- Dynamic client registration and UserInfo
- Implicit, hybrid, password, Client-Initiated Backchannel Authentication (CIBA), token-exchange, and mutual TLS flows
- Arbitrary request objects or request URIs
- The OIDC
claimsparameter - Rich Authorization Requests (RAR) and
authorization_details - JWT Secured Authorization Response Mode (JARM) and Financial-grade API (FAPI) Message Signing
- Shared client secrets and bearer-only API access