OIDC Test Client

Test OpenID Connect flows with Zero IDS

Current Auth Method: client_secret_basic Current Response Type: code
Login with SSO Test Client Credentials User Rules Settings

Test Scenarios

Follow these scenarios to test different OIDC flows. Configure the client in Settings before testing.

1. Authorization Code Flow (Standard Web App)

Use Case: The most secure and common flow for server-side web applications. The application (client) exchanges a temporary authorization code for an access token directly with the server (back-channel), ensuring tokens are never exposed to the user's browser.

Console Configuration:

Create a new Client in the Console with these exact settings:

  • Auth Method: client_secret_basic
  • Response Type: code
  • Grant Type: authorization_code
  • Scope: openid, profile, email, offline_access
  • Redirect URI: http://localhost:3001/callback
Test Client Configuration:
  • Go to Settings and enter the Client ID and Client Secret from your new Console client.
  • Auth Method: client_secret_basic
  • Response Type: Authorization Code (code)
  • Action: Click the "Login with SSO" button on the Home Page.
Node.js Setup (openid-client):
const { Issuer } = require('openid-client');

// 1. Discover Issuer
const issuer = await Issuer.discover('http://localhost:3000');

// 2. Initialize Client
const client = new issuer.Client({
  client_id: 'client-scenario-1',
  client_secret: 'secret-scen1',
  redirect_uris: ['http://localhost:3001/callback'],
  response_types: ['code']
});

// 3. Generate Auth URL (Start Login)
const code_verifier = generators.codeVerifier();
const code_challenge = generators.codeChallenge(code_verifier);

const authUrl = client.authorizationUrl({
  scope: 'openid profile email offline_access',
  code_challenge,
  code_challenge_method: 'S256'
});
// -> Redirect user to authUrl

// 4. Handle Callback (After Redirect)
const params = client.callbackParams(req);
const tokenSet = await client.callback('http://localhost:3001/callback', params, { code_verifier });

console.log('Access Token:', tokenSet.access_token);
Expected Result:
  1. Redirect: The browser is redirected to the Identity Server's login page.
  2. Login: User logs in successfully.
  3. Consent: User approves the access request.
  4. Callback: Server redirects back to the Test Client with a code.
  5. Token Exchange: Test Client backend exchanges the code for an access_token, id_token, and refresh_token.
  6. Success: You see the "Profile" page displaying your user details and the raw tokens.

2. Hybrid Flow (Frontend + Backend)

Use Case: Used when a frontend application (SPA) needs an ID Token immediately for UI customization (e.g., showing user avatar) while the backend securely handles the Access Token exchange using the code. This allows for immediate UI updates without waiting for a backend round-trip.

Console Configuration:

Create a new Client (or update existing) with these settings:

  • Auth Method: client_secret_basic
  • Response Type: Select BOTH code and id_token
  • Grant Type: authorization_code, implicit
  • Scope: openid, profile, email
  • Redirect URI: http://localhost:3001/callback
Test Client Configuration:
  • Go to Settings and enter your Client ID and Secret.
  • Auth Method: client_secret_basic
  • Response Type: Hybrid (code + id_token)
  • Action: Click the "Login with SSO" button on the Home Page.
Node.js Setup (openid-client):
// Client Setup
const client = new issuer.Client({
  client_id: 'client-scenario-2',
  client_secret: 'secret-scen2',
  redirect_uris: ['http://localhost:3001/callback'],
  response_types: ['code id_token'] // Hybrid
});

// Generate Auth URL
const authUrl = client.authorizationUrl({
  scope: 'openid profile email',
  response_type: 'code id_token',
  response_mode: 'form_post', // Required for Hybrid/Implicit
  nonce: generators.nonce()
});

// Handle Callback
const params = client.callbackParams(req);
const tokenSet = await client.callback('http://localhost:3001/callback', params, { nonce });

// tokenSet.id_token is available immediately
// tokenSet.access_token is exchanged via code
Expected Result:
  1. Redirect: Browser redirects to Identity Server.
  2. Callback: Server redirects back with both a code and an id_token (usually in the URL fragment or form post).
  3. Validation: The Test Client validates the id_token immediately.
  4. Exchange: The Test Client backend exchanges the code for the full token set (access_token, refresh_token).
  5. Success: Profile page loads, showing that both the initial ID Token and the exchanged tokens were received.

3. Implicit Flow (Legacy/SPA)

Use Case: Historically used for Single Page Applications (SPAs) where tokens were returned directly to the browser. Not Recommended for new applications due to security risks (tokens exposed in URL). Modern SPAs should use Authorization Code Flow with PKCE instead.

Console Configuration:

Create a new Client with these settings:

  • Auth Method: client_secret_basic (or None for public clients)
  • Response Type: id_token OR token (or both)
  • Grant Type: implicit
  • Scope: openid, profile
  • Redirect URI: http://localhost:3001/callback
Test Client Configuration:
  • Go to Settings and enter your Client ID and Secret.
  • Auth Method: client_secret_basic
  • Response Type: Implicit (id_token)
  • Action: Click the "Login with SSO" button on the Home Page.
Node.js Setup (openid-client):
// Client Setup
const client = new issuer.Client({
  client_id: 'client-scenario-3',
  client_secret: 'secret-scen3',
  redirect_uris: ['http://localhost:3001/callback'],
  response_types: ['id_token']
});

// Generate Auth URL
const authUrl = client.authorizationUrl({
  scope: 'openid profile',
  response_type: 'id_token',
  response_mode: 'fragment', // Tokens returned in URL fragment
  nonce: generators.nonce()
});

// Note: Implicit flow callbacks are typically handled 
// entirely in the browser (JavaScript), not the server.
Expected Result:
  1. Redirect: Browser redirects to Identity Server.
  2. Callback: Server redirects back with the id_token directly in the URL fragment (#id_token=...).
  3. No Exchange: There is no backend code exchange. The token is available immediately to the browser.
  4. Success: Profile page displays the ID Token claims. Note that you might not get a Refresh Token in this flow.

4. Client Credentials Flow (Machine-to-Machine)

Use Case: Used for backend-to-backend communication where no user is present (e.g., a daemon service, cron job, or internal microservice). The application authenticates itself to access resources on its own behalf.

Console Configuration:

Create a new Client with these settings:

  • Auth Method: client_secret_post
  • Response Type: N/A (Not used in this flow)
  • Grant Type: client_credentials
  • Scope: Custom resource scopes (e.g., api:read)
Test Client Configuration:
  • Go to Settings and enter your Client ID and Secret.
  • Auth Method: client_secret_post
  • Action: Click the "Test Client Credentials" button on the Home Page.
Node.js Setup (openid-client):
// Client Setup
const client = new issuer.Client({
  client_id: 'client-scenario-4',
  client_secret: 'secret-scen4',
  token_endpoint_auth_method: 'client_secret_post'
});

// Request Token Directly
const tokenSet = await client.grant({
  grant_type: 'client_credentials',
  scope: 'api:read'
});

console.log('Access Token:', tokenSet.access_token);
Expected Result:
  1. Direct Request: The Test Client sends a direct HTTP POST request to the /oidc/token endpoint.
  2. Authentication: It authenticates using the Client ID and Secret.
  3. Response: The Identity Server returns an access_token immediately (JSON response).
  4. Success: The Test Client displays the received Access Token. There is no user login step.

5. Refresh Token Flow

Use Case: Allows an application to obtain a new Access Token without requiring the user to log in again. This is critical for maintaining a seamless user experience in long-running sessions.

Console Configuration:

Ensure your Client has these settings enabled:

  • Grant Type: refresh_token
  • Scope: Must include offline_access
Test Client Configuration:
  • Prerequisite: You must have already logged in using Scenario 1 (Authorization Code) with offline_access scope.
  • Action: On the Profile Page (after login), click the "🔄 Refresh Token" button.
Node.js Setup (openid-client):
// Assuming you have an expired tokenSet with a refresh_token
const refreshToken = tokenSet.refresh_token;

// Refresh the Token
const newTokenSet = await client.refresh(refreshToken);

console.log('New Access Token:', newTokenSet.access_token);
console.log('New Refresh Token:', newTokenSet.refresh_token);
Expected Result:
  1. Request: The Test Client sends a POST /oidc/token request with grant_type=refresh_token and the stored refresh_token.
  2. Response: The Identity Server validates the refresh token and issues a new access_token (and optionally a new refresh_token).
  3. Success: The Profile page updates to show the new Access Token and its new expiration time.

6. Token Introspection

Use Case: Used by Resource Servers (APIs) to validate an incoming Access Token. It checks if the token is active, not expired, and not revoked, and retrieves metadata like scopes and subject.

Test Client Configuration:
  • Prerequisite: You must have a valid Access Token or Refresh Token (from any previous scenario).
  • Action: On the Profile Page, click the "🔍 Introspect" button next to the Access Token or Refresh Token.
Node.js Setup (openid-client):
// Introspect a token (access_token or refresh_token)
const token = 'eyJhbGciOiJ...';

const result = await client.introspect(token, 'access_token');

console.log('Active:', result.active);
console.log('Scopes:', result.scope);
Expected Result:
  1. Request: The Test Client sends a POST /oidc/token/introspection request to the server.
  2. Response: The server returns a JSON object containing active: true (if valid), exp (expiration), scope, and other metadata.
  3. Success: You see a page displaying the raw JSON response from the introspection endpoint.

7. Token Revocation

Use Case: Allows a client to explicitly invalidate a token before its natural expiration. This is important for "Sign Out" functionality or when a device is lost/compromised.

Test Client Configuration:
  • Prerequisite: You must have a valid Access Token or Refresh Token.
  • Action: On the Profile Page, click the "🚫 Revoke" button next to the Access Token or Refresh Token.
Node.js Setup (openid-client):
// Revoke a token
const token = 'eyJhbGciOiJ...';

await client.revoke(token, 'access_token');

console.log('Token revoked successfully');
Expected Result:
  1. Request: The Test Client sends a POST /oidc/token/revocation request to the server.
  2. Response: The server invalidates the token and returns a 200 OK.
  3. Success: You see a "Revocation Successful" message. If you try to use that token again (e.g., for Introspection or UserInfo), it will fail or show as inactive.

8. UserInfo Endpoint

Use Case: A standard OIDC endpoint that allows the client to retrieve the user's profile information (claims) using a valid Access Token. Useful when the ID Token doesn't contain all necessary user details.

Test Client Configuration:
  • Prerequisite: You must have logged in with the profile and email scopes.
  • Action: On the Profile Page, click the "👤 UserInfo" button.
Node.js Setup (openid-client):
// Fetch UserInfo using Access Token
const accessToken = tokenSet.access_token;

const userInfo = await client.userinfo(accessToken);

console.log('User Email:', userInfo.email);
console.log('User Sub:', userInfo.sub);
Expected Result:
  1. Request: The Test Client sends a GET /oidc/me request with the Access Token in the Authorization header.
  2. Response: The server returns the user's claims (e.g., sub, name, email, picture).
  3. Success: The Profile page reloads and displays a new section "UserInfo API Result" with the fetched data.

9. RP-Initiated Logout

Use Case: Allows the application (Relying Party) to initiate a logout process at the Identity Server. This ensures the user is logged out of the SSO session, not just the local application session.

Test Client Configuration:
  • Prerequisite: You must be logged in.
  • Action: Click the "Logout" button in the top right corner of the Profile Page.
Node.js Setup (openid-client):
// Generate Logout URL
const logoutUrl = client.endSessionUrl({
  id_token_hint: tokenSet.id_token,
  post_logout_redirect_uri: 'http://localhost:3001'
});

// Redirect user to logoutUrl
res.redirect(logoutUrl);
Expected Result:
  1. Local Logout: The Test Client destroys its local session.
  2. Redirect: The browser is redirected to the Identity Server's end_session_endpoint.
  3. Server Logout: The Identity Server terminates the user's SSO session.
  4. Final Redirect: The user is redirected back to the Test Client's Home Page (or a "Signed Out" page).