io.quarkus.oidc.OidcTenantConfig Maven / Gradle / Ivy
Show all versions of quarkus-oidc Show documentation
package io.quarkus.oidc;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import io.quarkus.oidc.common.runtime.OidcCommonConfig;
import io.quarkus.oidc.common.runtime.OidcConstants;
import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConvertWith;
import io.quarkus.runtime.configuration.TrimmedStringConverter;
import io.quarkus.security.identity.SecurityIdentityAugmentor;
@ConfigGroup
public class OidcTenantConfig extends OidcCommonConfig {
/**
* A unique tenant identifier. It must be set by {@code TenantConfigResolver} providers which
* resolve the tenant configuration dynamically and is optional in all other cases.
*/
@ConfigItem
public Optional tenantId = Optional.empty();
/**
* If this tenant configuration is enabled.
*
* Note that the default tenant will be disabled if it is not configured but either
* {@link TenantConfigResolver} which will resolve tenant configurations is registered
* or named tenants are configured.
* You do not have to disable the default tenant in this case.
*/
@ConfigItem(defaultValue = "true")
public boolean tenantEnabled = true;
/**
* The application type, which can be one of the following values from enum {@link ApplicationType}.
*/
@ConfigItem(defaultValueDocumentation = "service")
public Optional applicationType = Optional.empty();
/**
* Relative path or absolute URL of the OIDC authorization endpoint which authenticates the users.
* This property must be set for the 'web-app' applications if OIDC discovery is disabled.
* This property will be ignored if the discovery is enabled.
*/
@ConfigItem
public Optional authorizationPath = Optional.empty();
/**
* Relative path or absolute URL of the OIDC userinfo endpoint.
* This property must only be set for the 'web-app' applications if OIDC discovery is disabled
* and 'authentication.user-info-required' property is enabled.
* This property will be ignored if the discovery is enabled.
*/
@ConfigItem
public Optional userInfoPath = Optional.empty();
/**
* Relative path or absolute URL of the OIDC RFC7662 introspection endpoint which can introspect both opaque and JWT tokens.
* This property must be set if OIDC discovery is disabled and 1) the opaque bearer access tokens have to be verified
* or 2) JWT tokens have to be verified while the cached JWK verification set with no matching JWK is being refreshed.
* This property will be ignored if the discovery is enabled.
*/
@ConfigItem
public Optional introspectionPath = Optional.empty();
/**
* Relative path or absolute URL of the OIDC JWKS endpoint which returns a JSON Web Key Verification Set.
* This property should be set if OIDC discovery is disabled and the local JWT verification is required.
* This property will be ignored if the discovery is enabled.
*/
@ConfigItem
public Optional jwksPath = Optional.empty();
/**
* Relative path or absolute URL of the OIDC end_session_endpoint.
* This property must be set if OIDC discovery is disabled and RP Initiated Logout support for the 'web-app' applications is
* required.
* This property will be ignored if the discovery is enabled.
*/
@ConfigItem
public Optional endSessionPath = Optional.empty();
/**
* Public key for the local JWT token verification.
* OIDC server connection will not be created when this property is set.
*/
@ConfigItem
public Optional publicKey = Optional.empty();
/**
* Introspection Basic Authentication which must be configured only if the introspection is required
* and OpenId Connect Provider does not support the OIDC client authentication configured with
* {@link OidcCommonConfig#credentials} for its introspection endpoint.
*/
@ConfigItem
public IntrospectionCredentials introspectionCredentials = new IntrospectionCredentials();
/**
* Introspection Basic Authentication configuration
*/
@ConfigGroup
public static class IntrospectionCredentials {
/**
* Name
*/
@ConfigItem
public Optional name = Optional.empty();
/**
* Secret
*/
@ConfigItem
public Optional secret = Optional.empty();
/**
* Include OpenId Connect Client ID configured with 'quarkus.oidc.client-id'
*/
@ConfigItem(defaultValue = "true")
public boolean includeClientId = true;
public Optional getName() {
return name;
}
public void setName(String name) {
this.name = Optional.of(name);
}
public Optional getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = Optional.of(secret);
}
public boolean isIncludeClientId() {
return includeClientId;
}
public void setIncludeClientId(boolean includeClientId) {
this.includeClientId = includeClientId;
}
}
/**
* Configuration to find and parse a custom claim containing the roles information.
*/
@ConfigItem
public Roles roles = new Roles();
/**
* Configuration how to validate the token claims.
*/
@ConfigItem
public Token token = new Token();
/**
* RP Initiated, BackChannel and FrontChannel Logout configuration
*/
@ConfigItem
public Logout logout = new Logout();
/**
* Different options to configure authorization requests
*/
public Authentication authentication = new Authentication();
/**
* Authorization code grant configuration
*/
public CodeGrant codeGrant = new CodeGrant();
/**
* Default token state manager configuration
*/
@ConfigItem
public TokenStateManager tokenStateManager = new TokenStateManager();
/**
* Allow caching the token introspection data.
* Note enabling this property does not enable the cache itself but only permits to cache the token introspection
* for a given tenant. If the default token cache can be used then please see {@link OidcConfig.TokenCache} how to enable
* it.
*/
@ConfigItem(defaultValue = "true")
public boolean allowTokenIntrospectionCache = true;
/**
* Allow caching the user info data.
* Note enabling this property does not enable the cache itself but only permits to cache the user info data
* for a given tenant. If the default token cache can be used then please see {@link OidcConfig.TokenCache} how to enable
* it.
*/
@ConfigItem(defaultValue = "true")
public boolean allowUserInfoCache = true;
/**
* Allow inlining UserInfo in IdToken instead of caching it in the token cache.
* This property is only checked when an internal IdToken is generated when Oauth2 providers do not return IdToken.
* Inlining UserInfo in the generated IdToken allows to store it in the session cookie and avoids introducing a cached
* state.
*/
@ConfigItem(defaultValue = "false")
public boolean cacheUserInfoInIdtoken = false;
@ConfigGroup
public static class Logout {
/**
* The relative path of the logout endpoint at the application. If provided, the application is able to initiate the
* logout through this endpoint in conformance with the OpenID Connect RP-Initiated Logout specification.
*/
@ConfigItem
public Optional path = Optional.empty();
/**
* Relative path of the application endpoint where the user should be redirected to after logging out from the OpenID
* Connect Provider.
* This endpoint URI must be properly registered at the OpenID Connect Provider as a valid redirect URI.
*/
@ConfigItem
public Optional postLogoutPath = Optional.empty();
/**
* Name of the post logout URI parameter which will be added as a query parameter to the logout redirect URI.
*/
@ConfigItem(defaultValue = OidcConstants.POST_LOGOUT_REDIRECT_URI)
public String postLogoutUriParam;
/**
* Additional properties which will be added as the query parameters to the logout redirect URI.
*/
@ConfigItem
public Map extraParams;
/**
* Back-Channel Logout configuration
*/
@ConfigItem
public Backchannel backchannel = new Backchannel();
/**
* Front-Channel Logout configuration
*/
@ConfigItem
public Frontchannel frontchannel = new Frontchannel();
public void setPath(Optional path) {
this.path = path;
}
public Optional getPath() {
return path;
}
public void setPostLogoutPath(Optional postLogoutPath) {
this.postLogoutPath = postLogoutPath;
}
public Optional getPostLogoutPath() {
return postLogoutPath;
}
public Map getExtraParams() {
return extraParams;
}
public void setExtraParams(Map extraParams) {
this.extraParams = extraParams;
}
public String getPostLogoutUriParam() {
return postLogoutUriParam;
}
public void setPostLogoutUriParam(String postLogoutUriParam) {
this.postLogoutUriParam = postLogoutUriParam;
}
public Backchannel getBackchannel() {
return backchannel;
}
public void setBackchannel(Backchannel backchannel) {
this.backchannel = backchannel;
}
public Frontchannel getFrontchannel() {
return frontchannel;
}
public void setFrontchannel(Frontchannel frontchannel) {
this.frontchannel = frontchannel;
}
}
@ConfigGroup
public static class Backchannel {
/**
* The relative path of the Back-Channel Logout endpoint at the application.
*/
@ConfigItem
public Optional path = Optional.empty();
/**
* Maximum number of logout tokens that can be cached before they are matched against ID tokens stored in session
* cookies.
*/
@ConfigItem(defaultValue = "10")
public int tokenCacheSize = 10;
/**
* Number of minutes a logout token can be cached for.
*/
@ConfigItem(defaultValue = "10M")
public Duration tokenCacheTimeToLive = Duration.ofMinutes(10);
/**
* Token cache timer interval.
* If this property is set then a timer will check and remove the stale entries periodically.
*/
@ConfigItem
public Optional cleanUpTimerInterval = Optional.empty();
/**
* Logout token claim whose value will be used as a key for caching the tokens.
* Only `sub` (subject) and `sid` (session id) claims can be used as keys.
* Set it to `sid` only if ID tokens issued by the OIDC provider have no `sub` but have `sid` claim.
*/
@ConfigItem(defaultValue = "sub")
public String logoutTokenKey = "sub";
public void setPath(Optional path) {
this.path = path;
}
public Optional getPath() {
return path;
}
public String getLogoutTokenKey() {
return logoutTokenKey;
}
public void setLogoutTokenKey(String logoutTokenKey) {
this.logoutTokenKey = logoutTokenKey;
}
public int getTokenCacheSize() {
return tokenCacheSize;
}
public void setTokenCacheSize(int tokenCacheSize) {
this.tokenCacheSize = tokenCacheSize;
}
public Duration getTokenCacheTimeToLive() {
return tokenCacheTimeToLive;
}
public void setTokenCacheTimeToLive(Duration tokenCacheTimeToLive) {
this.tokenCacheTimeToLive = tokenCacheTimeToLive;
}
public Optional getCleanUpTimerInterval() {
return cleanUpTimerInterval;
}
public void setCleanUpTimerInterval(Duration cleanUpTimerInterval) {
this.cleanUpTimerInterval = Optional.of(cleanUpTimerInterval);
}
}
@ConfigGroup
public static class Frontchannel {
/**
* The relative path of the Front-Channel Logout endpoint at the application.
*/
@ConfigItem
public Optional path = Optional.empty();
public void setPath(Optional path) {
this.path = path;
}
public Optional getPath() {
return path;
}
}
/**
* Default Authorization Code token state manager configuration
*/
@ConfigGroup
public static class TokenStateManager {
public enum Strategy {
/**
* Keep ID, access and refresh tokens.
*/
KEEP_ALL_TOKENS,
/**
* Keep ID token only
*/
ID_TOKEN,
/**
* Keep ID and refresh tokens only
*/
ID_REFRESH_TOKENS
}
/**
* Default TokenStateManager strategy.
*/
@ConfigItem(defaultValue = "keep_all_tokens")
public Strategy strategy = Strategy.KEEP_ALL_TOKENS;
/**
* Default TokenStateManager keeps all tokens (ID, access and refresh)
* returned in the authorization code grant response in a single session cookie by default.
*
* Enable this property to minimize a session cookie size
*/
@ConfigItem(defaultValue = "false")
public boolean splitTokens;
/**
* Mandates that the Default TokenStateManager will encrypt the session cookie that stores the tokens.
*/
@ConfigItem(defaultValue = "true")
public boolean encryptionRequired = true;
/**
* Secret which will be used by the Default TokenStateManager to encrypt the session cookie
* storing the tokens when {@link #encryptionRequired} property is enabled.
*
* If this secret is not set, the client secret configured with
* either `quarkus.oidc.credentials.secret` or `quarkus.oidc.credentials.client-secret.value` will be checked.
* Finally, `quarkus.oidc.credentials.jwt.secret` which can be used for `client_jwt_secret` authentication will be
* checked.
* The secret will be auto-generated if it remains uninitialized after checking all of these properties.
*
* The length of the secret which will be used to encrypt the tokens should be at least 32 characters long.
* Warning will be logged if the secret length is less than 16 characters.
*/
@ConfigItem
public Optional encryptionSecret = Optional.empty();
public boolean isEncryptionRequired() {
return encryptionRequired;
}
public void setEncryptionRequired(boolean encryptionRequired) {
this.encryptionRequired = encryptionRequired;
}
public Optional getEncryptionSecret() {
return encryptionSecret;
}
public void setEncryptionSecret(String encryptionSecret) {
this.encryptionSecret = Optional.of(encryptionSecret);
}
public boolean isSplitTokens() {
return splitTokens;
}
public void setSplitTokens(boolean splitTokens) {
this.splitTokens = splitTokens;
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
public Optional getAuthorizationPath() {
return authorizationPath;
}
public void setAuthorizationPath(String authorizationPath) {
this.authorizationPath = Optional.of(authorizationPath);
}
public Optional getUserInfoPath() {
return userInfoPath;
}
public void setUserInfoPath(String userInfoPath) {
this.userInfoPath = Optional.of(userInfoPath);
}
public Optional getIntrospectionPath() {
return introspectionPath;
}
public void setIntrospectionPath(String introspectionPath) {
this.introspectionPath = Optional.of(introspectionPath);
}
public Optional getJwksPath() {
return jwksPath;
}
public void setJwksPath(String jwksPath) {
this.jwksPath = Optional.of(jwksPath);
}
public Optional getEndSessionPath() {
return endSessionPath;
}
public void setEndSessionPath(String endSessionPath) {
this.endSessionPath = Optional.of(endSessionPath);
}
public Optional getPublicKey() {
return publicKey;
}
public void setPublicKey(String publicKey) {
this.publicKey = Optional.of(publicKey);
}
public Roles getRoles() {
return roles;
}
public void setRoles(Roles roles) {
this.roles = roles;
}
public Token getToken() {
return token;
}
public void setToken(Token token) {
this.token = token;
}
public Authentication getAuthentication() {
return authentication;
}
public void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
public Optional getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = Optional.of(tenantId);
}
public boolean isTenantEnabled() {
return tenantEnabled;
}
public void setTenantEnabled(boolean enabled) {
this.tenantEnabled = enabled;
}
public void setLogout(Logout logout) {
this.logout = logout;
}
public Logout getLogout() {
return logout;
}
@ConfigGroup
public static class Roles {
public static Roles fromClaimPath(List path) {
return fromClaimPathAndSeparator(path, null);
}
public static Roles fromClaimPathAndSeparator(List path, String sep) {
Roles roles = new Roles();
roles.roleClaimPath = Optional.ofNullable(path);
roles.roleClaimSeparator = Optional.ofNullable(sep);
return roles;
}
/**
* List of paths to claims containing an array of groups. Each path starts from the top level JWT JSON object
* and can contain multiple segments where each segment represents a JSON object name only,
* example: "realm/groups". Use double quotes with the namespace qualified claim names.
* This property can be used if a token has no 'groups' claim but has the groups set in one or more different
* claims.
*/
@ConfigItem
public Optional> roleClaimPath = Optional.empty();
/**
* Separator for splitting a string which may contain multiple group values.
* It will only be used if the "role-claim-path" property points to one or more custom claims whose values are strings.
* A single space will be used by default because the standard 'scope' claim may contain a space separated sequence.
*/
@ConfigItem
public Optional roleClaimSeparator = Optional.empty();
/**
* Source of the principal roles.
*/
@ConfigItem
public Optional
* The secret will be auto-generated if it remains uninitialized after checking all of these properties.
*
* Error will be reported if the secret length is less than 16 characters.
*/
@ConfigItem
public Optional stateSecret = Optional.empty();
public Optional getInternalIdTokenLifespan() {
return internalIdTokenLifespan;
}
public void setInternalIdTokenLifespan(Duration internalIdTokenLifespan) {
this.internalIdTokenLifespan = Optional.of(internalIdTokenLifespan);
}
public Optional isPkceRequired() {
return pkceRequired;
}
public void setPkceRequired(boolean pkceRequired) {
this.pkceRequired = Optional.of(pkceRequired);
}
@Deprecated(forRemoval = true)
public Optional getPkceSecret() {
return pkceSecret;
}
@Deprecated(forRemoval = true)
public void setPkceSecret(String pkceSecret) {
this.pkceSecret = Optional.of(pkceSecret);
}
public Optional getErrorPath() {
return errorPath;
}
public void setErrorPath(String errorPath) {
this.errorPath = Optional.of(errorPath);
}
public boolean isJavaScriptAutoRedirect() {
return javaScriptAutoRedirect;
}
public void setJavaScriptAutoredirect(boolean autoRedirect) {
this.javaScriptAutoRedirect = autoRedirect;
}
public Optional getRedirectPath() {
return redirectPath;
}
public void setRedirectPath(String redirectPath) {
this.redirectPath = Optional.of(redirectPath);
}
public Optional> getScopes() {
return scopes;
}
public void setScopes(List scopes) {
this.scopes = Optional.of(scopes);
}
public Map getExtraParams() {
return extraParams;
}
public void setExtraParams(Map extraParams) {
this.extraParams = extraParams;
}
public void setAddOpenidScope(boolean addOpenidScope) {
this.addOpenidScope = Optional.of(addOpenidScope);
}
public Optional isAddOpenidScope() {
return addOpenidScope;
}
public Optional isForceRedirectHttpsScheme() {
return forceRedirectHttpsScheme;
}
public void setForceRedirectHttpsScheme(boolean forceRedirectHttpsScheme) {
this.forceRedirectHttpsScheme = Optional.of(forceRedirectHttpsScheme);
}
public boolean isRestorePathAfterRedirect() {
return restorePathAfterRedirect;
}
public void setRestorePathAfterRedirect(boolean restorePathAfterRedirect) {
this.restorePathAfterRedirect = restorePathAfterRedirect;
}
public boolean isCookieForceSecure() {
return cookieForceSecure;
}
public void setCookieForceSecure(boolean cookieForceSecure) {
this.cookieForceSecure = cookieForceSecure;
}
public String getCookiePath() {
return cookiePath;
}
public void setCookiePath(String cookiePath) {
this.cookiePath = cookiePath;
}
public Optional getCookieDomain() {
return cookieDomain;
}
public void setCookieDomain(String cookieDomain) {
this.cookieDomain = Optional.of(cookieDomain);
}
public Optional isUserInfoRequired() {
return userInfoRequired;
}
public void setUserInfoRequired(boolean userInfoRequired) {
this.userInfoRequired = Optional.of(userInfoRequired);
}
public boolean isRemoveRedirectParameters() {
return removeRedirectParameters;
}
public void setRemoveRedirectParameters(boolean removeRedirectParameters) {
this.removeRedirectParameters = removeRedirectParameters;
}
public boolean isVerifyAccessToken() {
return verifyAccessToken;
}
public void setVerifyAccessToken(boolean verifyAccessToken) {
this.verifyAccessToken = verifyAccessToken;
}
public Duration getSessionAgeExtension() {
return sessionAgeExtension;
}
public void setSessionAgeExtension(Duration sessionAgeExtension) {
this.sessionAgeExtension = sessionAgeExtension;
}
public Optional getCookiePathHeader() {
return cookiePathHeader;
}
public void setCookiePathHeader(String cookiePathHeader) {
this.cookiePathHeader = Optional.of(cookiePathHeader);
}
public Optional isIdTokenRequired() {
return idTokenRequired;
}
public void setIdTokenRequired(boolean idTokenRequired) {
this.idTokenRequired = Optional.of(idTokenRequired);
}
public Optional getCookieSuffix() {
return cookieSuffix;
}
public void setCookieSuffix(String cookieSuffix) {
this.cookieSuffix = Optional.of(cookieSuffix);
}
public Optional getResponseMode() {
return responseMode;
}
public void setResponseMode(ResponseMode responseMode) {
this.responseMode = Optional.of(responseMode);
}
public Optional> getForwardParams() {
return forwardParams;
}
public void setForwardParams(List forwardParams) {
this.forwardParams = Optional.of(forwardParams);
}
public CookieSameSite getCookieSameSite() {
return cookieSameSite;
}
public void setCookieSameSite(CookieSameSite cookieSameSite) {
this.cookieSameSite = cookieSameSite;
}
public boolean isAllowMultipleCodeFlows() {
return allowMultipleCodeFlows;
}
public void setAllowMultipleCodeFlows(boolean allowMultipleCodeFlows) {
this.allowMultipleCodeFlows = allowMultipleCodeFlows;
}
public boolean isNonceRequired() {
return nonceRequired;
}
public void setNonceRequired(boolean nonceRequired) {
this.nonceRequired = nonceRequired;
}
public Optional getStateSecret() {
return stateSecret;
}
public void setStateSecret(Optional stateSecret) {
this.stateSecret = stateSecret;
}
}
/**
* Authorization Code grant configuration
*/
@ConfigGroup
public static class CodeGrant {
/**
* Additional parameters, in addition to the required `code` and `redirect-uri` parameters,
* which have to be included to complete the authorization code grant request.
*/
@ConfigItem
public Map extraParams = new HashMap<>();
/**
* Custom HTTP headers which have to be sent to complete the authorization code grant request.
*/
@ConfigItem
public Map headers = new HashMap<>();
public Map getExtraParams() {
return extraParams;
}
public void setExtraParams(Map extraParams) {
this.extraParams = extraParams;
}
public Map getHeaders() {
return headers;
}
public void setHeaders(Map headers) {
this.headers = headers;
}
}
/**
* Supported asymmetric signature algorithms
*/
public static enum SignatureAlgorithm {
RS256,
RS384,
RS512,
PS256,
PS384,
PS512,
ES256,
ES384,
ES512,
EDDSA;
private static String EDDSA_ALG = "EDDSA";
private static String REQUIRED_EDDSA_ALG = "EdDSA";
public String getAlgorithm() {
String name = name();
return EDDSA_ALG.equals(name) ? REQUIRED_EDDSA_ALG : name;
}
}
@ConfigGroup
public static class Token {
public static Token fromIssuer(String issuer) {
Token tokenClaims = new Token();
tokenClaims.issuer = Optional.of(issuer);
tokenClaims.audience = Optional.ofNullable(null);
return tokenClaims;
}
public static Token fromAudience(String... audience) {
Token tokenClaims = new Token();
tokenClaims.issuer = Optional.ofNullable(null);
tokenClaims.audience = Optional.of(Arrays.asList(audience));
return tokenClaims;
}
/**
* Expected issuer 'iss' claim value.
* Note this property overrides the `issuer` property which may be set in OpenId Connect provider's well-known
* configuration.
* If the `iss` claim value varies depending on the host/IP address or tenant id of the provider then you may skip the
* issuer verification by setting this property to 'any' but it should be done only when other options (such as
* configuring
* the provider to use the fixed `iss` claim value) are not possible.
*/
@ConfigItem
public Optional issuer = Optional.empty();
/**
* Expected audience 'aud' claim value which may be a string or an array of strings.
*
* Note the audience claim will be verified for ID tokens by default.
* ID token audience must be equal to the value of `quarkus.oidc.client-id` property.
* Use this property to override the expected value if your OpenID Connect provider
* sets a different audience claim value in ID tokens. Set it to `any` if your provider
* does not set ID token audience` claim.
*
* Audience verification for access tokens will only be done if this property is configured.
*/
@ConfigItem
public Optional> audience = Optional.empty();
/**
* Require that the token includes a `sub` (subject) claim which is a unique
* and never reassigned identifier for the current user.
* Note that if you enable this property and if UserInfo is also required then
* both the token and UserInfo `sub` claims must be present and match each other.
*/
@ConfigItem(defaultValue = "false")
public boolean subjectRequired = false;
/**
* A map of required claims and their expected values.
* For example, `quarkus.oidc.token.required-claims.org_id = org_xyz` would require tokens to have the `org_id` claim to
* be present and set to `org_xyz`.
* Strings are the only supported types. Use {@linkplain SecurityIdentityAugmentor} to verify claims of other types or
* complex claims.
*/
@ConfigItem
@ConfigDocMapKey("claim-name")
public Map requiredClaims = new HashMap<>();
/**
* Expected token type
*/
@ConfigItem
public Optional tokenType = Optional.empty();
/**
* Life span grace period in seconds.
* When checking token expiry, current time is allowed to be later than token expiration time by at most the configured
* number of seconds.
* When checking token issuance, current time is allowed to be sooner than token issue time by at most the configured
* number of seconds.
*/
@ConfigItem
public OptionalInt lifespanGrace = OptionalInt.empty();
/**
* Token age.
*
* It allows for the number of seconds to be specified that must not elapse since the `iat` (issued at) time.
* A small leeway to account for clock skew which can be configured with 'quarkus.oidc.token.lifespan-grace' to verify
* the token expiry time
* can also be used to verify the token age property.
*
* Note that setting this property does not relax the requirement that Bearer and Code Flow JWT tokens
* must have a valid ('exp') expiry claim value. The only exception where setting this property relaxes the requirement
* is when a logout token is sent with a back-channel logout request since the current
* OpenId Connect Back-Channel specification does not explicitly require the logout tokens to contain an 'exp' claim.
* However, even if the current logout token is allowed to have no 'exp' claim, the `exp` claim will be still verified
* if the logout token contains it.
*/
@ConfigItem
public Optional age = Optional.empty();
/**
* Name of the claim which contains a principal name. By default, the 'upn', 'preferred_username' and `sub` claims are
* checked.
*/
@ConfigItem
public Optional principalClaim = Optional.empty();
/**
* Refresh expired authorization code flow ID or access tokens.
* If this property is enabled then a refresh token request will be performed if the authorization code
* ID or access token has expired and, if successful, the local session will be updated with the new set of tokens.
* Otherwise, the local session will be invalidated and the user redirected to the OpenID Provider to re-authenticate.
* In this case the user may not be challenged again if the OIDC provider session is still active.
*
* For this option be effective the `authentication.session-age-extension` property should also be set to a non-zero
* value since the refresh token is currently kept in the user session.
*
* This option is valid only when the application is of type {@link ApplicationType#WEB_APP}}.
*
* This property will be enabled if `quarkus.oidc.token.refresh-token-time-skew` is configured,
* you do not have to enable this property manually in this case.
*/
@ConfigItem
public boolean refreshExpired;
/**
* Refresh token time skew in seconds.
* If this property is enabled then the configured number of seconds is added to the current time
* when checking if the authorization code ID or access token should be refreshed.
* If the sum is greater than the authorization code ID or access token's expiration time then a refresh is going to
* happen.
*/
@ConfigItem
public Optional refreshTokenTimeSkew = Optional.empty();
/**
* Forced JWK set refresh interval in minutes.
*/
@ConfigItem(defaultValue = "10M")
public Duration forcedJwkRefreshInterval = Duration.ofMinutes(10);
/**
* Custom HTTP header that contains a bearer token.
* This option is valid only when the application is of type {@link ApplicationType#SERVICE}}.
*/
@ConfigItem
public Optional header = Optional.empty();
/**
* Required signature algorithm.
* OIDC providers support many signature algorithms but if necessary you can restrict
* Quarkus application to accept tokens signed only using an algorithm configured with this property.
*/
@ConfigItem
public Optional signatureAlgorithm = Optional.empty();
/**
* Decryption key location.
* JWT tokens can be inner-signed and encrypted by OpenId Connect providers.
* However, it is not always possible to remotely introspect such tokens because
* the providers may not control the private decryption keys.
* In such cases set this property to point to the file containing the decryption private key in
* PEM or JSON Web Key (JWK) format.
* Note that if a 'private_key_jwt' client authentication method is used then the private key
* which is used to sign client authentication JWT tokens will be used to try to decrypt an encrypted ID token
* if this property is not set.
*/
@ConfigItem
public Optional decryptionKeyLocation = Optional.empty();
/**
* Allow the remote introspection of JWT tokens when no matching JWK key is available.
*
* Note this property is set to 'true' by default for backward-compatibility reasons and will be set to `false`
* instead in one of the next releases.
*
* Also note this property will be ignored if JWK endpoint URI is not available and introspecting the tokens is
* the only verification option.
*/
@ConfigItem(defaultValue = "true")
public boolean allowJwtIntrospection = true;
/**
* Require that JWT tokens are only introspected remotely.
*
*/
@ConfigItem(defaultValue = "false")
public boolean requireJwtIntrospectionOnly = false;
/**
* Allow the remote introspection of the opaque tokens.
*
* Set this property to 'false' if only JWT tokens are expected.
*/
@ConfigItem(defaultValue = "true")
public boolean allowOpaqueTokenIntrospection = true;
/**
* Token customizer name.
*
* Allows to select a tenant specific token customizer as a named bean.
* Prefer using {@link TenantFeature} qualifier when registering custom {@link TokenCustomizer}.
* Use this property only to refer to `TokenCustomizer` implementations provided by this extension.
*/
@ConfigItem
public Optional customizerName = Optional.empty();
/**
* Indirectly verify that the opaque (binary) access token is valid by using it to request UserInfo.
* Opaque access token is considered valid if the provider accepted this token and returned a valid UserInfo.
* You should only enable this option if the opaque access tokens have to be accepted but OpenId Connect
* provider does not have a token introspection endpoint.
* This property will have no effect when JWT tokens have to be verified.
*/
@ConfigItem(defaultValueDocumentation = "false")
public Optional verifyAccessTokenWithUserInfo = Optional.empty();
public Optional isVerifyAccessTokenWithUserInfo() {
return verifyAccessTokenWithUserInfo;
}
public void setVerifyAccessTokenWithUserInfo(boolean verify) {
this.verifyAccessTokenWithUserInfo = Optional.of(verify);
}
public Optional getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = Optional.of(issuer);
}
public Optional getHeader() {
return header;
}
public void setHeader(String header) {
this.header = Optional.of(header);
}
public Optional> getAudience() {
return audience;
}
public void setAudience(List audience) {
this.audience = Optional.of(audience);
}
public OptionalInt getLifespanGrace() {
return lifespanGrace;
}
public void setLifespanGrace(int lifespanGrace) {
this.lifespanGrace = OptionalInt.of(lifespanGrace);
}
public Optional getPrincipalClaim() {
return principalClaim;
}
public void setPrincipalClaim(String principalClaim) {
this.principalClaim = Optional.of(principalClaim);
}
public boolean isRefreshExpired() {
return refreshExpired;
}
public void setRefreshExpired(boolean refreshExpired) {
this.refreshExpired = refreshExpired;
}
public Duration getForcedJwkRefreshInterval() {
return forcedJwkRefreshInterval;
}
public void setForcedJwkRefreshInterval(Duration forcedJwkRefreshInterval) {
this.forcedJwkRefreshInterval = forcedJwkRefreshInterval;
}
public Optional getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = Optional.of(tokenType);
}
public Optional getRefreshTokenTimeSkew() {
return refreshTokenTimeSkew;
}
public void setRefreshTokenTimeSkew(Duration refreshTokenTimeSkew) {
this.refreshTokenTimeSkew = Optional.of(refreshTokenTimeSkew);
}
public boolean isAllowJwtIntrospection() {
return allowJwtIntrospection;
}
public void setAllowJwtIntrospection(boolean allowJwtIntrospection) {
this.allowJwtIntrospection = allowJwtIntrospection;
}
public boolean isAllowOpaqueTokenIntrospection() {
return allowOpaqueTokenIntrospection;
}
public void setAllowOpaqueTokenIntrospection(boolean allowOpaqueTokenIntrospection) {
this.allowOpaqueTokenIntrospection = allowOpaqueTokenIntrospection;
}
public Optional getAge() {
return age;
}
public void setAge(Duration age) {
this.age = Optional.of(age);
}
public Optional getDecryptionKeyLocation() {
return decryptionKeyLocation;
}
public void setDecryptionKeyLocation(String decryptionKeyLocation) {
this.decryptionKeyLocation = Optional.of(decryptionKeyLocation);
}
public Map getRequiredClaims() {
return requiredClaims;
}
public void setRequiredClaims(Map requiredClaims) {
this.requiredClaims = requiredClaims;
}
public boolean isRequireJwtIntrospectionOnly() {
return requireJwtIntrospectionOnly;
}
public void setRequireJwtIntrospectionOnly(boolean requireJwtIntrospectionOnly) {
this.requireJwtIntrospectionOnly = requireJwtIntrospectionOnly;
}
public Optional getSignatureAlgorithm() {
return signatureAlgorithm;
}
public void setSignatureAlgorithm(SignatureAlgorithm signatureAlgorithm) {
this.signatureAlgorithm = Optional.of(signatureAlgorithm);
}
public Optional getCustomizerName() {
return customizerName;
}
public void setCustomizerName(String customizerName) {
this.customizerName = Optional.of(customizerName);
}
public boolean isSubjectRequired() {
return subjectRequired;
}
public void setSubjectRequired(boolean subjectRequired) {
this.subjectRequired = subjectRequired;
}
}
public static enum ApplicationType {
/**
* A {@code WEB_APP} is a client that serves pages, usually a frontend application. For this type of client the
* Authorization Code Flow is defined as the preferred method for authenticating users.
*/
WEB_APP,
/**
* A {@code SERVICE} is a client that has a set of protected HTTP resources, usually a backend application following the
* RESTful Architectural Design. For this type of client, the Bearer Authorization method is defined as the preferred
* method for authenticating and authorizing users.
*/
SERVICE,
/**
* A combined {@code SERVICE} and {@code WEB_APP} client.
* For this type of client, the Bearer Authorization method will be used if the Authorization header is set
* and Authorization Code Flow - if not.
*/
HYBRID
}
/**
* Well known OpenId Connect provider identifier
*/
@ConfigItem
public Optional provider = Optional.empty();
public static enum Provider {
APPLE,
FACEBOOK,
GITHUB,
GOOGLE,
MASTODON,
MICROSOFT,
SPOTIFY,
TWITCH,
TWITTER,
// New name for Twitter
X
}
public Optional getProvider() {
return provider;
}
public void setProvider(Provider provider) {
this.provider = Optional.of(provider);
}
public Optional getApplicationType() {
return applicationType;
}
public void setApplicationType(ApplicationType type) {
this.applicationType = Optional.of(type);
}
public boolean isAllowTokenIntrospectionCache() {
return allowTokenIntrospectionCache;
}
public void setAllowTokenIntrospectionCache(boolean allowTokenIntrospectionCache) {
this.allowTokenIntrospectionCache = allowTokenIntrospectionCache;
}
public boolean isAllowUserInfoCache() {
return allowUserInfoCache;
}
public void setAllowUserInfoCache(boolean allowUserInfoCache) {
this.allowUserInfoCache = allowUserInfoCache;
}
public boolean isCacheUserInfoInIdtoken() {
return cacheUserInfoInIdtoken;
}
public void setCacheUserInfoInIdtoken(boolean cacheUserInfoInIdtoken) {
this.cacheUserInfoInIdtoken = cacheUserInfoInIdtoken;
}
public IntrospectionCredentials getIntrospectionCredentials() {
return introspectionCredentials;
}
public void setIntrospectionCredentials(IntrospectionCredentials introspectionCredentials) {
this.introspectionCredentials = introspectionCredentials;
}
public CodeGrant getCodeGrant() {
return codeGrant;
}
public void setCodeGrant(CodeGrant codeGrant) {
this.codeGrant = codeGrant;
}
}