Run tinyidp, point a relying party at it, complete an authorization-code login, and inspect the issued session state.
This tutorial walks through the first complete relying-party login against tinyidp. It uses the default root issuer and the permissive dev-client so the protocol sequence is visible without extra client setup.
By the end, you will know which URLs must agree, what the browser login form does, what the token exchange produces, and how to inspect tinyidp's in-memory state after the flow.
You need:
tinyidp binary;The examples below assume the relying party callback is:
http://localhost:3000/callback
That URI is accepted by the built-in dev-client.
Start the provider with the basic root-issuer config:
tinyidp serve-dev --config-file examples/configs/dev-root.yaml
If you are running from source:
go run ./cmd/tinyidp serve-dev --config-file examples/configs/dev-root.yaml
The provider listens on 127.0.0.1:5556 and advertises the issuer http://localhost:5556.
Fetch the discovery document:
curl -s http://localhost:5556/.well-known/openid-configuration | jq '{issuer, authorization_endpoint, token_endpoint, jwks_uri}'
Expected shape:
{
"issuer": "http://localhost:5556",
"authorization_endpoint": "http://localhost:5556/authorize",
"token_endpoint": "http://localhost:5556/token",
"jwks_uri": "http://localhost:5556/jwks"
}
The relying party validates that the discovery issuer equals the issuer URL it was configured with. If these values differ, the client should reject the provider.
Configure your RP with:
issuer: http://localhost:5556
client_id: dev-client
client_secret: (empty)
redirect_uri: http://localhost:3000/callback
scope: openid profile email
For a first login, use dev-client. It is public, does not require a secret, and does not require PKCE. After the first flow works, switch to public-spa or web-app if you need to test stricter client behavior.
Start a login from the RP. The browser is redirected to tinyidp's authorize endpoint. The authorize GET validates the request and renders a login form. Hidden fields carry the original OIDC request parameters into the POST.
At the login page, type:
alice
Leave the password empty unless you are using a seeded users file that defines a password for Alice. Submit the form.
The authorize POST does four things:
login=alice and resolves the scenario.code and state.The RP sends the authorization code to /token. tinyidp checks the client, redirect URI, code expiry, and optional PKCE verifier. It then returns an ID token and access token.
The ID token contains claims derived from the selected login:
sub: deterministic synthetic subject
email: alice@example.test
email_verified: true
name: alice
iss: http://localhost:5556
aud: dev-client
The access token is opaque. tinyidp stores it in memory and uses it to answer /userinfo.
After the login, inspect tinyidp's state from another terminal:
curl -s http://localhost:5556/debug | jq .
curl -s http://localhost:5556/debug/sessions | jq .
curl -s http://localhost:5556/debug/codes | jq .
curl -s http://localhost:5556/debug/tokens | jq .
The debug views show active sessions, outstanding codes, and issued tokens. Secret values are shortened so the output can be used for diagnosis without exposing full bearer tokens.
Clear in-memory state when you want a clean run:
curl -s -X POST http://localhost:5556/debug/reset
This does not change the signing key or configured clients. It clears sessions, codes, access tokens, and refresh tokens.
The first login establishes the invariant every other tutorial builds on: the RP's configured issuer, the discovery issuer, token iss, client ID, and redirect URI must agree. Once that agreement holds, tinyidp can derive users from login names, issue signed ID tokens, and expose enough debug state to make relying-party tests understandable.
| Problem | Cause | Solution |
|---|---|---|
| RP rejects discovery. | Configured issuer does not equal discovery issuer. | Configure the RP with http://localhost:5556 for this tutorial. |
redirect_uri not allowed for this client. | The RP callback does not match the allowlist. | Use http://localhost:3000/callback or configure --redirect-uris. |
| Browser login succeeds but RP rejects token. | RP expects a different client ID, issuer, or JWKS. | Compare RP config with discovery and ID token claims. |
| Debug endpoints return 403. | Request is not from loopback. | Call debug endpoints from the same host. |
tinyidp help user-guide — operational guide for everyday use.tinyidp help tutorial — scenario and failure-mode tutorial.tinyidp help tutorial-seeded-users-and-claims — deterministic users and claims.tinyidp help tutorial-device-authorization — device-code approval and polling.tinyidp help reference — full endpoint and config reference.