Sign in with PerSQL
PerSQL is an OpenID Connect (OIDC) provider. You can let people sign in to
your own product with their PerSQL account: register a client, send users to
PerSQL to authorize, and receive a signed id_token carrying their identity.
Signing in establishes who the user is — it does not grant your app access
to their databases. The access token returned alongside the id_token can read
the user’s profile from /userinfo and nothing else.
1. Register a client
Section titled “1. Register a client”In the console, open a workspace and go to Sign in with PerSQL → New app.
- Name — shown to users on the consent screen.
- Redirect URIs — exact-match callback URLs. HTTPS only, except
http://localhostfor local development. - Client type:
- Confidential — a server-side app. You receive a
client_secret(shown once) and send it when exchanging the code. - Public — a single-page app or native client with no secret. PKCE (S256) is required.
- Confidential — a server-side app. You receive a
You get a client_id immediately and, for confidential clients, a one-time
client_secret. Rotate the secret any time from the same screen.
2. Endpoints
Section titled “2. Endpoints”Discovery document (everything below is advertised here):
https://api.persql.com/.well-known/openid-configuration| Issuer | https://api.persql.com |
| Authorization | https://api.persql.com/oauth/authorize |
| Token | https://api.persql.com/oauth/token |
| UserInfo | https://api.persql.com/userinfo |
| JWKS | https://api.persql.com/.well-known/jwks.json |
For the staging environment, swap api.persql.com for api-staging.persql.com.
Scopes: openid (required), email, profile.
Claims: sub (stable user id), email, email_verified, name,
picture. id_tokens are signed with RS256; verify them against the JWKS.
3. The flow
Section titled “3. The flow”Standard OIDC authorization-code flow. Send the user to the authorization endpoint:
https://api.persql.com/oauth/authorize ?response_type=code &client_id=YOUR_CLIENT_ID &redirect_uri=https://yourapp.com/callback &scope=openid%20email%20profile &state=RANDOM &nonce=RANDOM &code_challenge=BASE64URL_SHA256_OF_VERIFIER &code_challenge_method=S256After the user approves, PerSQL redirects back with ?code=...&state=....
Exchange the code for tokens:
curl -X POST https://api.persql.com/oauth/token \ -d grant_type=authorization_code \ -d code=THE_CODE \ -d redirect_uri=https://yourapp.com/callback \ -d client_id=YOUR_CLIENT_ID \ -d client_secret=YOUR_CLIENT_SECRET \ -d code_verifier=THE_PKCE_VERIFIERThe response contains an id_token (the user’s identity) and an
access_token (good only for /userinfo):
{ "id_token": "eyJ…", "access_token": "psqlid_…", "token_type": "Bearer", "expires_in": 3600, "scope": "openid email profile"}Verify the id_token signature against the JWKS, then read sub, email,
and name from its claims — or call /userinfo with the access token:
curl https://api.persql.com/userinfo -H "Authorization: Bearer psqlid_…"PKCE is required for public clients and optional (but verified when present) for confidential clients. Confidential clients may send the secret as a
client_secretform field or via HTTP Basic auth.
4. With Auth.js (NextAuth)
Section titled “4. With Auth.js (NextAuth)”PerSQL works as a generic OIDC provider — no plugin required:
// auth.ts (Auth.js v5)import NextAuth from "next-auth";
export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ { id: "persql", name: "PerSQL", type: "oidc", issuer: "https://api.persql.com", clientId: process.env.PERSQL_CLIENT_ID, clientSecret: process.env.PERSQL_CLIENT_SECRET, authorization: { params: { scope: "openid email profile" } }, }, ],});Register the redirect URI Auth.js uses —
https://yourapp.com/api/auth/callback/persql — as a redirect URI on your
client.