Skip to main content

OIDC Applications

Register an application that speaks OpenID Connect (OIDC) as a custom application, so your users can sign in to it with their Prism credentials instead of a separate account.

Prism acts as the OpenID Provider. Your application is an OIDC client: it redirects the user to Prism to sign in, and Prism redirects the user back with an authorization code that the application exchanges for tokens.

OIDC is the right choice for anything new, and for single-page applications. If you are still deciding, see Choosing a Protocol.

caution

Mobile and native desktop applications cannot be registered. The two redirect URI forms a native application uses (a private-use scheme such as com.example.app:/oauth2redirect, and an http:// loopback address such as http://127.0.0.1:3000/callback) are both rejected, so a native application has no valid redirect URI to register. Register applications that return to an https:// address: server-side web applications and single-page applications.

Prerequisites​

  • The target application must support OpenID Connect with the authorization code flow.
  • You must have administrator access to the application in order to configure its authentication settings.
  • You need to know the application's redirect URI (also called the callback URL or sign-in redirect URI) and the URL users should land on when they open it.

Available Actions​

ActionDescriptionLink
Add ApplicationRegister a new OIDC applicationCreate an OIDC Application
Reveal client secretRead the current secret for a confidential clientRevealing the Secret
Regenerate client secretReplace the secret with a new oneRegenerating the Secret

How OIDC SSO Works​

  1. A user opens the application, either directly or from its tile in the Prism portal.
  2. The application detects that the user is not authenticated and redirects them to Prism's authorization endpoint.
  3. If the user is not already signed in to Prism, they are prompted to authenticate. If they already have a Prism session, this step is invisible.
  4. Prism redirects the user back to one of the application's registered redirect URIs, with an authorization code.
  5. The application exchanges the code for an ID token (who the user is), an access token (what the user may do), and a refresh token.
  6. The application validates the tokens and starts its own session.
caution

Prism authenticates the user; your application decides what that user is allowed to do. Assigning users or groups to the application controls the portal tile and the role claims in the token. It does not gate the login. See Prism Authenticates, Your Application Authorizes.


Create an OIDC Application​

Step-by-Step Guide​

Part 1: Gather the Application's Details​

From the application you are integrating, collect:

  • The redirect URI it expects Prism to send users back to after authentication. Frameworks name this differently (callback URL, sign-in redirect URI, reply URL), but it is the same value. Many applications publish it as a fixed path, for example https://app.example.com/auth/callback.
  • The URL users should land on when they open the application, for example https://app.example.com/.
  • Whether the application can keep a secret. A server-side application can; a browser-based single-page application cannot. See Public and Confidential Clients.
  • Any sign-out URLs the application supports, if you intend to configure logout.

Part 2: Register the Application in Prism​

  1. Navigate to Admin Portal > Custom Applications from the sidebar.
  2. Start a new application and choose OIDC as the protocol.
  3. Fill in the application details:
    • Application Name, a descriptive name for the application.
    • Client ID, the identifier the application will use to identify itself to Prism. You choose this value; see Client ID for the rules.
    • Description (optional), what the application is for.
    • Application Icon (optional), the icon shown on the portal tile.
    • Home URL, where the portal tile sends the user.
    • Redirect URIs, at least one. See Redirect URIs.
  4. Choose whether the application is a confidential or a public client. See Public and Confidential Clients.
  5. Configure logout behaviour, including the post-logout redirect URI choice. See Logout.
  6. Save the application.

Part 3: Configure the Application​

Prism now shows the connection details the application needs.

  1. Copy the discovery URL and paste it into your application's OIDC configuration. Most libraries need nothing else; they read every endpoint from it.
  2. Copy the client ID.
  3. For a confidential client, reveal and copy the client secret, and store it wherever your application keeps its secrets.
  4. Deploy the configuration and test the sign-in.

See Connection Details Prism Provides for what each value is.

tip

Test with a single user in a private or incognito browser window before rolling the application out. A fresh window makes it obvious whether the sign-in really works, or whether you are only seeing an existing session.

Field Reference​

FieldTypeRequiredDescription
Application NameTextYesA descriptive name for the application in Prism.
Client IDTextYesThe identifier the application uses to identify itself to Prism. You choose it. Cannot be changed after creation. See Client ID.
DescriptionTextNoA description of the application's purpose.
Application IconImageNoAn icon for the application's portal tile.
Home URLURLYesWhere the portal tile sends the user. Absolute https://, no wildcards. See Home URL.
Redirect URIsList of URIsYesWhere Prism may return the user after authentication. At least one. See Redirect URIs.
Public clientToggleYesWhether the application can keep a secret. Public clients get no secret and must use PKCE. Cannot be changed after creation. See Public and Confidential Clients.
Require PKCE (S256)ToggleNoShown only for a confidential client, and on by default. For a public client the method is fixed at S256, shown read-only, and cannot be turned off. plain is never accepted for either kind.
Post-logout redirect URIsChoiceYesInherit the redirect URIs, an explicit list, or none. See Post-logout redirect URIs.
Front-channel logoutToggleNoOff by default. Turns front-channel logout on and reveals the Front-channel logout URL field. That field is hidden, and its value is not saved, while this toggle is off.
Front-channel logout URLURLNoLoaded in the user's browser at sign-out so the application can clear its session. Plain https://. Only available when the Front-channel logout toggle is on.
Back-channel logout URLURLNoCalled server-to-server at sign-out. Plain https://. More reliable than front-channel.
Include session ID in the back-channel logout tokenToggleNoOff by default. Adds the sid claim to the back-channel logout token, so the application can end one specific session rather than all of the user's sessions.
Require user consent at first sign-inToggleNoOff by default. The first time a user signs in to this application, Prism shows them a consent screen naming it before issuing tokens.
EnabledToggleYesOn by default. Turning it off disables the underlying client, so sign-in for the application stops working until it is turned back on. Shared with SAML applications; it is the last control in the dialog, below the protocol-specific fields.

Client ID​

The client ID is the name your application uses to identify itself to Prism. Unlike most identity systems, Prism lets you choose it, so pick something recognisable; the application's name is usually the best answer.

RuleDetail
Allowed charactersLetters, digits, and the characters ., _, and -
First characterMust be a letter or a digit
Length1 to 120 characters
UniquenessMust be unique within your organization

Examples of valid client IDs: internal-wiki, expense_portal, app.example.com.

Spaces, slashes, colons, and other punctuation are rejected. A URL is not a valid OIDC client ID, even though it is a common choice for a SAML entity ID. Two consecutive dots (..) are also rejected, because the client ID appears inside URLs that Prism builds. A leading or trailing space is rejected rather than trimmed for you, for the same reason it is on a redirect URI.

Reserved client IDs​

A small set of names is reserved and cannot be taken. Each already exists in your realm but is hidden from the applications list, so registering one would otherwise fail with an "already exists" error pointing at something you cannot see. The comparison is case-insensitive.

ReservedWhy
account, account-console, admin-cli, broker, realm-management, security-admin-console, admin-permissionsBuilt-in clients that the identity server creates in every realm
aws-console, aws-real-consoleInternal Prism clients
Anything beginning with ckauth-The whole namespace is reserved for Prism's own clients, including ones added in future releases

If a client ID is refused as reserved, choose a different one; the name is not available whatever it is used for.

warning

The client ID is baked into your application's configuration and cannot be changed after the application is created. If you need a different one, register a new application and retire the old one.

Home URL​

The Home URL is where the application's tile in the Prism portal sends the user. Normally that is the application's front page, for example https://app.example.com/. It is required.

It must be an absolute https:// URL. Wildcards are not accepted, and neither is http://, so a Home URL always points at a real, reachable address. A # fragment is not accepted either. See Hash-routed applications for what to register instead.

Because OIDC has no IdP-initiated sign-in, the Home URL is what makes the portal tile work at all: clicking the tile opens the application, and the application starts its own login, which returns immediately because the user's Prism session already exists. A wrong Home URL shows up as a tile that lands users on the wrong page, not as a login failure.

Redirect URIs​

A redirect URI is a location Prism is willing to send a user back to after they sign in. At least one is required. The value you register must match what the application actually asks for.

This list is a security boundary, not a convenience setting. It is the only thing preventing someone from starting a sign-in for your application and having Prism deliver the resulting authorization code to a server they control. Prism therefore validates it strictly.

The rules​

RuleDetail
Must be absoluteThe full URI including the scheme and host, for example https://app.example.com/auth/callback. Relative paths are rejected.
Must use https://Authorization codes travel on this URL and must not cross the network in the clear.
http:// is never acceptedThere is no loopback exception in any environment: http://127.0.0.1:3000/callback and http://[::1]:3000/callback are rejected along with http:// to every other host. Use an https:// address even for local development.
No private-use schemeshttps:// is the only scheme accepted. A private-use scheme such as com.example.app:/oauth2redirect (the RFC 8252 form a mobile or native desktop app registers) is not supported.
Wildcards only as a trailing /*A * is permitted only at the very end, immediately after a /, for example https://app.example.com/* or https://app.example.com/callback/*.
A wildcard cannot be combined with a query stringThe two cannot coexist. https://app.example.com/*?next=1 is rejected because the * is no longer the final character, and https://app.example.com/callback?next=/* is rejected because a ? switches the entry back to an exact match, leaving the * to match nothing. Drop one of the two.
No leading or trailing whitespaceA value with a space on either end is rejected, not trimmed. The URI is stored exactly as sent, so https://app.example.com/cb and https://app.example.com/cb would become two separate entries that look identical.
Maximum length255 characters
No embedded credentialsA user@host form is rejected.
Scheme and host in lower caseHTTPS://App.Example.com/cb is rejected; write https://app.example.com/cb. Internationalized domain names must be given in their punycode form.
No # fragmentA redirect URI may not contain a # at all. Hash-routed applications are still supported. See Hash-routed applications.
note

The whitespace rule catches API callers rather than the portal. The Custom Applications form strips spaces as you type and trims each URI before submitting, so a value pasted into the form is cleaned up for you. A request sent straight to the API (by the Terraform provider, or by your own script) is not, and a stray space is a 400. The same rule applies to the Client ID, the Home URL and the logout URLs.

Why the wildcard needs the slash​

https://app.example.com/* is accepted. https://app.example.com* (the same value without the slash) is rejected.

The reason is that a wildcard is a prefix match. Without the slash, the pattern https://app.example.com* matches anything that merely begins with those characters, and that includes https://app.example.com.attacker.com/steal. An attacker who registers that domain could start a sign-in for your application and have Prism hand them the authorization code.

The / forces the host to end where you meant it to end. With https://app.example.com/*, only paths under that exact host match, which is what you intended in the first place.

tip

Prefer listing exact redirect URIs over using a wildcard. Most applications need only one or two, and an exact list is the strongest configuration. Reach for https://host/* only when the application genuinely returns to varying paths.

Examples​

ValueAcceptedWhy
https://app.example.com/auth/callbackYesAbsolute, HTTPS, exact path
https://app.example.com/*YesTrailing wildcard after a complete host
https://app.example.com/callback/*YesTrailing wildcard after a path
https://app.example.com*NoWildcard without the /; would also match app.example.com.attacker.com
https://*.example.com/callbackNoThe wildcard must be at the end, not in the host
https://app.example.com/*?next=1NoThe * must be the last character; a wildcard and a query string cannot be combined
https://app.example.com/callback?next=/*NoA query string turns the entry back into an exact match, so the * would match nothing
*NoWould accept any destination at all
http://app.example.com/callbackNohttp:// is not accepted
http://127.0.0.1:3000/callbackNohttp:// is not accepted; there is no loopback exception
http://localhost:3000/callbackNohttp:// is not accepted
com.example.app:/oauth2redirectNoOnly https:// is accepted; private-use schemes are not supported
https://app.example.com/cb NoTrailing whitespace; the value is rejected rather than trimmed
/auth/callbackNoNot absolute
https://app.example.com/#/callbackNoContains a #; see Hash-routed applications for what to register instead

Hash-routed applications​

Single-page applications that route on the URL fragment (Angular's HashLocationStrategy is the common case, hash-mode Vue Router the other) come back to an address with a # in it, such as https://app.example.com/#/callback.

You cannot register that address. A redirect URI containing a # is rejected, and the reason is not a Prism preference: the identity server refuses to store one, because RFC 6749 §3.1.2 forbids a fragment in a redirection endpoint. The same applies to the Home URL and to post-logout redirect URIs.

These applications are still fully supported, and they do not need changing. Register the fragment-less prefix with a trailing wildcard instead:

https://app.example.com/*

A wildcard entry is matched as a prefix against the whole address the application asks to return to, fragment included. So this one entry accepts https://app.example.com/#/callback, https://app.example.com/#/auth/done and any other hash route the application uses, with no change to the application's own configuration.

caution

The wildcard is what makes this work. Registering the fragment-less URL on its own (https://app.example.com/ or https://app.example.com/callback) is an exact match and will not accept a request for https://app.example.com/#/callback. Sign-in fails with an invalid redirect URI.

If you would rather not grant a whole path prefix, the alternative is to change the application to use a fragment-less callback path such as https://app.example.com/callback, and let it move to the hash route itself once the sign-in has completed.

For the other fields:

FieldA # isWhat to do instead
Redirect URIsRejectedRegister https://app.example.com/*
Home URLRejectedRegister the fragment-less page, https://app.example.com/. The application resolves its own default route when it loads
Post-logout redirect URIsRejectedRegister the fragment-less sign-out landing page. A sign-out destination has no route to carry
Back-channel logout URLRejectedPut the value in the path or the query. A fragment is never sent in an HTTP request, so it would be stored and then silently ignored
Front-channel logout URLAllowedNothing. This is the one field where a fragment is both stored and delivered: the browser is what loads it, so the hash reaches your router

Public and Confidential Clients​

Every OIDC application is one of two kinds, and the distinction is simply whether the application is able to keep a secret.

Confidential clientPublic client
Use forServer-side web applications and backend servicesSingle-page applications
Has a client secretYesNo
How it proves itselfThe client secret, held on a server the user never seesPKCE, which proves the code is being redeemed by whoever started the login

A public client has no secret because it cannot keep one. Anything shipped to a browser can be read by the user, so a secret embedded there is not a secret. Instead, a public client uses PKCE (Proof Key for Code Exchange): it generates a one-time value at the start of the login and must present the matching proof when it redeems the authorization code.

note

Public clients are supported for single-page applications, not for mobile or native desktop applications. Those are public clients too, but they cannot be registered at all, because every redirect URI form they use is rejected. See Redirect URIs.

Prism requires PKCE with the S256 method for public clients, and this cannot be disabled. Every mainstream OIDC library supports it, usually with no configuration at all beyond declaring the client as public. If your library offers a choice of PKCE method, choose S256.

The weaker plain method is never accepted, for public or confidential clients. It sends the one-time value unprotected, which defeats the point of PKCE.

A confidential client is not required to use PKCE, because the client secret already authenticates it. You may still enable S256 on one, and it is good practice to do so.

tip

If you are unsure which kind you have, ask where the token exchange happens. If the exchange runs on your server, the application is confidential. If it runs in the user's browser or on their device, it is public.

warning

Whether an application is public or confidential is fixed when it is created and cannot be changed afterwards. If an application changes shape (a server-rendered app rebuilt as a single-page app, for example), register a new application for it.

Logout​

Post-logout redirect URIs​

A post-logout redirect URI is where a user may be sent after signing out. Prism asks you to make this an explicit choice rather than leaving a field blank, because "blank" is genuinely ambiguous in OIDC: an empty list conventionally means inherit every redirect URI, not allow none. An admin who clears the field expecting to lock logout down would get the opposite of what they intended.

You therefore choose one of three options:

OptionBehaviourUse when
Inherit the redirect URIsAny registered redirect URI is also accepted as a post-logout destinationThe common case. Sign-out returns users to the same application they signed in to
An explicit listOnly the URIs you list here are acceptedSign-out should land somewhere other than the sign-in destinations, such as a marketing page or a shared landing page
NoneNo post-logout redirect is accepted; the user stays on Prism's sign-out pageYou want sign-out to end on Prism, with no hand-back to the application

Post-logout redirect URIs follow the same validation rules as Redirect URIs, including the rule that they may not contain a #. Two separate things forbid it here: the identity server rejects a fragment in a post-logout redirect URI outright, and Prism stores the whole list as a single ##-separated value, in which a # is a separator rather than an inert suffix. See Hash-routed applications.

note

Choose the inherit or none option rather than trying to express it as a URI. Prism rejects the bare + and - shorthands some OIDC tooling uses for "inherit everything" and "allow nothing"; those are choices, not addresses, so make them as choices.

Front-channel and back-channel logout​

These two URLs let Prism tell your application that a user's session has ended, so the application can clear its own session rather than leaving the user apparently still signed in.

SettingWhat it doesNotes
Front-channel logout URLPrism loads this URL in the user's browser during sign-out, so the application can clear its cookiesRequires the user's browser to be present. Modern browsers restrict third-party cookies, which can make this unreliable
Back-channel logout URLPrism calls this URL server-to-server when the session endsMore reliable. Requires an endpoint your application exposes and Prism's servers can reach

Both are optional. Leave them empty if the application manages its own session lifetime; the user's Prism session still ends when they sign out of Prism.

Both must be https:// URLs, and unlike redirect URIs neither accepts a wildcard: these are literal destinations rather than values matched against something the application sends, so a * would have nothing to match. A loopback address would be no use here either (Prism's servers call the back-channel URL, so a 127.0.0.1 would point at Prism, not at your machine), and http:// is rejected on these fields exactly as it is on a redirect URI.

The two fields differ on one point, and it follows from who dereferences them:

  • The front-channel URL may contain a single #. The user's browser is what loads it, and a browser keeps the fragment, so a hash route reaches your application's router. Prism adds the sid and iss parameters the OIDC front-channel logout specification requires before the #, so your server still receives them. This is the only field in an OIDC application where a fragment is accepted.
  • The back-channel URL may not. It is called server-to-server, and a fragment is never transmitted in an HTTP request; your endpoint would be called at the path alone, with everything after the # discarded. Rather than store a value that quietly does nothing, Prism rejects it. Put whatever you needed in the path or the query instead.

The Front-channel logout URL field is only shown when the Front-channel logout toggle is on, and its value is only saved while that toggle stays on. Turning the toggle off and saving removes the URL. The back-channel URL has no such toggle; it is a plain optional field.

Connection Details Prism Provides​

After you save the application, Prism shows the values your application needs. They fall into two groups, and the distinction matters when you are integrating more than one application.

Per-realm values​

These describe your organization's Prism tenant. They are identical for every application you register, so once you have integrated one application you already have them.

ValueWhat it is
IssuerThe identity of your Prism tenant as an OpenID Provider. Tokens carry it in the iss claim, and your application should verify it
Discovery URLThe .well-known/openid-configuration document listing every endpoint below
Authorization endpointWhere users are sent to sign in
Token endpointWhere authorization codes are exchanged for tokens
UserInfo endpointWhere the application can fetch the signed-in user's profile
JWKS URIThe public keys used to verify Prism's token signatures
End-session endpointWhere the application sends users to sign out

The discovery URL follows this shape, where the host is your Prism authentication host and the realm is your organization's realm:

https://<prism-auth-host>/realms/<realm>/.well-known/openid-configuration
tip

The discovery URL is the value to paste into most OIDC libraries. Give a library the discovery URL and it fetches the issuer, all four endpoints, and the signing keys for itself, including new signing keys when they rotate. Configure the individual endpoints by hand only when your library has no discovery support.

Per-client values​

These are unique to this application.

ValueWhat it is
Client IDThe identifier you chose when creating the application
Client secretThe secret for a confidential client. Not present for a public client. See Client Secret Handling
Redirect URIsThe redirect URIs you registered, shown back so you can confirm they match what the application sends

Roles in Tokens​

The roles you assign to a user for this application are placed in resource_access.{clientId}.roles, where {clientId} is this application's client ID.

warning

Roles appear in the access token, not the ID token. An application that only inspects the ID token (which is very common for pure-SSO integrations, where the ID token is all that is needed to identify the user) will find no roles there and may conclude that role mapping is broken. It is not. Read the access token, or call the UserInfo endpoint, to see the user's roles.

Remember that these roles are input to your authorization decision. Prism does not enforce them; your application must. See Prism Authenticates, Your Application Authorizes.

Client Secret Handling​

Confidential clients have a client secret. Public clients do not, and nothing in this section applies to them.

Where the secret lives​

Prism does not keep a copy of the client secret. The secret exists in your organization's realm, and Prism reads it on demand when you ask to see it. There is no stored duplicate to fall out of date, and nothing to leak from Prism's own records.

Revealing the secret​

The Reveal action fetches the current secret at that moment; it is not showing you a cached copy. You can reveal it as many times as you need; revealing does not change the secret and does not affect a running application.

warning

Revealing a secret requires the SSO admin role, the same role as creating, updating and deleting an application. Reading a client secret is treated as being at least as sensitive as editing the application it belongs to, because anyone holding the secret can obtain tokens as that client.

An admin below that role gets a 403 whose message reads "Only SSO admins can create, update or delete custom applications". That wording lists only the mutating actions and does not mention revealing a secret, so the refusal looks like a bug. It is not: it is the same role check, and the answer is to have an SSO admin reveal the secret.

warning

Client secrets are long. Expect roughly 86 characters. If you are storing the secret in a configuration field, an environment variable, or a secrets manager entry with a length limit, check that limit before you paste; a field sized for a 32-character value will silently truncate the secret, and the only symptom will be authentication failures that look like a wrong password.

Regenerating the secret​

Regenerating replaces the secret with a new one. This is a hard replace with no grace period.

danger

There is no dual-secret rotation window. The moment you regenerate, the old secret stops working. Your application will fail to authenticate, and stay broken, until the new secret is deployed to it. Plan for downtime between those two moments.

Because of this, do not regenerate a secret casually, and never regenerate one to "check that it works".

Runbook: responding to a leaked secret​

If a client secret has been exposed (committed to a repository, pasted into a ticket, or logged), it must be replaced. This will interrupt the application, so the goal is to make the interruption as short as you can rather than to avoid it.

  1. Plan the cutover. Pick a window, and tell whoever depends on the application that it will be briefly unavailable. If the leak is serious enough, that window is now and the notice is after the fact.
  2. Have the deployment ready to go. Get the change that reads the new secret staged and ready to ship: pipeline green, approvals in hand, the secrets-manager entry ready to update. Everything except the value itself should be done in advance.
  3. Regenerate the secret in Prism, and copy the new value immediately.
  4. Deploy it immediately. Push the new value to your secret store and restart or reload the application.
  5. Verify a sign-in end to end before you call it done.
  6. Deal with the leak itself. Rotating the secret stops it being useful, but the exposed copy is still out there. Purge it from the repository history, ticket, or log where it appeared.

Between steps 3 and 4 the application cannot authenticate anyone. That gap is unavoidable (it is the cost of a credential with no overlap window), so the work is in making it short, not in pretending it is not there.

Troubleshooting​

IssueSolution
Sign-in fails with an invalid or mismatched redirect URIThe URI the application sent does not exactly match a registered one. Matching is exact, including scheme, host, port, path, and trailing slash. Compare the URI in the error or in the browser's address bar against the registered list.
A redirect URI is rejected when you try to save itCheck it against the rules. The most common causes are http:// instead of https:// (including a 127.0.0.1 or localhost address, for which there is no exception), a wildcard written without the /, a wildcard combined with a query string, and, for API callers, a leading or trailing space on a pasted value.
A client ID is rejected as reservedThe name belongs to a built-in or Prism-managed client that is hidden from the applications list. See Reserved client IDs for the full list, and choose another name.
Revealing a client secret returns 403 Only SSO admins can create, update or delete custom applicationsRevealing a secret needs the SSO admin role too, even though the message names only the mutating actions. See Revealing the secret.
Authentication fails with an invalid client or invalid client secret errorThe secret configured in the application does not match the current one. Reveal the secret in Prism and compare it in full; a truncated value is the usual cause. If the secret was regenerated, deploy the new value.
A public client fails when redeeming the authorization codePKCE is required and cannot be disabled. Confirm the application sends a code challenge using the S256 method, and that it is registered as a public client.
No roles appear for the userRoles are in the access token, not the ID token. Read the access token or call the UserInfo endpoint. Also confirm the user or one of their groups is assigned to this application.
A user who should not have access can still sign inExpected. Prism assignment does not gate authentication. The application must enforce its own authorization from the roles in the access token. See Prism Authenticates, Your Application Authorizes.
Sign-out leaves the user on an error pageThe post-logout redirect the application requested is not permitted by the current post-logout option. Either add it to the explicit list, or switch to inheriting the redirect URIs.
The application still shows the user as signed in after they sign out of PrismThe application is holding its own session. Configure a back-channel logout URL, or shorten the application's session lifetime.