mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-05 16:22:17 +00:00
272 lines
13 KiB
Java
272 lines
13 KiB
Java
package auth.sso.oidc;
|
|
|
|
import static auth.AuthUtils.*;
|
|
import static auth.ConfigUtil.*;
|
|
|
|
import auth.sso.SsoConfigs;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import lombok.Getter;
|
|
|
|
/** Class responsible for extracting and validating OIDC related configurations. */
|
|
@Getter
|
|
public class OidcConfigs extends SsoConfigs {
|
|
|
|
/** Required configs */
|
|
public static final String OIDC_CLIENT_ID_CONFIG_PATH = "auth.oidc.clientId";
|
|
|
|
public static final String OIDC_CLIENT_SECRET_CONFIG_PATH = "auth.oidc.clientSecret";
|
|
public static final String OIDC_DISCOVERY_URI_CONFIG_PATH = "auth.oidc.discoveryUri";
|
|
|
|
/** Optional configs */
|
|
public static final String OIDC_USERNAME_CLAIM_CONFIG_PATH = "auth.oidc.userNameClaim";
|
|
|
|
public static final String OIDC_USERNAME_CLAIM_REGEX_CONFIG_PATH = "auth.oidc.userNameClaimRegex";
|
|
public static final String OIDC_SCOPE_CONFIG_PATH = "auth.oidc.scope";
|
|
public static final String OIDC_CLIENT_NAME_CONFIG_PATH = "auth.oidc.clientName";
|
|
public static final String OIDC_CLIENT_AUTHENTICATION_METHOD_CONFIG_PATH =
|
|
"auth.oidc.clientAuthenticationMethod";
|
|
public static final String OIDC_JIT_PROVISIONING_ENABLED_CONFIG_PATH =
|
|
"auth.oidc.jitProvisioningEnabled";
|
|
public static final String OIDC_PRE_PROVISIONING_REQUIRED_CONFIG_PATH =
|
|
"auth.oidc.preProvisioningRequired";
|
|
public static final String OIDC_EXTRACT_GROUPS_ENABLED = "auth.oidc.extractGroupsEnabled";
|
|
public static final String OIDC_GROUPS_CLAIM_CONFIG_PATH_CONFIG_PATH =
|
|
"auth.oidc.groupsClaim"; // Claim expected to be an array of group names.
|
|
public static final String OIDC_RESPONSE_TYPE = "auth.oidc.responseType";
|
|
public static final String OIDC_RESPONSE_MODE = "auth.oidc.responseMode";
|
|
public static final String OIDC_USE_NONCE = "auth.oidc.useNonce";
|
|
public static final String OIDC_CUSTOM_PARAM_RESOURCE = "auth.oidc.customParam.resource";
|
|
public static final String OIDC_READ_TIMEOUT = "auth.oidc.readTimeout";
|
|
public static final String OIDC_CONNECT_TIMEOUT = "auth.oidc.connectTimeout";
|
|
public static final String OIDC_EXTRACT_JWT_ACCESS_TOKEN_CLAIMS =
|
|
"auth.oidc.extractJwtAccessTokenClaims";
|
|
public static final String OIDC_PREFERRED_JWS_ALGORITHM = "auth.oidc.preferredJwsAlgorithm";
|
|
public static final String OIDC_GRANT_TYPE = "auth.oidc.grantType";
|
|
public static final String OIDC_ACR_VALUES = "auth.oidc.acrValues";
|
|
|
|
/** Default values */
|
|
private static final String DEFAULT_OIDC_USERNAME_CLAIM = "email";
|
|
|
|
private static final String DEFAULT_OIDC_USERNAME_CLAIM_REGEX = "(.*)";
|
|
private static final String DEFAULT_OIDC_SCOPE = "openid profile email";
|
|
// Often "group" must be included for groups.
|
|
private static final String DEFAULT_OIDC_CLIENT_NAME = "oidc";
|
|
private static final String DEFAULT_OIDC_CLIENT_AUTHENTICATION_METHOD = "client_secret_basic";
|
|
private static final String DEFAULT_OIDC_JIT_PROVISIONING_ENABLED = "true";
|
|
private static final String DEFAULT_OIDC_PRE_PROVISIONING_REQUIRED = "false";
|
|
private static final String DEFAULT_OIDC_EXTRACT_GROUPS_ENABLED = "false";
|
|
// False since extraction of groups can overwrite existing group membership.
|
|
private static final String DEFAULT_OIDC_GROUPS_CLAIM = "groups";
|
|
private static final String DEFAULT_OIDC_READ_TIMEOUT = "5000";
|
|
private static final String DEFAULT_OIDC_CONNECT_TIMEOUT = "1000";
|
|
|
|
private final String clientId;
|
|
private final String clientSecret;
|
|
private final String discoveryUri;
|
|
private final String userNameClaim;
|
|
private final String userNameClaimRegex;
|
|
private final String scope;
|
|
private final String clientName;
|
|
private final String clientAuthenticationMethod;
|
|
private final boolean jitProvisioningEnabled;
|
|
private final boolean preProvisioningRequired;
|
|
private final boolean extractGroupsEnabled;
|
|
private final String groupsClaimName;
|
|
private final Optional<String> responseType;
|
|
private final Optional<String> responseMode;
|
|
private final Optional<Boolean> useNonce;
|
|
private final Optional<String> customParamResource;
|
|
private final String readTimeout;
|
|
private final String connectTimeout;
|
|
private final Optional<Boolean> extractJwtAccessTokenClaims;
|
|
private final Optional<String> preferredJwsAlgorithm;
|
|
private final Optional<String> grantType;
|
|
private final Optional<String> acrValues;
|
|
|
|
public OidcConfigs(Builder builder) {
|
|
super(builder);
|
|
this.clientId = builder.clientId;
|
|
this.clientSecret = builder.clientSecret;
|
|
this.discoveryUri = builder.discoveryUri;
|
|
this.userNameClaim = builder.userNameClaim;
|
|
this.userNameClaimRegex = builder.userNameClaimRegex;
|
|
this.scope = builder.scope;
|
|
this.clientName = builder.clientName;
|
|
this.clientAuthenticationMethod = builder.clientAuthenticationMethod;
|
|
this.jitProvisioningEnabled = builder.jitProvisioningEnabled;
|
|
this.preProvisioningRequired = builder.preProvisioningRequired;
|
|
this.extractGroupsEnabled = builder.extractGroupsEnabled;
|
|
this.groupsClaimName = builder.groupsClaimName;
|
|
this.responseType = builder.responseType;
|
|
this.responseMode = builder.responseMode;
|
|
this.useNonce = builder.useNonce;
|
|
this.customParamResource = builder.customParamResource;
|
|
this.readTimeout = builder.readTimeout;
|
|
this.connectTimeout = builder.connectTimeout;
|
|
this.extractJwtAccessTokenClaims = builder.extractJwtAccessTokenClaims;
|
|
this.preferredJwsAlgorithm = builder.preferredJwsAlgorithm;
|
|
this.acrValues = builder.acrValues;
|
|
this.grantType = builder.grantType;
|
|
}
|
|
|
|
public static class Builder extends SsoConfigs.Builder<Builder> {
|
|
private String clientId;
|
|
private String clientSecret;
|
|
private String discoveryUri;
|
|
private String userNameClaim = DEFAULT_OIDC_USERNAME_CLAIM;
|
|
private String userNameClaimRegex = DEFAULT_OIDC_USERNAME_CLAIM_REGEX;
|
|
private String scope = DEFAULT_OIDC_SCOPE;
|
|
private String clientName = DEFAULT_OIDC_CLIENT_NAME;
|
|
private String clientAuthenticationMethod = DEFAULT_OIDC_CLIENT_AUTHENTICATION_METHOD;
|
|
private boolean jitProvisioningEnabled =
|
|
Boolean.parseBoolean(DEFAULT_OIDC_JIT_PROVISIONING_ENABLED);
|
|
private boolean preProvisioningRequired =
|
|
Boolean.parseBoolean(DEFAULT_OIDC_PRE_PROVISIONING_REQUIRED);
|
|
private boolean extractGroupsEnabled =
|
|
Boolean.parseBoolean(DEFAULT_OIDC_EXTRACT_GROUPS_ENABLED);
|
|
private String groupsClaimName = DEFAULT_OIDC_GROUPS_CLAIM;
|
|
private Optional<String> responseType = Optional.empty();
|
|
private Optional<String> responseMode = Optional.empty();
|
|
private Optional<Boolean> useNonce = Optional.empty();
|
|
private Optional<String> customParamResource = Optional.empty();
|
|
private String readTimeout = DEFAULT_OIDC_READ_TIMEOUT;
|
|
private String connectTimeout = DEFAULT_OIDC_CONNECT_TIMEOUT;
|
|
private Optional<Boolean> extractJwtAccessTokenClaims = Optional.empty();
|
|
private Optional<String> preferredJwsAlgorithm = Optional.empty();
|
|
private Optional<String> grantType = Optional.empty();
|
|
private Optional<String> acrValues = Optional.empty();
|
|
|
|
public Builder from(final com.typesafe.config.Config configs) {
|
|
super.from(configs);
|
|
clientId = getRequired(configs, OIDC_CLIENT_ID_CONFIG_PATH);
|
|
clientSecret = getRequired(configs, OIDC_CLIENT_SECRET_CONFIG_PATH);
|
|
discoveryUri = getRequired(configs, OIDC_DISCOVERY_URI_CONFIG_PATH);
|
|
userNameClaim =
|
|
getOptional(configs, OIDC_USERNAME_CLAIM_CONFIG_PATH, DEFAULT_OIDC_USERNAME_CLAIM);
|
|
userNameClaimRegex =
|
|
getOptional(
|
|
configs, OIDC_USERNAME_CLAIM_REGEX_CONFIG_PATH, DEFAULT_OIDC_USERNAME_CLAIM_REGEX);
|
|
scope = getOptional(configs, OIDC_SCOPE_CONFIG_PATH, DEFAULT_OIDC_SCOPE);
|
|
clientName = getOptional(configs, OIDC_CLIENT_NAME_CONFIG_PATH, DEFAULT_OIDC_CLIENT_NAME);
|
|
clientAuthenticationMethod =
|
|
getOptional(
|
|
configs,
|
|
OIDC_CLIENT_AUTHENTICATION_METHOD_CONFIG_PATH,
|
|
DEFAULT_OIDC_CLIENT_AUTHENTICATION_METHOD);
|
|
jitProvisioningEnabled =
|
|
Boolean.parseBoolean(
|
|
getOptional(
|
|
configs,
|
|
OIDC_JIT_PROVISIONING_ENABLED_CONFIG_PATH,
|
|
DEFAULT_OIDC_JIT_PROVISIONING_ENABLED));
|
|
preProvisioningRequired =
|
|
Boolean.parseBoolean(
|
|
getOptional(
|
|
configs,
|
|
OIDC_PRE_PROVISIONING_REQUIRED_CONFIG_PATH,
|
|
DEFAULT_OIDC_PRE_PROVISIONING_REQUIRED));
|
|
extractGroupsEnabled =
|
|
Boolean.parseBoolean(
|
|
getOptional(
|
|
configs, OIDC_EXTRACT_GROUPS_ENABLED, DEFAULT_OIDC_EXTRACT_GROUPS_ENABLED));
|
|
groupsClaimName =
|
|
getOptional(
|
|
configs, OIDC_GROUPS_CLAIM_CONFIG_PATH_CONFIG_PATH, DEFAULT_OIDC_GROUPS_CLAIM);
|
|
responseType = getOptional(configs, OIDC_RESPONSE_TYPE);
|
|
responseMode = getOptional(configs, OIDC_RESPONSE_MODE);
|
|
useNonce = getOptional(configs, OIDC_USE_NONCE).map(Boolean::parseBoolean);
|
|
customParamResource = getOptional(configs, OIDC_CUSTOM_PARAM_RESOURCE);
|
|
readTimeout = getOptional(configs, OIDC_READ_TIMEOUT, DEFAULT_OIDC_READ_TIMEOUT);
|
|
connectTimeout = getOptional(configs, OIDC_CONNECT_TIMEOUT, DEFAULT_OIDC_CONNECT_TIMEOUT);
|
|
extractJwtAccessTokenClaims =
|
|
getOptional(configs, OIDC_EXTRACT_JWT_ACCESS_TOKEN_CLAIMS).map(Boolean::parseBoolean);
|
|
preferredJwsAlgorithm =
|
|
Optional.ofNullable(getOptional(configs, OIDC_PREFERRED_JWS_ALGORITHM, null));
|
|
grantType = Optional.ofNullable(getOptional(configs, OIDC_GRANT_TYPE, null));
|
|
acrValues = Optional.ofNullable(getOptional(configs, OIDC_ACR_VALUES, null));
|
|
return this;
|
|
}
|
|
|
|
public Builder from(final com.typesafe.config.Config configs, final String ssoSettingsJsonStr) {
|
|
super.from(ssoSettingsJsonStr);
|
|
if (jsonNode.has(CLIENT_ID)) {
|
|
clientId = jsonNode.get(CLIENT_ID).asText();
|
|
}
|
|
if (jsonNode.has(CLIENT_SECRET)) {
|
|
clientSecret = jsonNode.get(CLIENT_SECRET).asText();
|
|
}
|
|
if (jsonNode.has(DISCOVERY_URI)) {
|
|
discoveryUri = jsonNode.get(DISCOVERY_URI).asText();
|
|
}
|
|
if (jsonNode.has(USER_NAME_CLAIM)) {
|
|
userNameClaim = jsonNode.get(USER_NAME_CLAIM).asText();
|
|
}
|
|
if (jsonNode.has(USER_NAME_CLAIM_REGEX)) {
|
|
userNameClaimRegex = jsonNode.get(USER_NAME_CLAIM_REGEX).asText();
|
|
}
|
|
if (jsonNode.has(SCOPE)) {
|
|
scope = jsonNode.get(SCOPE).asText();
|
|
}
|
|
if (jsonNode.has(CLIENT_NAME)) {
|
|
clientName = jsonNode.get(CLIENT_NAME).asText();
|
|
}
|
|
if (jsonNode.has(CLIENT_AUTHENTICATION_METHOD)) {
|
|
clientAuthenticationMethod = jsonNode.get(CLIENT_AUTHENTICATION_METHOD).asText();
|
|
}
|
|
if (jsonNode.has(JIT_PROVISIONING_ENABLED)) {
|
|
jitProvisioningEnabled = jsonNode.get(JIT_PROVISIONING_ENABLED).asBoolean();
|
|
}
|
|
if (jsonNode.has(PRE_PROVISIONING_REQUIRED)) {
|
|
preProvisioningRequired = jsonNode.get(PRE_PROVISIONING_REQUIRED).asBoolean();
|
|
}
|
|
if (jsonNode.has(EXTRACT_GROUPS_ENABLED)) {
|
|
extractGroupsEnabled = jsonNode.get(EXTRACT_GROUPS_ENABLED).asBoolean();
|
|
}
|
|
if (jsonNode.has(GROUPS_CLAIM)) {
|
|
groupsClaimName = jsonNode.get(GROUPS_CLAIM).asText();
|
|
}
|
|
if (jsonNode.has(RESPONSE_TYPE)) {
|
|
responseType = Optional.of(jsonNode.get(RESPONSE_TYPE).asText());
|
|
}
|
|
if (jsonNode.has(RESPONSE_MODE)) {
|
|
responseMode = Optional.of(jsonNode.get(RESPONSE_MODE).asText());
|
|
}
|
|
if (jsonNode.has(USE_NONCE)) {
|
|
useNonce = Optional.of(jsonNode.get(USE_NONCE).asBoolean());
|
|
}
|
|
if (jsonNode.has(READ_TIMEOUT)) {
|
|
readTimeout = jsonNode.get(READ_TIMEOUT).asText();
|
|
}
|
|
if (jsonNode.has(CONNECT_TIMEOUT)) {
|
|
connectTimeout = jsonNode.get(CONNECT_TIMEOUT).asText();
|
|
}
|
|
if (jsonNode.has(EXTRACT_JWT_ACCESS_TOKEN_CLAIMS)) {
|
|
extractJwtAccessTokenClaims =
|
|
Optional.of(jsonNode.get(EXTRACT_JWT_ACCESS_TOKEN_CLAIMS).asBoolean());
|
|
}
|
|
if (jsonNode.has(PREFERRED_JWS_ALGORITHM)) {
|
|
preferredJwsAlgorithm = Optional.of(jsonNode.get(PREFERRED_JWS_ALGORITHM).asText());
|
|
} else {
|
|
preferredJwsAlgorithm =
|
|
Optional.ofNullable(getOptional(configs, OIDC_PREFERRED_JWS_ALGORITHM, null));
|
|
}
|
|
|
|
grantType = Optional.ofNullable(getOptional(configs, OIDC_GRANT_TYPE, null));
|
|
acrValues = Optional.ofNullable(getOptional(configs, OIDC_ACR_VALUES, null));
|
|
|
|
return this;
|
|
}
|
|
|
|
public OidcConfigs build() {
|
|
Objects.requireNonNull(oidcEnabled, "oidcEnabled is required");
|
|
Objects.requireNonNull(clientId, "clientId is required");
|
|
Objects.requireNonNull(clientSecret, "clientSecret is required");
|
|
Objects.requireNonNull(discoveryUri, "discoveryUri is required");
|
|
Objects.requireNonNull(authBaseUrl, "authBaseUrl is required");
|
|
|
|
return new OidcConfigs(this);
|
|
}
|
|
}
|
|
}
|