Security Setup
Choosing an identity provider, wiring up an external one, and getting the claim mapping right before anyone signs in.
Stroom authenticates with OpenID Connect. Which provider it uses is a single setting, and it is worth getting right early, because the choice determines where accounts live and how people are matched to their permissions.
This page covers authentication: proving who someone is. What they are then allowed to do is Users and permissions.
The options
stroom.security.authentication.openId.identityProviderType takes one of:
| Value | Accounts live | Use for |
|---|---|---|
INTERNAL_IDP | In Stroom | A standalone system, evaluation, or anywhere with no existing provider |
EXTERNAL_IDP | In your provider | Any estate that already has one |
Stroom defaults to INTERNAL_IDP, and accepts only INTERNAL_IDP or EXTERNAL_IDP. Any other value, such as NO_IDP or the removed TEST_CREDENTIALS, stops it starting.
Stroom Proxy has the same setting with a different choice. It defaults to NO_IDP, meaning it authenticates nobody itself, which suits a remote proxy that only forwards onward; set EXTERNAL_IDP to have it check tokens from your provider. INTERNAL_IDP is not valid for a proxy at all, because a proxy has no accounts of its own, and NO_IDP is not valid for Stroom.
Internal
Stroom is its own identity provider. It holds the accounts, the passwords and the password policy, and Security → Manage Accounts is where they are administered.
This is the right choice for a standalone system and for evaluation, and it is the only one that works with nothing else in place. Its cost is that account recovery, password policy and any second factor are Stroom's rather than your organisation's, so it does not scale well to an estate that already solved those problems once.
External
An existing provider holds the accounts, and Stroom redirects the browser to it. Password policy, recovery and multi-factor authentication all become that provider's business, which is usually the reason to choose it.
Register Stroom as a client with your provider. The client's valid redirect URIs must include https://<stroom-host>/api/auth/flow/v1/signin-oidc, exactly, or the provider rejects every sign-in with an "invalid redirect_uri" error. If you use the provider's own logout, also add https://<stroom-host>/ as a valid post-logout redirect URI.
Then set:
openIdConfigurationEndpoint: the provider's.well-known/openid-configurationURL. This is required forEXTERNAL_IDP, and Stroom will not start without it. Stroom reads the issuer, the authorisation, token and JWKS endpoints from it rather than you setting each one.clientIdandclientSecret, as issued by the provider.requestScopes, only if you change it: it must includeopenid, which the default (openid,email) does.
The individual endpoints can also be set by hand, but only to override what the discovery document supplies. Avoid it unless something prevents discovery working: endpoints copied by hand are a standing opportunity for one of them to be wrong or to drift.
Stroom also checks the audience (aud) claim of every token from the provider, and by default rejects a token that has none. With allowedAudiences empty, aud must match clientId, and Stroom will not start if neither is set. If your provider puts something else in aud, such as an API identifier, list the expected values under allowedAudiences. If its access tokens carry no aud at all, as some Cognito and Okta tokens do not, set audienceClaimRequired: false. Turning audience checks off altogether, with validateAudience: false, lets a token issued to another application at the same provider be used against Stroom.
As optional hardening, set requiredAccessTokenType to the typ header your provider puts on its access tokens, for example at+jwt for an RFC 9068 provider or Bearer for Keycloak's default, and Stroom refuses an ID token presented in place of one. Leave it unset if your provider uses the same typ for both, as Cognito does.
Getting the claim mapping right
This is the part that is easy to get wrong and expensive to correct.
| Setting | Default | What it is for |
|---|---|---|
uniqueIdentityClaim | sub | The claim that identifies the person. Stroom keys its user record on this |
userDisplayNameClaim | preferred_username | A friendlier name to show. Need not be unique, and may change |
fullNameClaimTemplate | ${name} | The person's full name, for display |
When someone signs in for the first time, Stroom creates a user record keyed on the value of uniqueIdentityClaim. Every later sign-in finds that same record, and the display and full names are refreshed from the claims each time.
So the identity claim must be unique and permanent. The default, sub, is both by design. An email address or a username is neither: people change both, and the provider may reissue them.
Warning
Decide the identity claim before anyone signs in. Changing it later, or choosing a claim whose value can change, means existing users are no longer found and new, empty ones are created in their place.
No identity provider
NO_IDP is for a remote proxy with no access to OIDC infrastructure, which forwards to a downstream proxy or to Stroom rather than authenticating anyone itself. Trust is established at the transport, by certificates.
It is not a way to switch authentication off on a Stroom instance.
Nor is there a test-credentials provider any more. TEST_CREDENTIALS, which let Stroom and Stroom Proxy authenticate to each other with a fixed, publicly known key, has been removed, and a configuration that still sets it fails validation at start-up. For a test or demonstration stack that needs the same shortcut, setting both STROOM_ALLOW_INSECURE_TEST_CREDENTIALS=true and STROOM_INSECURE_TEST_CREDENTIAL=<a secret of your choosing>, as environment variables or system properties, makes Stroom accept that secret as a bearer token for the processing user. Never set them in production.
Behind an authenticating proxy
Where a reverse proxy already authenticates and passes Stroom a verified identity, that is configured separately, under stroom.security.authentication.edgeAuthentication. Stroom then trusts what the edge tells it, which makes the edge part of your security boundary.
How long: immediate
Authentication settings are read when a sign-in happens, so a change affects the next sign-in rather than sessions already running. Someone already signed in stays signed in.
When testing a change, use a fresh private browser window. Testing in the window you are already authenticated in will keep telling you the old configuration works.
Check it worked
Sign in as a real user in a new private browser window, then check in Security → Users that the user record Stroom matched is the existing one, with its group memberships intact, rather than a new one.
The check that matters most
An existing user signs in and lands on their own account, with the permissions they had before.
The second half is the check. Signing in successfully only proves authentication worked; it says nothing about whether Stroom matched the person to the right record, which is the thing claim mapping decides.
This does not prove it worked
A successful sign-in is not proof the claim mapping is right. A wrong identity claim authenticates perfectly and creates a brand new user, which looks like a working sign-in to a new starter and like lost permissions to everyone else.
Your own sign-in working is not proof the estate will. Administrators often have permissions granted directly as well as through groups, so they notice this least.
Destroys data
Changing the identity claim orphans every existing user.
Stroom's user records are keyed on the claim's value. Change which claim is used, and the next sign-in produces a value Stroom has never seen, so it creates a new user with no groups and no permissions. The original user still exists and still owns everything.
There is no error, and to the person signing in it looks as though their content and access have disappeared. Recovering means mapping old records to new ones by hand, or putting the setting back.
Treat the identity claim as something chosen once, before the first sign-in.
Fails silently
A display name claim that changes is harmless; an identity claim that changes is not.
userDisplayNameClaim is explicitly allowed to change, and Stroom refreshes it on each sign-in. It is tempting to use the same friendly claim for both, which quietly turns a cosmetic value into the key that permissions hang from.
If it isn't working
In order. Each step rules out a class of cause, so don't skip ahead.
- Did a new user record appear at the moment someone signed in? The signature of a claim mapping problem, and visible in Security → Users.
- Which claim is the identity claim? Compare it against what the provider actually issues; the provider's own documentation and a decoded token settle it.
- Is the discovery endpoint reachable from the Stroom node? It is fetched by the server, not the browser, so a URL that works from your desktop may not work from the node.
- Do the client ID and secret match the provider's registration? A wrong secret fails at the token exchange, after the provider has already shown a login page, which makes it look like a Stroom fault rather than a configuration one.
- Is the redirect URI registered with the provider? It must be
https://<stroom-host>/api/auth/flow/v1/signin-oidc, matching what Stroom sends exactly, including the scheme and any port. - Is the user enabled in Stroom? A disabled user is refused after authenticating successfully, so the provider's logs show success and Stroom shows a failure.
- Is it a proxy?
INTERNAL_IDPis not valid for Stroom Proxy. UseNO_IDP, or an external provider.