All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.helidon.security.providers.oidc.common.OidcConfig Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018, 2024 Oracle and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.helidon.security.providers.oidc.common;

import java.lang.System.Logger.Level;
import java.net.URI;
import java.time.Duration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;

import io.helidon.common.Errors;
import io.helidon.common.LazyValue;
import io.helidon.common.config.Config;
import io.helidon.common.configurable.Resource;
import io.helidon.config.metadata.Configured;
import io.helidon.config.metadata.ConfiguredOption;
import io.helidon.cors.CrossOriginConfig;
import io.helidon.http.SetCookie;
import io.helidon.security.Security;
import io.helidon.security.SecurityException;
import io.helidon.security.jwt.jwk.JwkKeys;
import io.helidon.security.providers.oidc.common.spi.TenantConfigFinder;
import io.helidon.security.util.TokenHandler;
import io.helidon.webclient.api.WebClient;
import io.helidon.webclient.api.WebClientConfig;

/**
 * Configuration of OIDC usable from all resources that utilize OIDC specification, such as security provider, web server
 * extension and IDCS connectivity.
 * 

* Some of the configuration options below use "resource" type. The following configuration * can be used for a resource (example for oidc-metadata key): * {@code * oidc-metadata-path: "path/on/filesystem" * oidc-metadata-resource-path: "class-path/resource" * oidc-metadata-url: "URI on the net" * oidc-metadata-content-plain: "Value of the resource in plain text" * oidc-metadata-content: "Value in base64 encoded bytes" * } *

* Configuration options required (under security.providers[].${name}): *

* * * * * * * * * * * * * * * * * * * * * *
Mandatory configuration parameters
keydescription
client-idClient ID as generated by OIDC server
client-secretClient secret as generated by OIDC server
identity-uriURI of the identity server, base used to retrieve OIDC metadata
frontend-uriFull URI of the frontend for redirects back from OIDC server (e.g. http://myserver/myApp)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Optional configuration parameters
keydefault valuedescription
proxy-protocolhttpProxy protocol to use when proxy is used.
proxy-hostnullProxy host to use. When defined, triggers usage of proxy for HTTP requests.
proxy-port80Port of the proxy server to use
relative-urisfalseFlag to force the use of relative URIs in all requests. By default, * requests that use the Proxy will have absolute URIs. Set this flag to * true if the host is unable to accept absolute URIs.
redirect-uri/oidc/redirectURI to register web server component on, used by the OIDC server to * redirect authorization requests to after a user logs in or approves scopes. Note that usually the redirect URI * configured here must be the same one as configured on OIDC server.
scope-audienceempty stringAudience of the scope required by this application. This is prefixed to * the scope name when requesting scopes from the identity server.
cookie-usetrueWhether to use cookie to store JWT. If used, redirects happen only in case the user * is not authenticated or has insufficient scopes
cookie-nameJSESSIONIDName of the cookie
cookie-domainnullDomain the cookie is valid for. Not used by default
cookie-path/Path the cookie is valid for.
cookie-max-age-secondsnullWhen using cookie, used to set MaxAge attribute of the cookie, defining * how long the cookie is valid.
cookie-http-onlytrueWhen using cookie, if set to true, the HttpOnly attribute will be configured.
cookie-securefalseWhen using cookie, if set to true, the Secure attribute will be configured.
cookie-same-siteLaxWhen using cookie, used to set the SameSite cookie value. Can be "Strict" or "Lax". * Setting this to "Strict" will result in infinite redirects when calling OIDC on a different host. *
query-param-usefalseWhether to expect JWT in a query parameter
query-param-nameaccessTokenName of a query parameter that contains the JWT token when parameter is used.
header-usetrueWhether to expect JWT in a header field.
header-token"Authorization" header with prefix "bearer "A {@link TokenHandler} configuration to process header containing a JWT
oidc-metadata-well-knowntrueIf set to true, metadata will be loaded from default (well known) * location, unless it is explicitly defined using oidc-metadata-resource. If set to false, it would not be loaded even * if oidc-metadata-resource is not defined. In such a case all URIs must be explicitly * defined (e.g. token-endpoint-uri).
oidc-metadata.resourceidentity-uri/.well-known/openid-configurationResource configuration for OIDC Metadata containing endpoints to various identity services, as well as information * about the identity server. See {@link Resource#create(io.helidon.common.config.Config)}
token-endpoint-uritoken_endpoint in OIDC metadata, or identity-url/oauth2/v1/token if not availableURI of a token endpoint used to obtain a JWT based on the authentication code.
authorization-endpoint-uri"authorization_endpoint" in OIDC metadata, or identity-uri/oauth2/v1/authorize if not availableURI of an authorization endpoint used to redirect users to for logging-in.
validate-jwt-with-jwktrueWhen true - validate against jwk defined by "sign-jwk", when false * validate JWT through OIDC Server endpoint "validation-endpoint-uri"
sign-jwk.resource"jwks-uri" in OIDC metadata, or identity-uri/admin/v1/SigningCert/jwk if not available, only needed * when jwt validation is done by usA resource pointing to JWK with public keys of signing certificates used to validate JWT. * See {@link Resource#create(io.helidon.common.config.Config)}
introspect-endpoint-uri"introspection_endpoint" in OIDC metadata, or identity-uri/oauth2/v1/introspectWhen validate-jwt-with-jwk is set to "false", this is the endpoint used
base-scopes{@value Builder#DEFAULT_BASE_SCOPES}Configure scopes to be requested by default. If the scope has a qualifier, it must be included here
redirectfalseWhether to redirect to identity server when authentication failed.
realmhelidonRealm returned in HTTP response if redirect is not enabled or possible.
redirect-attempt-param{@value DEFAULT_ATTEMPT_PARAM}Query parameter holding the number of times we redirected to an identity server. Customizable to prevent * conflicts with application parameters
max-redirects{@value DEFAULT_MAX_REDIRECTS}Maximal number of times we can redirect to an identity server. When the number is reached, no further redirects * happen and the request finishes with an error (status {@code 401})
server-type Type of identity server. Currently supported is {@code idcs} or not configured (for default).
{@code client-timeout-millis}30 secondsTimeout on HTTP client calls
{@code cookie-encryption-enabled}Depends on other configurationWhether cookies should be encrypted. Will be enabled if logout is enabled.
{@code cookie-encryption-password}Generated for this service (as a file)Encryption password to be used for symmetric cipher. Must be the same for all services that are intended * to share a cookie as a form of authentication
{@code cookie-encryption-name} Name of encryption configuration in {@link io.helidon.security.Security}. If used, security must be registered * in curent context or in global context (this is done automatically in Helidon MP).
{@code logout-endpoint-uri}From well known metadata endpointEndpoint to redirect user to log out from OIDC server.
{@code post-logout-uri} Required if logout is enabled. Endpoint the OIDC server redirects back to after logging user out.
{@code logout-enabled}{@code false}Whether logout support should be enabled. Requires encryption of cookies (and cookies must be used).
{@code cors} Cross-origin resource sharing settings. See {@link io.helidon.cors.CrossOriginConfig}.
{@code force-https-redirects} Force https for redirects to identity provider. * This is helpful if you have a frontend SSL or cloud load balancer in front and Helidon is serving plain http.
{@code optional-audience}{@code false}Allow audience claim to be optional.
{@code check-audience}{@code true}Turn audience claim check on when {@code true} or off when {@code false}.
*/ public final class OidcConfig extends TenantConfigImpl { /** * Default name of the header we expect JWT in. */ public static final String PARAM_HEADER_NAME = "X_OIDC_TOKEN_HEADER"; /** * Default name of the header we expect JWT in. */ public static final String PARAM_ID_HEADER_NAME = "X_OIDC_ID_TOKEN_HEADER"; /** * Default tenant query param name. */ public static final String DEFAULT_TENANT_PARAM_NAME = "h_tenant"; /** * Default access token cookie name. */ public static final String DEFAULT_COOKIE_NAME = "JSESSIONID"; /** * Default id token cookie name. */ public static final String DEFAULT_ID_COOKIE_NAME = DEFAULT_COOKIE_NAME + "_2"; /** * Default refresh token cookie name. */ public static final String DEFAULT_REFRESH_COOKIE_NAME = DEFAULT_COOKIE_NAME + "_3"; /** * Default tenant cookie name. */ public static final String DEFAULT_TENANT_COOKIE_NAME = "HELIDON_TENANT"; /** * Default state cookie name. */ public static final String DEFAULT_STATE_COOKIE_NAME = "OIDC_STATE"; static final String DEFAULT_REDIRECT_URI = "/oidc/redirect"; static final String DEFAULT_LOGOUT_URI = "/oidc/logout"; static final boolean DEFAULT_REDIRECT = true; static final String DEFAULT_ATTEMPT_PARAM = "h_ra"; static final int DEFAULT_MAX_REDIRECTS = 5; static final boolean DEFAULT_FORCE_HTTPS_REDIRECTS = false; static final Duration DEFAULT_TOKEN_REFRESH_SKEW = Duration.ofSeconds(5); static final boolean DEFAULT_RELATIVE_URIS = false; static final int DEFAULT_PROXY_PORT = 80; static final String DEFAULT_PROXY_PROTOCOL = "http"; static final String TENANT_IDENT = "name"; static final String DEFAULT_PARAM_NAME = "accessToken"; static final String DEFAULT_ID_TOKEN_PARAM_NAME = "id_token"; static final boolean DEFAULT_PARAM_USE = false; static final boolean DEFAULT_HEADER_USE = false; static final boolean DEFAULT_COOKIE_USE = true; private static final System.Logger LOGGER = System.getLogger(OidcConfig.class.getName()); private final Map tenantConfigurations; private final String redirectUri; private final String logoutUri; private final boolean logoutEnabled; private final String frontendUri; private final boolean redirect; private final String redirectAttemptParam; private final int maxRedirects; private final URI postLogoutUri; private final CrossOriginConfig crossOriginConfig; private final boolean forceHttpsRedirects; private final Duration tokenRefreshSkew; private final boolean relativeUris; private final WebClient webClient; private final Supplier webClientBuilderSupplier; private final LazyValue defaultTenant; private final boolean useParam; private final String paramName; private final String idTokenParamName; private final String tenantParamName; private final boolean useHeader; private final TokenHandler headerHandler; private final boolean useCookie; private final OidcCookieHandler tokenCookieHandler; private final OidcCookieHandler idTokenCookieHandler; private final OidcCookieHandler refreshTokenCookieHandler; private final OidcCookieHandler tenantCookieHandler; private final OidcCookieHandler stateCookieHandler; private final boolean tokenSignatureValidation; private final boolean idTokenSignatureValidation; private final boolean accessTokenIpCheck; private OidcConfig(Builder builder) { super(builder); this.frontendUri = builder.frontendUri; this.redirectUri = builder.redirectUri; this.logoutUri = builder.logoutUri; this.logoutEnabled = builder.logoutEnabled; this.postLogoutUri = builder.postLogoutUri; this.redirect = builder.redirect; this.redirectAttemptParam = builder.redirectAttemptParam; this.maxRedirects = builder.maxRedirects; this.forceHttpsRedirects = builder.forceHttpsRedirects; this.crossOriginConfig = builder.crossOriginConfig; this.tokenRefreshSkew = builder.tokenRefreshSkew; this.tenantConfigurations = Map.copyOf(builder.tenantConfigurations); this.webClient = builder.webClient; this.relativeUris = builder.relativeUris; this.useParam = builder.useParam; this.paramName = builder.paramName; this.idTokenParamName = builder.idTokenParamName; this.tenantParamName = builder.tenantParamName; this.useHeader = builder.useHeader; this.headerHandler = builder.headerHandler; this.useCookie = builder.useCookie; this.tokenCookieHandler = builder.tokenCookieBuilder.build(); this.idTokenCookieHandler = builder.idTokenCookieBuilder.build(); this.tenantCookieHandler = builder.tenantCookieBuilder.build(); this.refreshTokenCookieHandler = builder.refreshTokenCookieBuilder.build(); this.stateCookieHandler = builder.stateCookieBuilder.build(); this.tokenSignatureValidation = builder.tokenSignatureValidation; this.idTokenSignatureValidation = builder.idTokenSignatureValidation; this.accessTokenIpCheck = builder.accessTokenIpCheck; this.webClientBuilderSupplier = builder.webClientBuilderSupplier; this.defaultTenant = LazyValue.create(() -> Tenant.create(this, this)); LOGGER.log(Level.TRACE, () -> "Redirect URI with host: " + frontendUri + redirectUri); } /** * Create a builder to programmatically construct OIDC configuration. * * @return a new builder instance usable for fluent API */ public static Builder builder() { return new Builder(); } /** * Create a new instance from {@link io.helidon.common.config.Config}. * The config instance has to be on the node containing keys used by this class (e.g. client-id). * * @param config configuration used to obtain OIDC integration values * @return a new instance of this class configured from provided config */ public static OidcConfig create(Config config) { return OidcConfig.builder() .config(config) .build(); } /** * Whether to use query parameter to get the information from request. * * @return if query parameter should be used * @see Builder#useParam(Boolean) */ public boolean useParam() { return useParam; } /** * Query parameter name. * * @return name of the query parameter to use * @see Builder#paramName(String) */ public String paramName() { return paramName; } /** * Query id token parameter name. * * @return name of the query parameter to use * @see Builder#idTokenParamName(String) */ public String idTokenParamName() { return idTokenParamName; } /** * Tenant query parameter name. * * @return name of the tenant query parameter to use * @see Builder#paramTenantName(String) */ public String tenantParamName() { return tenantParamName; } /** * Whether to use HTTP header to get the information from request. * * @return if header should be used * @see Builder#useHeader(Boolean) */ public boolean useHeader() { return useHeader; } /** * {@link TokenHandler} to extract header information from request. * * @return handler to extract header * @see Builder#headerTokenHandler(TokenHandler) */ public TokenHandler headerHandler() { return headerHandler; } /** * Whether to use cooke to get the information from request. * * @return if cookie should be used * @see Builder#useCookie(Boolean) */ public boolean useCookie() { return useCookie; } /** * Cookie handler to create cookies or unset cookies for token. * * @return a new cookie handler */ public OidcCookieHandler tokenCookieHandler() { return tokenCookieHandler; } /** * Cookie handler to create cookies or unset cookies for id token. * * @return a new cookie handler */ public OidcCookieHandler idTokenCookieHandler() { return idTokenCookieHandler; } /** * Cookie handler to create cookies or unset cookies for tenant name. * * @return a new cookie handler */ public OidcCookieHandler tenantCookieHandler() { return tenantCookieHandler; } /** * Cookie handler to create cookies or unset cookies for refresh token. * * @return a new cookie handler */ public OidcCookieHandler refreshTokenCookieHandler() { return refreshTokenCookieHandler; } /** * Cookie handler to create cookies or unset cookies for state value. * * @return a new cookie handler */ public OidcCookieHandler stateCookieHandler() { return stateCookieHandler; } /** * Redirection URI. * * @return uri the OIDC server redirects back to * @see Builder#redirectUri(String) */ public String redirectUri() { return redirectUri; } /** * Whether to force https when redirecting to identity provider. * * @return {@code true} to force use of https */ public boolean forceHttpsRedirects() { return forceHttpsRedirects; } /** * Whether logout is enabled. * * @return {@code true} if logout is enabled */ public boolean logoutEnabled() { return logoutEnabled; } /** * Logout URI. * * @return uri that processes logout in Helidon and redirects to OIDC server logout * @see Builder#logoutUri(String) */ public String logoutUri() { return logoutUri; } /** * Post logout redirect URI. * * @return uri that OIDC server redirects to once logout is finished * @see Builder#postLogoutUri(java.net.URI) */ public URI postLogoutUri() { return postLogoutUri; } /** * Redirect URI with host information. * * @return redirect URI * @see Builder#redirectUri(String) */ public String redirectUriWithHost() { if (frontendUri == null) { throw new SecurityException("Frontend URI is not defined"); } return frontendUri + redirectUri; } /** * Redirect URI with host information taken from request, * unless an explicit frontend uri is defined in configuration. * * @param frontendUri the frontend uri * @return redirect URI */ public String redirectUriWithHost(String frontendUri) { if (this.frontendUri != null) { return redirectUriWithHost(); } return frontendUri + this.redirectUri; } /** * Whether to redirect to identity server if user is not authenticated. * * @return whether to redirect, defaults to true */ public boolean shouldRedirect() { return redirect; } /** * Name of the parameter used in state passed to OIDC to store the number of attempted redirects. * This is to prevent infinite redirects. * * @return name of the query parameter */ public String redirectAttemptParam() { return redirectAttemptParam; } /** * Maximal number of redirects allowed between Helidon and OIDC provider. * * @return maximal number of redirects */ public int maxRedirects() { return maxRedirects; } /** * Cross-origin resource sharing settings. * * @return CORS settings */ public CrossOriginConfig crossOriginConfig() { return crossOriginConfig; } /** * Amount of time access token should be refreshed before its expiration time. * * @return refresh time skew */ public Duration tokenRefreshSkew() { return tokenRefreshSkew; } /** * Determines whether to force the use of relative URIs in all requests, * regardless of the presence or absence of proxies or no-proxy lists. * * @return {@code true} if we should use relative URIs */ public boolean relativeUris() { return relativeUris; } /** * Client with configured proxy with no security. * * @return client for general use. */ public WebClient generalWebClient() { return webClient; } /** * Client with configured proxy and security. * * @return client for communicating with OIDC identity server */ public WebClient appWebClient() { return defaultTenant.get().appWebClient(); } /** * Return {@link TenantConfig} bound to the provided tenant id. * If no {@link TenantConfig} found, default OIDC configuration should be returned. * * @param tenantId tenant id of the configuration * @return configuration bound to the tenant id, or default oidc configuration if not found */ public TenantConfig tenantConfig(String tenantId) { TenantConfig tenantConfig = tenantConfigurations.get(tenantId); if (tenantConfig == null) { return tenantConfigurations.getOrDefault(TenantConfigFinder.DEFAULT_TENANT_ID, this); } return tenantConfig; } /** * Token endpoint URI. * * @return endpoint URI */ public URI tokenEndpointUri() { return defaultTenant.get().tokenEndpointUri(); } /** * Authorization endpoint. * * @return authorization endpoint uri as a string */ public String authorizationEndpointUri() { return defaultTenant.get().authorizationEndpointUri(); } /** * Logout endpoint on OIDC server. * * @return URI of the logout endpoint * @see OidcConfig.Builder#logoutEndpointUri(java.net.URI) */ public URI logoutEndpointUri() { return defaultTenant.get().logoutEndpointUri(); } /** * Token issuer. * * @return token issuer * @see OidcConfig.Builder#issuer(String) */ public String issuer() { return defaultTenant.get().issuer(); } /** * JWK used for signature validation. * * @return set of keys used use to verify tokens */ public JwkKeys signJwk() { return defaultTenant.get().signJwk(); } /** * Introspection endpoint URI. * * @return introspection endpoint URI * @see OidcConfig.Builder#introspectEndpointUri(java.net.URI) */ public URI introspectUri() { return defaultTenant.get().introspectUri(); } /** * Whether access token signature should be validated. * * @return validate access token signature */ public boolean tokenSignatureValidation() { return tokenSignatureValidation; } /** * Whether id token signature should be validated. * * @return validate id token signature */ public boolean idTokenSignatureValidation() { return idTokenSignatureValidation; } /** * Whether to check IP address access token was issued for. * * @return whether to check IP address access token was issued for */ public boolean accessTokenIpCheck() { return accessTokenIpCheck; } Supplier webClientBuilderSupplier() { return webClientBuilderSupplier; } /** * Client Authentication methods that are used by Clients to authenticate to the Authorization * Server when using the Token Endpoint. */ public enum ClientAuthentication { /** * Clients that have received a client_secret value from the Authorization Server authenticate with the Authorization * Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] using the HTTP Basic authentication scheme. * This is the default client authentication. */ CLIENT_SECRET_BASIC, /** * Clients that have received a client_secret value from the Authorization Server, authenticate with the Authorization * Server in accordance with Section 2.3.1 of OAuth 2.0 [RFC6749] by including the Client Credentials in the request body. */ CLIENT_SECRET_POST, /** * Clients that have received a client_secret value from the Authorization Server create a JWT using an HMAC SHA * algorithm, such as HMAC SHA-256. The HMAC (Hash-based Message Authentication Code) is calculated using the octets of * the UTF-8 representation of the client_secret as the shared key. * The Client authenticates in accordance with JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and * Authorization Grants [OAuth.JWT] and Assertion Framework for OAuth 2.0 Client Authentication and Authorization * Grants [OAuth.Assertions]. *

* The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following * OPTIONAL Claim Values. *

* Required: * {@code iss, sub, aud, jti, exp} *

* Optional: * {@code iat} */ CLIENT_SECRET_JWT, /** * Clients that have registered a public key sign a JWT using that key. The Client authenticates in accordance with * JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.JWT] and Assertion * Framework for OAuth 2.0 Client Authentication and Authorization Grants [OAuth.Assertions]. *

* The JWT MUST contain the following REQUIRED Claim Values and MAY contain the following * OPTIONAL Claim Values. *

* Required: * {@code iss, sub, aud, jti, exp} *

* Optional: * {@code iat} */ PRIVATE_KEY_JWT, /** * The Client does not authenticate itself at the Token Endpoint, either because it uses only the Implicit Flow (and so * does not use the Token Endpoint) or because it is a Public Client with no Client Secret or other authentication * mechanism. */ NONE } /** * Types of requests to identity provider. */ public enum RequestType { /** * Request to exchange code for a token issued against the token endpoint. */ CODE_TO_TOKEN, /** * Request to validate a JWT against an introspection endpoint. */ INTROSPECT_JWT; } /** * A fluent API {@link io.helidon.common.Builder} to build instances of {@link OidcConfig}. */ @Configured(description = "Open ID Connect configuration") public static class Builder extends BaseBuilder { private final Map tenantConfigurations = new HashMap<>(); // mandatory properties private String redirectUri = DEFAULT_REDIRECT_URI; private String logoutUri = DEFAULT_LOGOUT_URI; private boolean logoutEnabled = false; // optional properties private String frontendUri; private boolean redirect = DEFAULT_REDIRECT; private String redirectAttemptParam = DEFAULT_ATTEMPT_PARAM; private int maxRedirects = DEFAULT_MAX_REDIRECTS; private URI postLogoutUri; private CrossOriginConfig crossOriginConfig; private boolean forceHttpsRedirects = DEFAULT_FORCE_HTTPS_REDIRECTS; private Duration tokenRefreshSkew = DEFAULT_TOKEN_REFRESH_SKEW; private String proxyHost; private String proxyProtocol = DEFAULT_PROXY_PROTOCOL; private int proxyPort = DEFAULT_PROXY_PORT; private WebClient webClient; private Supplier webClientBuilderSupplier; private String paramName = DEFAULT_PARAM_NAME; private String idTokenParamName = DEFAULT_ID_TOKEN_PARAM_NAME; private String tenantParamName = DEFAULT_TENANT_PARAM_NAME; private boolean useHeader = DEFAULT_HEADER_USE; private boolean useParam = DEFAULT_PARAM_USE; private final OidcCookieHandler.Builder tenantCookieBuilder = OidcCookieHandler.builder() .encryptionEnabled(true) .cookieName(DEFAULT_TENANT_COOKIE_NAME); private final OidcCookieHandler.Builder tokenCookieBuilder = OidcCookieHandler.builder() .cookieName(DEFAULT_COOKIE_NAME); private final OidcCookieHandler.Builder idTokenCookieBuilder = OidcCookieHandler.builder() .encryptionEnabled(true) .cookieName(DEFAULT_ID_COOKIE_NAME); private final OidcCookieHandler.Builder refreshTokenCookieBuilder = OidcCookieHandler.builder() .encryptionEnabled(true) .cookieName(DEFAULT_REFRESH_COOKIE_NAME); private final OidcCookieHandler.Builder stateCookieBuilder = OidcCookieHandler.builder() .encryptionEnabled(true) .cookieName(DEFAULT_STATE_COOKIE_NAME); private TokenHandler headerHandler = TokenHandler.builder() .tokenHeader("Authorization") .tokenPrefix("bearer ") .build(); private boolean useCookie = DEFAULT_COOKIE_USE; private boolean cookieSameSiteDefault = true; private boolean relativeUris = DEFAULT_RELATIVE_URIS; private boolean tokenSignatureValidation = true; private boolean idTokenSignatureValidation = true; private boolean accessTokenIpCheck = true; protected Builder() { } @Override public OidcConfig build() { buildConfiguration(); Errors.Collector collector = Errors.collector(); if (useCookie && logoutEnabled) { if (postLogoutUri == null) { collector.fatal("post-logout-uri must be defined when logout is enabled."); } } // second set of validations collector.collect().checkValid(); if (cookieSameSiteDefault && useCookie) { // compare frontend and oidc endpoints to see if // we should use lax or strict by default if (identityUri() != null) { String identityHost = identityUri().getHost(); if (frontendUri != null) { String frontendHost = URI.create(frontendUri).getHost(); if (identityHost.equals(frontendHost)) { LOGGER.log(Level.INFO, "As frontend host and identity host are equal, setting Same-Site policy" + " to Strict this can be overridden using configuration option of OIDC: " + "\"cookie-same-site\""); this.tenantCookieBuilder.sameSite(SetCookie.SameSite.STRICT); this.tokenCookieBuilder.sameSite(SetCookie.SameSite.STRICT); this.idTokenCookieBuilder.sameSite(SetCookie.SameSite.STRICT); } } } } this.webClientBuilderSupplier = () -> OidcUtil.webClientBaseBuilder(proxyProtocol, proxyHost, proxyPort, relativeUris, clientTimeout()); this.webClient = webClientBuilderSupplier.get().build(); if (!tokenSignatureValidation) { LOGGER.log(Level.WARNING, "You have disabled access token signature validation. " + "This option should never be disabled for production environment " + "since it could cause security issues"); } if (!idTokenSignatureValidation) { LOGGER.log(Level.WARNING, "You have disabled id token signature validation. " + "This option should never be disabled for production environment " + "since it could cause security issues"); } return new OidcConfig(this); } /** * Update this builder with values from configuration. * * @param config configuration located on node with OIDC configuration keys (e.g. client-id) * @return updated builder instance */ public Builder config(Config config) { super.config(config); // mandatory configuration config.get("frontend-uri").asString().ifPresent(this::frontendUri); // environment config.get("proxy-protocol") .asString() .ifPresent(this::proxyProtocol); config.get("proxy-host").asString().ifPresent(this::proxyHost); config.get("proxy-port").asInt().ifPresent(this::proxyPort); config.get("relative-uris").asBoolean().ifPresent(this::relativeUris); // token handling config.get("query-param-use").asBoolean().ifPresent(this::useParam); config.get("query-param-name").asString().ifPresent(this::paramName); config.get("query-param-tenant-name").asString().ifPresent(this::paramTenantName); config.get("header-use").asBoolean().ifPresent(this::useHeader); config.get("header-token").as(TokenHandler.class).ifPresent(this::headerTokenHandler); config.get("cookie-use").asBoolean().ifPresent(this::useCookie); config.get("cookie-name").asString().ifPresent(this::cookieName); config.get("cookie-name-id-token").asString().ifPresent(this::cookieNameIdToken); config.get("cookie-name-tenant").asString().ifPresent(this::cookieTenantName); config.get("cookie-name-refresh-token").asString().ifPresent(this::cookieNameRefreshToken); config.get("cookie-name-state").asString().ifPresent(this::cookieNameState); config.get("cookie-domain").asString().ifPresent(this::cookieDomain); config.get("cookie-path").asString().ifPresent(this::cookiePath); config.get("cookie-max-age-seconds").asLong().ifPresent(this::cookieMaxAgeSeconds); config.get("cookie-http-only").asBoolean().ifPresent(this::cookieHttpOnly); config.get("cookie-secure").asBoolean().ifPresent(this::cookieSecure); config.get("cookie-same-site").asString().ifPresent(this::cookieSameSite); // encryption of cookies config.get("cookie-encryption-enabled").asBoolean().ifPresent(this::cookieEncryptionEnabled); config.get("cookie-encryption-id-enabled").asBoolean().ifPresent(this::cookieEncryptionEnabledIdToken); config.get("cookie-encryption-tenant-enabled").asBoolean().ifPresent(this::cookieEncryptionEnabledTenantName); config.get("cookie-encryption-refresh-enabled").asBoolean().ifPresent(this::cookieEncryptionEnabledRefreshToken); config.get("cookie-encryption-state-enabled").asBoolean().ifPresent(this::cookieEncryptionEnabledState); config.get("cookie-encryption-password").as(String.class) .map(String::toCharArray) .ifPresent(this::cookieEncryptionPassword); config.get("cookie-encryption-name").asString().ifPresent(this::cookieEncryptionName); // our application config.get("redirect-uri").asString().ifPresent(this::redirectUri); config.get("logout-uri").asString().ifPresent(this::logoutUri); config.get("post-logout-uri").as(URI.class).ifPresent(this::postLogoutUri); config.get("logout-enabled").asBoolean().ifPresent(this::logoutEnabled); config.get("redirect").asBoolean().ifPresent(this::redirect); config.get("redirect-attempt-param").asString().ifPresent(this::redirectAttemptParam); config.get("max-redirects").asInt().ifPresent(this::maxRedirects); config.get("force-https-redirects").asBoolean().ifPresent(this::forceHttpsRedirects); config.get("cors").map(CrossOriginConfig::create).ifPresent(this::crossOriginConfig); config.get("token-refresh-before-expiration").as(Duration.class).ifPresent(this::tokenRefreshSkew); config.get("token-signature-validation").asBoolean().ifPresent(this::tokenSignatureValidation); config.get("id-token-signature-validation").asBoolean().ifPresent(this::idTokenSignatureValidation); config.get("access-token-ip-check").asBoolean().ifPresent(this::accessTokenIpCheck); config.get("tenants").asList(Config.class) .ifPresent(confList -> confList.forEach(tenantConfig -> tenantFromConfig(config, tenantConfig))); return this; } private void tenantFromConfig(Config defaultConfig, Config tenantConfig) { addTenantConfig(TenantConfig.tenantBuilder().config(defaultConfig).config(tenantConfig).build()); } /** * Amount of time access token should be refreshed before its expiration time. * Default is 5 seconds. * * @param tokenRefreshSkew time to refresh token before expiration * @return updated builder */ public Builder tokenRefreshSkew(Duration tokenRefreshSkew) { this.tokenRefreshSkew = tokenRefreshSkew; return this; } /** * Assign cross-origin resource sharing settings. * * @param crossOriginConfig cross-origin settings to apply to the redirect endpoint * @return updated builder instance */ @ConfiguredOption(key = "cors") public Builder crossOriginConfig(CrossOriginConfig crossOriginConfig) { this.crossOriginConfig = crossOriginConfig; return this; } /** * Whether to enable logout support. * When logout is enabled, we use two cookies (User token and user ID token) and we expose * an endpoint {@link #logoutUri(String)} that can be used to log the user out from Helidon session * and also from OIDC session (uses {@link #logoutEndpointUri(java.net.URI)} on OIDC server). * Logout support is disabled by default. * * @param logoutEnabled whether to enable logout * @return updated builder instance */ public Builder logoutEnabled(Boolean logoutEnabled) { this.logoutEnabled = logoutEnabled; return this; } /** * By default, the client should redirect to the identity server for the user to log in. * This behavior can be overridden by setting redirect to false. When token is not present in the request, the client * will not redirect and just return appropriate error response code. * * @param redirect Whether to redirect to OIDC server in case the request does not contain sufficient information to * authenticate the user, defaults to true * @return updated builder instance */ @ConfiguredOption("false") public Builder redirect(boolean redirect) { this.redirect = redirect; return this; } /** * Full URI of this application that is visible from user browser. * Used to redirect request back from identity server after successful login. * * @param uri the frontend URI, such as "http://my.server.com/myApp * @return updated builder instance */ @ConfiguredOption public Builder frontendUri(String uri) { this.frontendUri = uri; return this; } /** * Force HTTPS for redirects to identity provider. * Defaults to {@code false}. * * @param forceHttpsRedirects flag to redirect with https * @return updated builder instance */ @ConfiguredOption("false") public Builder forceHttpsRedirects(boolean forceHttpsRedirects) { this.forceHttpsRedirects = forceHttpsRedirects; return this; } /** * Can be set to {@code true} to force the use of relative URIs in all requests, * regardless of the presence or absence of proxies or no-proxy lists. By default, * requests that use the Proxy will have absolute URIs. Set this flag to {@code true} * if the host is unable to accept absolute URIs. * Defaults to {@value #DEFAULT_RELATIVE_URIS}. * * @param relativeUris relative URIs flag * @return updated builder instance */ @ConfiguredOption("false") public Builder relativeUris(boolean relativeUris) { this.relativeUris = relativeUris; return this; } /** * URI to register web server component on, used by the OIDC server to * redirect authorization requests to after a user logs in or approves * scopes. * Note that usually the redirect URI configured here must be the * same one as configured on OIDC server. * *

* Defaults to {@value #DEFAULT_REDIRECT_URI} * * @param redirectUri the URI (path without protocol, host and port) used to redirect requests back to us * @return updated builder instance */ @ConfiguredOption(value = DEFAULT_REDIRECT_URI) public Builder redirectUri(String redirectUri) { this.redirectUri = redirectUri; return this; } /** * Path to register web server for logout link. * This should be used by application to redirect user to logout the current user * from Helidon based session (when using cookies and redirection). * This endpoint will logout user from Helidon session (remove Helidon cookies) and redirect user to * logout screen of the OIDC server. * * @param logoutUri URI path for logout component * @return updated builder instance */ public Builder logoutUri(String logoutUri) { this.logoutUri = logoutUri; return this; } /** * URI to redirect to once the logout process is done. * The endpoint should not be protected by OIDC (as this would serve no purpose, just to log the user in again). * This endpoint usually must be registered with the application as the allowed post-logout redirect URI. * Note that the URI should not contain any query parameters. You can obtain state using the * state query parameter that must be provided to {@link #logoutUri(String)}. * * @param uri this will be used by the OIDC server to redirect user to once logout is done, can define just path, * in which case the scheme, host and port will be taken from request. * @return updated builder instance */ public Builder postLogoutUri(URI uri) { this.postLogoutUri = uri; return this; } /** * Configure the parameter used to store the number of attempts in redirect. *

* Defaults to {@value #DEFAULT_ATTEMPT_PARAM} * * @param paramName name of the parameter used in the state parameter * @return updated builder instance */ @ConfiguredOption(value = DEFAULT_ATTEMPT_PARAM) public Builder redirectAttemptParam(String paramName) { this.redirectAttemptParam = paramName; return this; } /** * Configure maximal number of redirects when redirecting to an OIDC provider within a single authentication * attempt. *

* Defaults to {@value #DEFAULT_MAX_REDIRECTS} * * @param maxRedirects maximal number of redirects from Helidon to OIDC provider * @return updated builder instance */ @ConfiguredOption("5") public Builder maxRedirects(int maxRedirects) { this.maxRedirects = maxRedirects; return this; } /** * Proxy protocol to use when proxy is used. * Defaults to {@value DEFAULT_PROXY_PROTOCOL}. * * @param protocol protocol to use (such as https) * @return updated builder instance */ @ConfiguredOption(value = DEFAULT_PROXY_PROTOCOL) public Builder proxyProtocol(String protocol) { this.proxyProtocol = protocol; return this; } /** * Proxy host to use. When defined, triggers usage of proxy for HTTP requests. * Setting to empty String has the same meaning as setting to null - disables proxy. * * @param proxyHost host of the proxy * @return updated builder instance * @see #proxyProtocol(String) * @see #proxyPort(int) */ @ConfiguredOption public Builder proxyHost(String proxyHost) { if ((proxyHost == null) || proxyHost.isEmpty()) { this.proxyHost = null; } else { this.proxyHost = proxyHost; } return this; } /** * Proxy port. * Defaults to {@value DEFAULT_PROXY_PORT} * * @param proxyPort port of the proxy server to use * @return updated builder instance */ @ConfiguredOption("80") public Builder proxyPort(int proxyPort) { this.proxyPort = proxyPort; return this; } /** * A {@link TokenHandler} to * process header containing a JWT. * Default is "Authorization" header with a prefix "bearer ". * * @param tokenHandler token handler to use * @return updated builder instance */ @ConfiguredOption(key = "header-token") public Builder headerTokenHandler(TokenHandler tokenHandler) { this.headerHandler = tokenHandler; return this; } /** * Whether to expect JWT in a header field. * * @param useHeader set to true to use a header extracted with {@link #headerTokenHandler(TokenHandler)} * @return updated builder instance */ @ConfiguredOption(key = "header-use", value = "true") public Builder useHeader(Boolean useHeader) { this.useHeader = useHeader; return this; } /** * Name of a query parameter that contains the JWT access token when parameter is used. * * @param paramName name of the query parameter to expect * @return updated builder instance */ @ConfiguredOption(key = "query-param-name", value = DEFAULT_PARAM_NAME) public Builder paramName(String paramName) { this.paramName = paramName; return this; } /** * Name of a query parameter that contains the JWT id token when parameter is used. * * @param idTokenParamName name of the query parameter to expect * @return updated builder instance */ @ConfiguredOption(key = "query-id-token-param-name", value = DEFAULT_ID_TOKEN_PARAM_NAME) public Builder idTokenParamName(String idTokenParamName) { this.idTokenParamName = idTokenParamName; return this; } /** * Name of a query parameter that contains the tenant name when the parameter is used. * Defaults to {@link #DEFAULT_TENANT_PARAM_NAME}. * * @param paramName name of the query parameter to expect * @return updated builder instance */ @ConfiguredOption(key = "query-param-tenant-name", value = DEFAULT_TENANT_PARAM_NAME) public Builder paramTenantName(String paramName) { this.tenantParamName = paramName; return this; } /** * Whether to use a query parameter to send JWT token from application to this * server. * * @param useParam whether to use a query parameter (true) or not (false) * @return updated builder instance * @see #paramName(String) */ @ConfiguredOption(key = "query-param-use", value = "false") public Builder useParam(Boolean useParam) { this.useParam = useParam; return this; } /** * Name of the encryption configuration available through {@link Security#encrypt(String, byte[])} and * {@link Security#decrypt(String, String)}. * If configured and encryption is enabled for any cookie, * Security MUST be configured in global or current {@code io.helidon.common.context.Context} (this * is done automatically in Helidon MP). * * @param cookieEncryptionName name of the encryption configuration in security used to encrypt/decrypt cookies * @return updated builder */ @ConfiguredOption public Builder cookieEncryptionName(String cookieEncryptionName) { this.tokenCookieBuilder.encryptionName(cookieEncryptionName); this.idTokenCookieBuilder.encryptionName(cookieEncryptionName); this.tenantCookieBuilder.encryptionName(cookieEncryptionName); this.refreshTokenCookieBuilder.encryptionName(cookieEncryptionName); this.stateCookieBuilder.encryptionName(cookieEncryptionName); return this; } /** * Master password for encryption/decryption of cookies. This must be configured to the same value on each microservice * using the cookie. * * @param cookieEncryptionPassword encryption password * @return updated builder */ @ConfiguredOption public Builder cookieEncryptionPassword(char[] cookieEncryptionPassword) { this.tokenCookieBuilder.encryptionPassword(cookieEncryptionPassword); this.idTokenCookieBuilder.encryptionPassword(cookieEncryptionPassword); this.tenantCookieBuilder.encryptionPassword(cookieEncryptionPassword); this.refreshTokenCookieBuilder.encryptionPassword(cookieEncryptionPassword); this.stateCookieBuilder.encryptionPassword(cookieEncryptionPassword); return this; } /** * Whether to encrypt token cookie created by this microservice. * Defaults to {@code false}. * * @param cookieEncryptionEnabled whether cookie should be encrypted {@code true}, or as obtained from * OIDC server {@code false} * @return updated builder instance */ @ConfiguredOption(value = "false") public Builder cookieEncryptionEnabled(boolean cookieEncryptionEnabled) { this.tokenCookieBuilder.encryptionEnabled(cookieEncryptionEnabled); return this; } /** * Whether to encrypt id token cookie created by this microservice. * Defaults to {@code true}. * * @param cookieEncryptionEnabled whether cookie should be encrypted {@code true}, or as obtained from * OIDC server {@code false} * @return updated builder instance */ @ConfiguredOption(key = "cookie-encryption-id-enabled", value = "true") public Builder cookieEncryptionEnabledIdToken(boolean cookieEncryptionEnabled) { this.idTokenCookieBuilder.encryptionEnabled(cookieEncryptionEnabled); return this; } /** * Whether to encrypt tenant name cookie created by this microservice. * Defaults to {@code true}. * * @param cookieEncryptionEnabled whether cookie should be encrypted {@code true}, or as plain text name {@code false} * @return updated builder instance */ @ConfiguredOption(key = "cookie-encryption-tenant-enabled", value = "true") public Builder cookieEncryptionEnabledTenantName(boolean cookieEncryptionEnabled) { this.tenantCookieBuilder.encryptionEnabled(cookieEncryptionEnabled); return this; } /** * Whether to encrypt refresh token cookie created by this microservice. * Defaults to {@code true}. * * @param cookieEncryptionEnabled whether cookie should be encrypted {@code true}, or as obtained from * OIDC server {@code false} * @return updated builder instance */ @ConfiguredOption(key = "cookie-encryption-refresh-enabled", value = "true") public Builder cookieEncryptionEnabledRefreshToken(boolean cookieEncryptionEnabled) { this.refreshTokenCookieBuilder.encryptionEnabled(cookieEncryptionEnabled); return this; } /** * Whether to encrypt state cookie created by this microservice. * Defaults to {@code true}. * * @param cookieEncryptionEnabled whether cookie should be encrypted {@code true}, or as sent to * OIDC server {@code false} * @return updated builder instance */ @ConfiguredOption(key = "cookie-encryption-state-enabled", value = "true") public Builder cookieEncryptionEnabledState(boolean cookieEncryptionEnabled) { this.stateCookieBuilder.encryptionEnabled(cookieEncryptionEnabled); return this; } /** * When using cookie, used to set the SameSite cookie value. Can be * "Strict" or "Lax" * * @param sameSite SameSite cookie attribute value * @return updated builder instance */ public Builder cookieSameSite(String sameSite) { return cookieSameSite(SetCookie.SameSite.valueOf(sameSite.toUpperCase(Locale.ROOT))); } /** * When using cookie, used to set the SameSite cookie value. Can be * "Strict" or "Lax". * * @param sameSite SameSite cookie attribute * @return updated builder instance */ @ConfiguredOption(value = "LAX") public Builder cookieSameSite(SetCookie.SameSite sameSite) { this.tokenCookieBuilder.sameSite(sameSite); this.idTokenCookieBuilder.sameSite(sameSite); this.tenantCookieBuilder.sameSite(sameSite); this.refreshTokenCookieBuilder.sameSite(sameSite); this.stateCookieBuilder.sameSite(sameSite); this.cookieSameSiteDefault = false; return this; } /** * When using cookie, if set to true, the Secure attribute will be configured. * Defaults to false. * * @param secure whether the cookie should be secure (true) or not (false) * @return updated builder instance */ @ConfiguredOption("false") public Builder cookieSecure(Boolean secure) { this.tokenCookieBuilder.secure(secure); this.idTokenCookieBuilder.secure(secure); this.tenantCookieBuilder.secure(secure); this.refreshTokenCookieBuilder.secure(secure); this.stateCookieBuilder.secure(secure); return this; } /** * When using cookie, if set to true, the HttpOnly attribute will be configured. * Defaults to {@value OidcCookieHandler.Builder#DEFAULT_HTTP_ONLY}. * * @param httpOnly whether the cookie should be HttpOnly (true) or not (false) * @return updated builder instance */ @ConfiguredOption("true") public Builder cookieHttpOnly(Boolean httpOnly) { this.tokenCookieBuilder.httpOnly(httpOnly); this.idTokenCookieBuilder.httpOnly(httpOnly); this.tenantCookieBuilder.httpOnly(httpOnly); this.refreshTokenCookieBuilder.httpOnly(httpOnly); this.stateCookieBuilder.httpOnly(httpOnly); return this; } /** * When using cookie, used to set MaxAge attribute of the cookie, defining how long * the cookie is valid. * Not used by default. * * @param age age in seconds * @return updated builder instance */ @ConfiguredOption public Builder cookieMaxAgeSeconds(long age) { this.tokenCookieBuilder.maxAge(age); this.idTokenCookieBuilder.maxAge(age); this.tenantCookieBuilder.maxAge(age); this.refreshTokenCookieBuilder.maxAge(age); this.stateCookieBuilder.maxAge(age); return this; } /** * Path the cookie is valid for. * Defaults to "/". * * @param path the path to use as value of cookie "Path" attribute * @return updated builder instance */ @ConfiguredOption(value = OidcCookieHandler.Builder.DEFAULT_PATH) public Builder cookiePath(String path) { this.tokenCookieBuilder.path(path); this.idTokenCookieBuilder.path(path); this.tenantCookieBuilder.path(path); this.refreshTokenCookieBuilder.path(path); this.stateCookieBuilder.path(path); return this; } /** * Domain the cookie is valid for. * Not used by default. * * @param domain domain to use as value of cookie "Domain" attribute * @return updated builder instance */ @ConfiguredOption public Builder cookieDomain(String domain) { this.tokenCookieBuilder.domain(domain); this.idTokenCookieBuilder.domain(domain); this.tenantCookieBuilder.domain(domain); this.refreshTokenCookieBuilder.domain(domain); this.stateCookieBuilder.domain(domain); return this; } /** * Name of the cookie to use. * Defaults to {@value #DEFAULT_COOKIE_NAME}. * * @param cookieName name of a cookie * @return updated builder instance */ @ConfiguredOption(value = DEFAULT_COOKIE_NAME) public Builder cookieName(String cookieName) { this.tokenCookieBuilder.cookieName(cookieName); return this; } /** * Name of the cookie to use for id token. * Defaults to {@value #DEFAULT_COOKIE_NAME}_2. * * This cookie is only used when logout is enabled, as otherwise it is not needed. * Content of this cookie is encrypted. * * @param cookieName name of a cookie * @return updated builder instance */ @ConfiguredOption(DEFAULT_ID_COOKIE_NAME) public Builder cookieNameIdToken(String cookieName) { this.idTokenCookieBuilder.cookieName(cookieName); return this; } /** * The name of the cookie to use for the tenant name. * Defaults to {@value #DEFAULT_TENANT_COOKIE_NAME}. * * @param cookieName name of a cookie * @return updated builder instance */ @ConfiguredOption(key = "cookie-name-tenant", value = DEFAULT_TENANT_COOKIE_NAME) public Builder cookieTenantName(String cookieName) { this.tenantCookieBuilder.cookieName(cookieName); return this; } /** * The name of the cookie to use for the refresh token. * Defaults to {@value #DEFAULT_REFRESH_COOKIE_NAME}. * * @param cookieName name of a cookie * @return updated builder instance */ @ConfiguredOption(DEFAULT_REFRESH_COOKIE_NAME) public Builder cookieNameRefreshToken(String cookieName) { this.refreshTokenCookieBuilder.cookieName(cookieName); return this; } /** * The name of the cookie to use for the state storage. * Defaults to {@value #DEFAULT_STATE_COOKIE_NAME}. * * @param cookieName name of a cookie * @return updated builder instance */ @ConfiguredOption(DEFAULT_REFRESH_COOKIE_NAME) public Builder cookieNameState(String cookieName) { this.stateCookieBuilder.cookieName(cookieName); return this; } /** * Whether to use cookie to store JWT between requests. * Defaults to {@value #DEFAULT_COOKIE_USE}. * * @param useCookie whether to use cookie to store JWT (true) or not (false)) * @return updated builder instance */ @ConfiguredOption(key = "cookie-use", value = "true") public Builder useCookie(Boolean useCookie) { this.useCookie = useCookie; return this; } /** * Add specific {@link TenantConfig} instance. * * @param tenantConfig tenant configuration * @return updated builder instance */ @ConfiguredOption(key = "tenants", type = TenantConfig.class, description = "Configurations of the tenants") public Builder addTenantConfig(TenantConfig tenantConfig) { tenantConfigurations.put(tenantConfig.name(), tenantConfig); return this; } /** * Whether access token signature check should be enabled. * Signature check is enabled by default, and it is highly recommended to not change that. * Change this setting only when you really know what you are doing, otherwise it could case security issues. * * @param enabled whether access token signature check is enabled * @return updated builder instance */ @ConfiguredOption("true") public Builder tokenSignatureValidation(boolean enabled) { tokenSignatureValidation = enabled; return this; } /** * Whether id token signature check should be enabled. * Signature check is enabled by default, and it is highly recommended to not change that. * Change this setting only when you really know what you are doing, otherwise it could case security issues. * * @param enabled whether id token signature check is enabled * @return updated builder instance */ @ConfiguredOption("true") public Builder idTokenSignatureValidation(boolean enabled) { idTokenSignatureValidation = enabled; return this; } /** * Whether to check if current IP address matches the one access token was issued for. * This check helps with cookie replay attack prevention. * * @param enabled whether to check if current IP address matches the one access token was issued for * @return updated builder instance */ @ConfiguredOption("true") public Builder accessTokenIpCheck(boolean enabled) { accessTokenIpCheck = enabled; return this; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy