Environments and the issuer
The issuer address, the discovery document and the signing keys, and how to configure a client so it never hard-codes an endpoint.
On this page
Every client of identity starts from one string: the issuer. It is an https address, and it is the only address you configure. Everything else, the authorization endpoint, the token endpoint, the signing keys, comes from the discovery document that the issuer publishes.
The issuer#
TDACorp Identity's issuer is:
https://identity.tdacorp.inThree rules follow from what the issuer is.
- It is an identifier before it is an address. Every ID token and access token carries it as
iss, every authorization response carries it asiss, and you must compare it byte for byte. No trailing slash, no different case, nowww. A token whoseissdiffers is not from identity. - It has no query or fragment, and it must be
https. The SDK refuses anything else, with one exception for a loopback host during local development. - It is never taken from a request. Identity builds its metadata from a configured issuer, not from the
Hostheader, and your code should do the same: put the issuer in your configuration, not in a value derived from an incoming request.
If TDACorp gives you a different issuer for testing, use it exactly the same way. Only the issuer and your client id change. A client is registered with one issuer, so ask for a separate registration for each.
Discovery#
The discovery document is JSON at a fixed path under the issuer:
GET https://identity.tdacorp.in/.well-known/openid-configurationThe same document is also served at /.well-known/oauth-authorization-server, for libraries that look for the OAuth name. Fetch it once, cache it, and read endpoints from it. An excerpt:
{ "issuer": "https://identity.tdacorp.in", "authorization_endpoint": "https://identity.tdacorp.in/authorize", "pushed_authorization_request_endpoint": "https://identity.tdacorp.in/par", "token_endpoint": "https://identity.tdacorp.in/token", "userinfo_endpoint": "https://identity.tdacorp.in/userinfo", "revocation_endpoint": "https://identity.tdacorp.in/revoke", "end_session_endpoint": "https://identity.tdacorp.in/logout", "jwks_uri": "https://identity.tdacorp.in/.well-known/jwks.json", "response_types_supported": ["code"], "code_challenge_methods_supported": ["S256"], "require_pushed_authorization_requests": true, "dpop_signing_alg_values_supported": ["EdDSA", "ES256"], "device_authorization_endpoint": null}The members that change how you build a client:
| Member | What it tells you |
|---|---|
pushed_authorization_request_endpoint and require_pushed_authorization_requests | Every sign-in begins with a pushed request. See Pushed authorization requests. |
code_challenge_methods_supported | S256 only. A plain challenge is refused. |
response_modes_supported | query and form_post. A web client defaults to form_post when it does not say. |
authorization_response_iss_parameter_supported | The authorization response carries iss. Check it. |
token_endpoint_auth_methods_supported | The ways to authenticate to the token endpoint. See Client authentication. |
dpop_signing_alg_values_supported | The algorithms identity accepts for DPoP proofs. See DPoP. |
scopes_supported and claims_supported | The standard scopes and claims. See Scopes and consent. |
resource_indicators_supported | A resource parameter is understood. See Resource indicators. |
subject_types_supported | public and pairwise. A client registered pairwise sees a sub specific to its sector. See ID token. |
backchannel_logout_supported | Identity sends logout tokens. See Back-channel logout. |
device_authorization_endpoint | Always null: the device flow does not exist. |
The document lists only what is reachable. A member appears when the thing it describes works, so a client can act on what it reads. The generated table of endpoints is in OIDC endpoints.
The SDK caches discovery for five minutes by default and requires every endpoint to be on the issuer's own origin.
Signing keys#
jwks_uri points to the JSON Web Key Set that verifies every token identity signs. Identity signs with EdDSA or ES256, and each key has a kid. Verify like this:
- Read the
kidfrom the token header. Do not trust any other header member to choose a key. - Look it up in the cached key set. If it is not there, fetch the set again, but not on every request: an attacker controls the
kidof an unverified token, so refetch at most once in a cooldown period. - Import the key for the algorithm you allow and verify the signature. Do not let the token pick the algorithm.
Keys rotate. A cached key set that is too old, or a kid you do not know, means you refetch, not that the token is bad. The SDK does this for you, and a resource server built with the SDK does it too.
What to configure#
| Setting | Source |
|---|---|
| Issuer | Your configuration. One string. |
| Client id | Your configuration. Public. |
Client private key and kid | Your secret manager. |
| DPoP private key | Your secret manager. See DPoP. |
| Redirect URI | Your configuration. Must equal the registered address exactly. |
| Every endpoint | Discovery. Never hard-coded. |
Next: Choosing an integration if you have not decided on a client type, or the Quickstart.