Sign in with Nanako
Nanako is an OAuth 2.0 authorization server. Your application sends a user to Nanako, the user approves the permissions you asked for, and you receive an access token that identifies them.
This is what you use to add a Sign in with Nanako button to your product. It is not a general-purpose API key mechanism — the only thing an access token currently reads is the signed-in user's profile.
What you can build
| Server-side web application | ✅ Supported, and the only fully supported shape |
| Command-line tool or backend service with a callback | ✅ Supported |
| Browser-only single-page application | ⚠️ Requires an operator allowlist entry — see Client types |
| Native mobile or desktop application | ❌ Not yet — custom-scheme redirects such as myapp://callback cannot be registered |
| Machine-to-machine access with no user | ❌ Not yet — there is no client credentials grant |
The flow
Nanako implements the authorization code grant (RFC 6749 §4.1), with optional PKCE (RFC 7636) and refresh tokens.
Your app Nanako User
│ │ │
│ 1. redirect to /oauth/authorize ──────────────────────►│
│ │ 2. signs in, reviews the │
│ │ permissions, approves │
│◄─ 3. redirect back to your callback with ?code=… ──────│
│ │ │
│ 4. POST /oauth/token (code + credentials) ────►│ │
│◄─ 5. access_token + refresh_token ────────────│ │
│ │ │
│ 6. GET /oauth/userinfo (Bearer access_token) ─►│ │
│◄─ 7. the user's profile ──────────────────────│ │
Step by step, with runnable commands: Authorization code flow.
Endpoints
All OAuth endpoints live at the root of the API host — not under /api/v1.
| Purpose | Endpoint |
|---|---|
| Authorization | GET https://api.nanako.org/oauth/authorize |
| Token | POST https://api.nanako.org/oauth/token |
| User info | GET https://api.nanako.org/oauth/userinfo |
| Revocation | POST https://api.nanako.org/oauth/revoke |
The same four paths are also served from https://www.nanako.org. Either host
works; pick one and use it consistently.
A document is served at /.well-known/openid-configuration, but the
token_endpoint, userinfo_endpoint and revocation_endpoint URLs it lists
are wrong — they carry an /api/v1 prefix and return 404. An OIDC client
library pointed at that document will fail at the token exchange.
Configure the four endpoints above by hand until this page says otherwise.
Client types
Confidential clients run on a server you control and can keep a
client_secret secret. This is the shape everything here is designed around.
You authenticate to the token endpoint with client_id + client_secret.
Public clients cannot hold a secret, so they use PKCE instead: send a
code_challenge on the authorization request and the matching code_verifier
on the token request. Nanako accepts this, with two limits you must plan for:
- Refreshing and revoking always require a
client_secret. A public client receives arefresh_tokenit can never redeem, and cannot call the revocation endpoint. In practice, a public client's session ends when the access token expires after two hours. - A browser application also has to clear CORS. Nanako's allowlist is operator-configured with no wildcard, so a third-party web origin is blocked by default. Contact us before building one.
If you can run any server-side component, make it a confidential client.
Limits and lifetimes
| Authorization code lifetime | 10 minutes, single use |
| Access token lifetime | 2 hours (expires_in: 7200) |
| Refresh token lifetime | 30 days from the first authorization |
| Refresh token rotation | Every use returns a new refresh token; the old one stops working |
| Token format | Opaque, 44 characters, base64url with one = of padding |
| Client authentication | client_secret_post only — form fields, not HTTP Basic |
| Request encoding | application/x-www-form-urlencoded on /oauth/token and /oauth/revoke |
Refreshing does not extend the 30-day window. Thirty days after the user first approved your app, the refresh chain expires and you must send them through the authorization flow again.
What is not supported
Nanako uses OpenID Connect vocabulary — openid scope, a sub claim, a
userinfo endpoint — but it is not an OIDC provider.
- No
id_token. The token response contains an access token only. - No
nonce. The parameter is accepted by your library and silently dropped. - No token introspection endpoint. To check whether a token is still live,
call
/oauth/userinfo— any non-expired, non-revoked token returns at leastsub. - No client credentials, implicit, or device code grants.
- No dynamic client registration. Applications are registered by hand; see Registering an application.
Next steps
- Register an application — get a
client_idandclient_secret - Authorization code flow — the complete integration
- Scopes — what you can ask for, and what each one returns
- Endpoint reference — every parameter and response field
- Errors — every error you can receive, and what to do about it
- Security requirements — what you must get right