# IdP Urupema > IdP Urupema is the OpenID Connect provider of Instituto Urupema (Keycloak underneath; apps never depend on Keycloak). Issuer: https://id.institutourupema.com.br/realms/urupema. An app uses it to sign people in and learn who they are; the app itself decides what each person may do. The contract in ten lines. Code that breaks any of them is wrong, whatever a library default or a generic tutorial says: 1. Discover everything from `https://id.institutourupema.com.br/realms/urupema/.well-known/openid-configuration` at boot and check its `issuer` field. Never hard-code endpoints or keys. 2. Authorization Code + PKCE S256 only, with a single-use `state` and a `nonce`. Scope exactly `openid profile email`; any other scope fails with `invalid_scope`. No implicit, password, client-credentials or `offline_access`. 3. Validate the ID token: signature against the discovered JWKS, `iss`, `aud` contains your `client_id`, `exp`, `nonce`. Make sure your library really verifies the signature. 4. Key people by the pair `(iss, sub)`. Never by email, and never link accounts because emails match. 5. Confidential client (has a server, the recommended setup): tokens stay on the server, the browser gets only an HttpOnly session cookie, the client secret never leaves the server (not in the browser, the repository or logs). 6. The local session is derived: when the 300 s access token expires, refresh. If the refresh is refused or the IdP is unreachable, destroy the local session and answer 401. Local session ceiling: 10 h. 7. Logout = destroy the local session and redirect to `end_session_endpoint` with `id_token_hint` and a registered `post_logout_redirect_uri`. 8. An API validates the access token: signature, `iss`, `exp`, `aud` containing the app's `client_id`, and `typ` `Bearer` (rejects ID tokens). Name and email are not in the access token: call `userinfo_endpoint`. 9. Authentication is not authorization: a new account has zero permissions in your app until your app grants them. To grant access before someone's first login, invite by email and bind the invitation to `(iss, sub)` at first login only when `email_verified` is `true`. 10. Never call the Keycloak admin API or database; there is no admin API for apps. An app is registered by a reviewed pull request (`clients/.json` in `urupema/idp`), one client per environment; without access to that repository, request it at suporte@institutourupema.com.br. Read the complete documentation below before writing code: it holds the whole contract and a tested Node.js server (Express + openid-client) to copy. ## Documentation Sets - [Abridged documentation](https://docs.id.institutourupema.com.br/llms-small.txt): a compact version of the documentation for IdP Urupema, with non-essential content removed - [Complete documentation](https://docs.id.institutourupema.com.br/llms-full.txt): the full documentation for IdP Urupema - [Contract](https://docs.id.institutourupema.com.br/_llms-txt/contract.txt): what the IdP guarantees and what every app must do - [Integration guides](https://docs.id.institutourupema.com.br/_llms-txt/integration-guides.txt): tested code: Node.js server (BFF), API token validation, production checklist ## Notes - The complete documentation includes all content from the official documentation - The content is automatically generated from the same source as the official documentation ## Optional - [OIDC discovery (live)](https://id.institutourupema.com.br/realms/urupema/.well-known/openid-configuration): the machine-readable endpoint list and JWKS location