Skip to main content

OpenID Connect (OIDC)

Integrate with Propper's OpenID Connect implementation for user authentication.

Discovery Document

The OIDC discovery document contains all endpoints and capabilities:

curl "https://auth.propper.ai/.well-known/openid-configuration"

Response:

{
"issuer": "https://auth.propper.ai",
"authorization_endpoint": "https://auth.propper.ai/oauth2/authorize",
"token_endpoint": "https://auth.propper.ai/oauth2/token",
"userinfo_endpoint": "https://auth.propper.ai/oauth2/userinfo",
"jwks_uri": "https://auth.propper.ai/.well-known/jwks.json",
"scopes_supported": ["openid", "profile", "email"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"],
"code_challenge_methods_supported": ["S256"]
}

ID Tokens

When requesting the openid scope, you receive an ID token containing user identity claims.

Requesting an ID Token

Include openid in your scope:

https://auth.propper.ai/oauth2/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=openid profile email&
state=random_state&
code_challenge=YOUR_CHALLENGE&
code_challenge_method=S256

ID Token Claims

{
"iss": "https://auth.propper.ai",
"sub": "user_123",
"aud": "your_client_id",
"exp": 1704067200,
"iat": 1704063600,
"nonce": "your_nonce_value",
"email": "user@example.com",
"name": "John Doe"
}
ClaimScope RequiredDescription
subopenidUnique user identifier
emailemailUser's email address
nameprofileUser's display name
nonce-Echo of your nonce parameter

UserInfo Endpoint

Retrieve additional user information using an access token:

curl "https://auth.propper.ai/oauth2/userinfo" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Response:

{
"sub": "user_123",
"email": "user@example.com",
"name": "John Doe",
"roles": ["admin", "user"],
"scope": "openid profile email"
}

Nonce Parameter

Use the nonce parameter to prevent replay attacks:

  1. Generate a random nonce before authorization
  2. Include it in the authorization request
  3. Verify the nonce in the ID token matches
// Generate nonce
const nonce = generateRandomString(32);
sessionStorage.setItem('oidc_nonce', nonce);

// Include in authorization URL
const authUrl = `https://auth.propper.ai/oauth2/authorize?...&nonce=${nonce}`;

// After receiving ID token, verify nonce
const idToken = decodeJwt(response.id_token);
if (idToken.nonce !== sessionStorage.getItem('oidc_nonce')) {
throw new Error('Nonce mismatch - possible replay attack');
}

Integrating with OIDC Libraries

Most OAuth/OIDC libraries can auto-configure using the discovery document.

JavaScript (oidc-client-ts)

import { UserManager } from 'oidc-client-ts';

const userManager = new UserManager({
authority: 'https://auth.propper.ai',
client_id: 'YOUR_CLIENT_ID',
redirect_uri: 'https://yourapp.com/callback',
scope: 'openid profile email sign:read',
});

// Start login
await userManager.signinRedirect();

// Handle callback
const user = await userManager.signinRedirectCallback();
console.log('User:', user.profile);

Python (authlib)

from authlib.integrations.requests_client import OAuth2Session

client = OAuth2Session(
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
scope='openid profile email'
)

# Fetch discovery document
client.fetch_metadata('https://auth.propper.ai/.well-known/openid-configuration')

# Create authorization URL
uri, state = client.create_authorization_url(
'https://auth.propper.ai/oauth2/authorize'
)

.NET (Microsoft.AspNetCore.Authentication.OpenIdConnect)

services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://auth.propper.ai";
options.ClientId = "YOUR_CLIENT_ID";
options.ClientSecret = "YOUR_CLIENT_SECRET";
options.ResponseType = "code";
options.Scope.Add("profile");
options.Scope.Add("email");
});

Session Management

Checking Session Status

Your application should periodically verify the user's session is still valid:

  1. Check if the access token is expired
  2. Attempt to refresh using the refresh token
  3. If refresh fails, redirect to login

Logout

To properly log out:

  1. Revoke the refresh token
  2. Clear local session data
  3. Optionally redirect to the authorization server's logout endpoint
async function logout() {
// Revoke refresh token
await fetch('https://auth.propper.ai/oauth2/revoke', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: `token=${refreshToken}&token_type_hint=refresh_token`
});

// Clear local storage
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');

// Redirect to login
window.location.href = '/login';
}