Applications — OIDC¶
Overview¶
OIDC applications are clients that use JustIAM as an OpenID Connect Provider. JustIAM supports the Authorization Code flow with optional PKCE.
Application types¶
| Type | Use case |
|---|---|
oidc |
Server-side web application (confidential client, has a secret) |
spa |
Single-page application (public client, PKCE required) |
Creating an application¶
UI: Administration → Applications → + Create Application
API:
POST /api/v1/applications
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "My App",
"description": "Internal dashboard",
"type": "oidc",
"redirect_uris": ["https://app.example.com/callback"],
"allowed_scopes": ["openid", "profile", "email", "groups"],
"grant_types": ["authorization_code", "refresh_token"],
"token_expiry": 3600,
"access_restricted": false,
"show_in_dashboard": true,
"launch_url": "https://app.example.com",
"mfa_policy": "inherit"
}
On creation JustIAM generates a client_id and client_secret.
Key fields¶
| Field | Description |
|---|---|
friendly_name |
Optional display label shown in the UI instead of name. Falls back to name when empty |
client_id |
Public identifier sent in authorization requests |
client_secret |
Credential for the token endpoint (confidential clients only) |
redirect_uris |
Allowed callback URLs. Supports exact strings or regex: prefixed patterns (e.g. regex:^https://app\.example\.com/auth/callback.*). Patterns are full-string matched. |
allowed_scopes |
Scopes the client may request. Standard: openid, profile, email, groups |
grant_types |
authorization_code and/or refresh_token |
is_public |
Public client (no secret); PKCE becomes mandatory |
require_pkce |
Require PKCE even for confidential clients |
token_expiry |
Access/ID token lifetime in seconds (default 3600) |
access_restricted |
If true, only explicitly granted users/groups can authenticate |
show_in_dashboard |
Show in the end-user My Apps portal |
launch_url |
Launch URL shown in the portal |
app_group |
Visual grouping label in the portal (e.g. "Productivity") |
icon_url |
Application icon shown in the portal |
mfa_policy |
Override global MFA policy for this app (inherit / disabled / any / otp / passkey) |
backchannel_logout_uri |
OIDC Backchannel Logout endpoint; JustIAM POSTs a logout token here when the user logs out |
post_logout_uris |
Allowed redirect URIs for RP-Initiated Logout (post_logout_redirect_uri query parameter). Must be registered to prevent open-redirect attacks |
Scopes¶
| Scope | Claims included |
|---|---|
openid |
sub, iss, aud, iat, exp |
profile |
name, given_name, family_name, preferred_username |
email |
email |
groups |
groups (array of group names) |
Additional claims can be added via Claim Mappings.
Access control¶
When access_restricted = true, only explicitly granted users and groups can complete an authorization flow for this application. All others see a branded Access Denied page at the /oauth2/authorize step.
The denial happens before an authorization code is issued, so the relying party never receives a code that it cannot exchange. The page includes a "Return to {application}" button that redirects the browser back to the registered redirect_uri with an error=access_denied query parameter per RFC 6749 §4.1.2.1, allowing the application to react to the rejection.
Grant access via the Access tab on the application page, or via the API:
POST /api/v1/applications/{id}/access/groups
{ "group_id": "<uuid>" }
POST /api/v1/applications/{id}/access/users
{ "user_id": "<uuid>" }
Regenerating the client secret¶
Warning
All existing integrations using the old secret will stop working immediately.
Claim mappings¶
Claim mappings let you add custom claims to the ID token and access token. See Claim Mappings.
MFA policy per application¶
You can require a specific MFA level for an individual application by setting mfa_policy to a value other than inherit. This overrides the global setting for that application only.
| Value | Behaviour |
|---|---|
inherit |
Use the global mfa_policy setting |
disabled |
No MFA, even if global policy requires it |
any |
Any enrolled MFA method accepted |
otp |
TOTP required |
passkey |
Passkey required |
Token simulator¶
The token simulator lets you preview the exact access token and ID token claims a user would receive — including claim mappings and claim script patches — without issuing any real credentials or creating a session.
To open it, click the flask icon (🧪) in the Applications table row for any OIDC app.
What it simulates¶
- Standard claims (
sub,iss,aud,scope,email,name, …) - Custom claim mappings configured on the application
- Output from the claim script (if configured), applied on top of the base claims
API¶
POST /api/v1/applications/{id}/simulate
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"user_id": "<user-uuid>",
"scopes": ["openid", "email", "profile"]
}
Response:
{
"type": "oidc",
"has_access": true,
"access_claims": { "sub": "...", "email": "...", ... },
"id_claims": { "sub": "...", "email": "...", ... },
"script_error": "<only present if the claim script fails>"
}
has_access is false when the application has Access restricted enabled and the user is not in any allowed group or has no explicit grant.