OIDC Quickstart
This guide walks you through adding BlokSec as an OpenID Connect identity provider to your web application, from creating the application in the admin console to validating tokens, refreshing sessions, and signing out.
BlokSec implements the standard OIDC authorization code flow on top of node-oidc-provider. Any conformant OIDC client library will work. For the complete endpoint and claim reference, see the OIDC Reference.
Prerequisites
Section titled “Prerequisites”- Admin access to the BlokSec admin console
- A web application that supports OIDC (most frameworks have an OIDC client library)
Choose your client type
Section titled “Choose your client type”How you integrate depends on whether your app can keep a secret:
| Client type | Examples | Authentication |
|---|---|---|
| Confidential | Server-rendered apps, backends | Client ID + client secret |
| Public | Single-page apps (SPAs), native/mobile apps | PKCE (no secret) |
Public clients cannot safely store a secret, so they prove possession of the authorization code using PKCE instead. The steps below note where the two paths differ.
Step 1: Create an OIDC application in BlokSec
Section titled “Step 1: Create an OIDC application in BlokSec”- In the admin console, go to Applications > Add Application.
- Enter a name for your application.
- Set Protocol to OpenID Connect.
- Set Application Type to match your app:
- Web application — confidential client (server-rendered app or backend). BlokSec issues a client secret after creation.
- Single-Page App (SPA) or Native app — public client (browser SPA or mobile app). Uses PKCE; no client secret is issued.
- Add your application’s redirect URI (e.g.,
https://yourapp.com/callback). It must match exactly at runtime, including scheme and path. - Optionally add a post-logout redirect URI.
- Click Create.
After creation, note the Client ID shown on the application detail page — you’ll need it in the next step.
For a Web application, click Generate Secret on the application detail page to create a client secret. Copy it immediately; it’s only shown once. SPA and Native app clients don’t get a secret.

Step 2: Point your client at the discovery document
Section titled “Step 2: Point your client at the discovery document”Configure your OIDC client library with BlokSec’s issuer URL and let it self-configure from the discovery document:
Issuer (authority): https://api.bloksec.io/oidcDiscovery document: https://api.bloksec.io/oidc/.well-known/openid-configurationFor the sandbox/development environment, use https://api.bloksec.dev/oidc.
The discovery document provides every endpoint your client needs. The key ones:
| Endpoint | URL |
|---|---|
| Authorization | https://api.bloksec.io/oidc/auth |
| Token | https://api.bloksec.io/oidc/token |
| UserInfo | https://api.bloksec.io/oidc/me |
| JWKS | https://api.bloksec.io/oidc/jwks |
| End session | https://api.bloksec.io/oidc/session/end |
Step 3: Initiate the auth flow
Section titled “Step 3: Initiate the auth flow”Redirect the user to the authorization endpoint:
https://api.bloksec.io/oidc/auth? client_id=YOUR_CLIENT_ID &redirect_uri=https://yourapp.com/callback &response_type=code &scope=openid email profile &state=RANDOM_STATE_VALUE &nonce=RANDOM_NONCE_VALUERequired parameters:
| Parameter | Description |
|---|---|
client_id |
Your application’s Client ID from the admin console |
redirect_uri |
Must match a redirect URI you registered |
response_type |
code for the authorization code flow |
scope |
Space-separated list of scopes; must include openid |
Recommended parameters:
| Parameter | Description |
|---|---|
state |
A random value your app generates to prevent CSRF. Verify it matches when the user returns. |
nonce |
A random value bound into the ID token. Verify it matches after token exchange. |
Public clients (SPAs and native apps) must also include PKCE:
| Parameter | Description |
|---|---|
code_challenge |
Base64URL-encoded SHA-256 hash of a random code_verifier |
code_challenge_method |
Must be S256 |
The user sees the BlokSec login screen and authenticates with their phone — no password.
Step 4: Exchange the code for tokens
Section titled “Step 4: Exchange the code for tokens”After authentication, BlokSec redirects back to your redirect_uri with an authorization code:
https://yourapp.com/callback?code=AUTH_CODE&state=YOUR_STATE_VALUEVerify state matches what you sent, then POST the code to the token endpoint. The code is valid for 10 minutes and can be used once.
Confidential client:
curl -X POST https://api.bloksec.io/oidc/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTH_CODE" \ -d "redirect_uri=https://yourapp.com/callback" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"Public client (PKCE): omit client_secret and include the code_verifier that matches the code_challenge from step 3:
curl -X POST https://api.bloksec.io/oidc/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=AUTH_CODE" \ -d "redirect_uri=https://yourapp.com/callback" \ -d "client_id=YOUR_CLIENT_ID" \ -d "code_verifier=YOUR_CODE_VERIFIER"The response contains:
{ "access_token": "0pHqW8c5Rf...opaque", "id_token": "eyJhbGci...", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "8xY..."}Step 5: Validate the ID token
Section titled “Step 5: Validate the ID token”The id_token is a JWT carrying the user’s identity claims. Before trusting it:
- Verify the signature using BlokSec’s JWKS endpoint (
https://api.bloksec.io/oidc/jwks). Tokens are signed withPS256orRS256. - Check
issequalshttps://api.bloksec.io/oidc(including the/oidcsuffix). - Check
audequals your Client ID. - Check
expis in the future. - Check
noncematches the value you sent in step 3.
Most OIDC client libraries perform all of these checks automatically.
The ID token includes claims based on the scopes you requested:
| Scope | Claims included |
|---|---|
openid |
sub (subject identifier), aud, amr |
email |
email, email_verified |
profile |
name, given_name, family_name, preferred_username, picture, upn, user_did, account |
phone |
phone_number, phone_number_verified |
See the reference for the full claim list, including BlokSec-specific claims like account (which carries the user’s roles).
Step 6: Call UserInfo (optional)
Section titled “Step 6: Call UserInfo (optional)”To fetch the user’s profile separately from the ID token, call the UserInfo endpoint with the access token:
curl https://api.bloksec.io/oidc/me \ -H "Authorization: Bearer ACCESS_TOKEN"It returns the claims granted by the token’s scopes. This is also how a resource server can resolve an opaque access token to a user identity without the introspection credentials.
Step 7: Refresh the access token
Section titled “Step 7: Refresh the access token”Access tokens last 1 hour. To keep a session alive without sending the user back through login, use a refresh token (valid for 7 days).
To receive a refresh token, your authorization request in step 3 must include both:
offline_accessin thescope(e.g.,scope=openid email profile offline_access)prompt=consent
Exchange the refresh token for a fresh access token:
curl -X POST https://api.bloksec.io/oidc/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=YOUR_REFRESH_TOKEN" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET"Public clients omit client_secret.
Step 8: Signing out
Section titled “Step 8: Signing out”Redirect the user to the end session endpoint to terminate their BlokSec session:
https://api.bloksec.io/oidc/session/end? id_token_hint=THE_ID_TOKEN &client_id=YOUR_CLIENT_ID &post_logout_redirect_uri=https://yourapp.com/Clear your own local tokens first, then perform the redirect. The post_logout_redirect_uri must be registered on the application.
SPA integration with oidc-client-ts
Section titled “SPA integration with oidc-client-ts”The configuration below is the one the BlokSec admin console itself uses in production. It’s a complete, working reference for a browser SPA using oidc-client-ts:
import { UserManager, WebStorageStateStore } from 'oidc-client-ts';
const userManager = new UserManager({ authority: 'https://api.bloksec.io/oidc', client_id: 'YOUR_CLIENT_ID', redirect_uri: `${window.location.origin}/auth/callback`, post_logout_redirect_uri: `${window.location.origin}/auth/signin`, response_type: 'code',
// offline_access for refresh tokens; prompt=consent is REQUIRED to get them scope: 'openid profile email offline_access', prompt: 'consent',
// Silent (iframe) renewal before the access token expires silent_redirect_uri: `${window.location.origin}/auth/silent-callback`, automaticSilentRenew: true,
loadUserInfo: true, monitorSession: false, userStore: new WebStorageStateStore({ store: localStorage }),
// some libraries mishandle the empty 200 revocation response; revoke via signout revokeTokensOnSignout: false,});You’ll need two callback routes:
/auth/callback— callsuserManager.signinRedirectCallback()to complete login./auth/silent-callback— a near-empty page that callsuserManager.signinSilentCallback(); it renders inside a hidden iframe during renewal.
For signout, clear the user and redirect to the end session endpoint:
async function signOut() { await userManager.removeUser(); const url = `https://api.bloksec.io/oidc/session/end` + `?client_id=YOUR_CLIENT_ID` + `&post_logout_redirect_uri=${encodeURIComponent(window.location.origin + '/auth/signin')}`; window.location.href = url;}Troubleshooting
Section titled “Troubleshooting”No refresh token in the response. Add prompt=consent and include offline_access in your scope. Confirm the application has the refresh_token grant type enabled.
ID token validation fails on the issuer. Set authority / the expected iss to https://api.bloksec.io/oidc, including the /oidc suffix — not the bare host.
Trying to decode the access token fails. Access tokens are opaque, not JWTs. Validate them with introspection or UserInfo, not by decoding.
Silent renewal never fires. Set automaticSilentRenew: true and make sure your silent-callback route is reachable. BlokSec always returns expires_in, which client libraries need to schedule renewal.
Errors at signout. Set revokeTokensOnSignout: false and use the end session endpoint as shown above.
What’s next
Section titled “What’s next”- OIDC Reference — every endpoint, all scopes and claims, token lifetimes, and error codes
- Authentication Flow — how BlokSec’s passwordless authentication works under the hood