Skip to main content
Version: Next (unreleased)

Endpoints

Paths are relative to the issuer. On the hosted gateway that is https://auth.resoauth.cloud; on your own deployment it is whatever SAG_ISSUER says, including any base path.

PathMethodWhat it is
/.well-known/openid-configurationGETOpenID Connect discovery. Start here
/.well-known/oauth-authorization-serverGETThe same instance described as an OAuth authorisation server (RFC 8414)
/.well-known/oauth-protected-resourceGETDescribes /userinfo as a protected resource (RFC 9728)
/.well-known/jwks.jsonGETThe public keys that verify an id_token
/jwks.jsonGETThe same keys at the pre-RFC 8414 location, for older libraries
/authorizeGET, POSTWhere you send the person to sign in
/callbackGETWhere an upstream provider returns them. Not for your application
/tokenPOSTExchange an authorisation code for an id_token
/userinfoGET, POSTClaims about the signed-in person, using the access token
/logoutGET, POSTEnd the session (end_session_endpoint)
/healthzGETWhether this instance can actually sign somebody in
/aliveGETWhether a process is listening at all

The /authorize/* sub-paths (/authorize/email, /authorize/otp, /authorize/resend, and the rest) belong to the sign-in screens themselves. They are form targets, not an API, and their shape may change between releases. Your application only ever needs /authorize.

/ is deliberately not a landing page. It returns 404 with "This is a sign-in service. Start from the application you want to use."

Which of these are stable

/authorize, /token, /userinfo, /logout, the discovery documents, and the JWKS are the interface. They follow OpenID Connect and RFC 8414, and a change to them is a breaking change.

The /authorize/* form targets and /static/* are internal. They are the sign-in screens talking to themselves, and they may change in any release.

Do not hard-code any of them. Read the discovery document, which is the point of having one.

The discovery document describes the instance

This is worth stating on its own, because it catches people out.

SAG advertises what the running instance can actually do, not what the software supports. No profile scope when nothing could fill it. No federated acr value without an upstream configured. No signing algorithm without a key behind it.

So a claim, scope, or algorithm missing from discovery is missing because this deployment cannot provide it. Reading discovery at startup and configuring from it is not defensive programming here; it is the intended way to use it.

Extensions SAG publishes under its own namespace:

KeyMeaning
urn:sag:require_pkceAlways true. PKCE is not optional
urn:sag:post_quantum_signing_supportedWhether a post-quantum key is published
urn:sag:post_quantum_algsWhich post-quantum algorithms, if any
urn:sag:client_registrationHow this instance accepts relying parties
urn:sag:protected_resourcesResources the access token is good for. /userinfo, and nothing else

/alive versus /healthz

These answer different questions, and using the wrong one causes real incidents.

/alive returns 200 and the body ok. Nothing else. It is handled before configuration is even parsed, so it answers 200 on an instance that is misconfigured and cannot sign anybody in. Use it for a container liveness probe, and for load-balancer target health.

/healthz returns JSON and answers whether this instance can actually sign somebody in. It reports the running version, the issuer, the signing setup, warnings, which upstream providers are configured and how many domains each covers, whether email codes are on, how relying parties are described, and the state of any peer JWKS federation.

Point failover checks at /healthz. Pointing them at /alive means traffic keeps arriving at an instance that will fail every sign-in.

/healthz deliberately will not tell you whether a state store is configured, name any upstream domain, or identify any relying party. Those would turn a public endpoint into a description of who uses the service. Operators get that from the start-up banner and the logs instead.

Reading both is covered in operations, and the multi-region routing case in multi-region.