OAuth 2.0 and OpenID Connect endpoints

Status: planned. This page describes the protocol surface of every KeenAuth environment as specified in the plan (§13). The endpoints are being built in phase 2 and are not yet available in a hosted environment. Details can still change before general availability.

Every environment is its own OAuth 2.0 authorization server and OpenID Connect provider. The endpoints are not part of the management API: they live on the environment host, https://<environment-slug>.<region>.keenauth.app, or on your verified custom domain. In the table, <issuer> is the environment's issuer, the value of issuer in the discovery document.

Endpoints

Endpoint Method and path Client authentication
Discovery GET <issuer>/.well-known/openid-configuration and GET <issuer>/.well-known/oauth-authorization-server (RFC 8414, same content) None
Keys GET <issuer>/.well-known/jwks.json None
Authorization GET or POST <login host>/oauth2/authorize None (browser)
Pushed authorization request (RFC 9126) POST <issuer>/oauth2/par Required for confidential clients; client_id for public clients
Token POST <issuer>/oauth2/token Required for confidential clients; client_id for public clients (DPoP is optional)
Device authorization (RFC 8628) POST <issuer>/oauth2/device_authorization Same as the token endpoint
Revocation (RFC 7009) POST <issuer>/oauth2/revoke Same as the token endpoint
Introspection (RFC 7662) POST <issuer>/oauth2/introspect Confidential client only
UserInfo GET or POST <issuer>/oauth2/userinfo Bearer or DPoP access token
End session GET or POST <login host>/oauth2/logout None (id_token_hint or client_id)

<login host> is any sign-in domain of the environment: the default host or an added custom domain. The discovery document is served only on the issuer host. On another sign-in host, /.well-known/openid-configuration returns 404 with the issuer URL in the body.

Grant types

Grant Use
authorization_code Browser and native sign-in. PKCE with S256 is required.
refresh_token Renews tokens. Every use rotates the refresh token, and reusing an old one revokes the whole token family.
client_credentials Machine-to-machine access.
urn:ietf:params:oauth:grant-type:device_code Devices without a keyboard, such as a TV or a command-line tool.
urn:ietf:params:oauth:grant-type:token-exchange Delegation and impersonation between services.

Implicit flows (response_type=token and anything that contains id_token), the resource owner password credentials grant and hybrid response types are not supported, now or later. RFC 9700 forbids the first two.

Device authorization

A device without a browser starts the flow with POST <issuer>/oauth2/device_authorization. Only applications of type device or native that list the device grant explicitly can use it. The response carries a device_code, a user_code and a verification address. The user opens the address on another device, signs in and approves. Meanwhile, the device polls the token endpoint with grant_type=urn:ietf:params:oauth:grant-type:device_code. The user_code has 8 characters and is shown as XXXX-XXXX. A device code is valid for 10 minutes and works once. The device polls every 5 seconds at most; faster polling is answered with slow_down, which adds 5 seconds to the interval. The verification_uri is https://<login host>/u/device, and the user is shown the application, the requested scopes and the country of the device that started the request before approving.

Security rules

The environment follows the OAuth 2.0 Security Best Current Practice (RFC 9700) without exception:

Sessions and sign-out

After a successful sign-in the environment keeps one single sign-on session in an HttpOnly cookie on the sign-in host. Applications of the same environment reuse it, so a second application does not ask for a password again unless its policy needs a stronger or newer authentication. Your code never sees the cookie: it only sees the authorization response.

The end-session endpoint (OpenID Connect RP-Initiated Logout 1.0) ends that session, revokes the refresh tokens that belong to it and notifies the applications that registered a back-channel logout address. To list or revoke the sessions of a user from your backend, use the session endpoints of the management API.

If the user signed in through an enterprise connection, add federated=true to the end-session request to sign them out at their identity provider too. The session here ends first; the browser then goes to the identity provider's logout (SAML single logout, or the OpenID provider's end-session endpoint) and comes back to the post_logout_redirect_uri. This happens only when the connection has identity-provider logout turned on and the provider publishes a logout address. Otherwise, or if the provider cannot be reached, the request works as it does without the parameter. Signing out at the identity provider can also end the user's other applications that use it.