org.wildfly.security.http.oidc.OidcClientConfigurationBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of wildfly-elytron-http-oidc
Show all versions of wildfly-elytron-http-oidc
WildFly Security HTTP OIDC Mechanism Implementation
/*
* JBoss, Home of Professional Open Source.
* Copyright 2020 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.wildfly.security.http.oidc;
import static org.jose4j.jws.AlgorithmIdentifiers.NONE;
import static org.wildfly.security.http.oidc.ElytronMessages.log;
import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.OAUTH2;
import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.REQUEST;
import static org.wildfly.security.http.oidc.Oidc.AuthenticationRequestFormat.REQUEST_URI;
import static org.wildfly.security.http.oidc.Oidc.SSLRequired;
import static org.wildfly.security.http.oidc.Oidc.TokenStore;
import java.io.IOException;
import java.io.InputStream;
import java.security.PublicKey;
import java.util.concurrent.Callable;
import org.apache.http.client.HttpClient;
import org.wildfly.common.iteration.CodePointIterator;
import org.wildfly.security.jose.util.SystemPropertiesJsonParserFactory;
import org.wildfly.security.pem.Pem;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Builder for the OpenID Connect (OIDC) configuration for a client application. This class is based on
* {@code org.keycloak.adapters.KeycloakDeploymentBuilder}.
*
* @author Bill Burke
* @author Brad Culley
* @author John D. Ament
* @author Farah Juma
*/
public class OidcClientConfigurationBuilder {
protected OidcClientConfiguration oidcClientConfiguration = new OidcClientConfiguration();
protected OidcClientConfigurationBuilder() {
}
protected OidcClientConfiguration internalBuild(final OidcJsonConfiguration oidcJsonConfiguration) {
if (oidcJsonConfiguration.getAuthServerUrl() != null && oidcJsonConfiguration.getRealm() == null) {
throw log.keycloakRealmMissing();
}
if (oidcJsonConfiguration.getRealm() != null) {
oidcClientConfiguration.setRealm(oidcJsonConfiguration.getRealm());
}
String resource = oidcJsonConfiguration.getResource();
String clientId = oidcJsonConfiguration.getClientId();
if (resource == null && clientId == null) {
throw log.resourceOrClientIdMustBeSet();
}
oidcClientConfiguration.setResource(resource);
oidcClientConfiguration.setClientId(clientId);
String realmKeyPem = oidcJsonConfiguration.getRealmKey();
if (realmKeyPem != null) {
PublicKey realmKey;
try {
realmKey = Pem.parsePemPublicKey(CodePointIterator.ofString(realmKeyPem));
HardcodedPublicKeyLocator pkLocator = new HardcodedPublicKeyLocator(realmKey);
oidcClientConfiguration.setPublicKeyLocator(pkLocator);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
JWKPublicKeyLocator pkLocator = new JWKPublicKeyLocator();
oidcClientConfiguration.setPublicKeyLocator(pkLocator);
}
if (oidcJsonConfiguration.getSslRequired() != null) {
oidcClientConfiguration.setSSLRequired(SSLRequired.valueOf(oidcJsonConfiguration.getSslRequired().toUpperCase()));
} else {
oidcClientConfiguration.setSSLRequired(SSLRequired.EXTERNAL);
}
if (oidcJsonConfiguration.getConfidentialPort() != -1) {
oidcClientConfiguration.setConfidentialPort(oidcJsonConfiguration.getConfidentialPort());
}
if (oidcJsonConfiguration.getTokenStore() != null) {
oidcClientConfiguration.setTokenStore(TokenStore.valueOf(oidcJsonConfiguration.getTokenStore().toUpperCase()));
} else {
oidcClientConfiguration.setTokenStore(TokenStore.SESSION);
}
if (oidcJsonConfiguration.getTokenCookiePath() != null) {
oidcClientConfiguration.setOidcStateCookiePath(oidcJsonConfiguration.getTokenCookiePath());
}
if (oidcJsonConfiguration.getScope() != null) {
oidcClientConfiguration.setScope(oidcJsonConfiguration.getScope());
}
if (oidcJsonConfiguration.getAuthenticationRequestFormat() != null) {
if (!(oidcJsonConfiguration.getAuthenticationRequestFormat().equals(OAUTH2.getValue()) ||
oidcJsonConfiguration.getAuthenticationRequestFormat().equals(REQUEST.getValue()) ||
oidcJsonConfiguration.getAuthenticationRequestFormat().equals(REQUEST_URI.getValue()))) {
throw log.invalidAuthenticationRequestFormat();
}
oidcClientConfiguration.setAuthenticationRequestFormat(oidcJsonConfiguration.getAuthenticationRequestFormat());
} else {
oidcClientConfiguration.setAuthenticationRequestFormat(OAUTH2.getValue());
}
if (oidcJsonConfiguration.getRequestObjectSigningAlgorithm() != null) {
oidcClientConfiguration.setRequestObjectSigningAlgorithm(oidcJsonConfiguration.getRequestObjectSigningAlgorithm());
} else {
oidcClientConfiguration.setRequestObjectSigningAlgorithm(NONE);
}
if (oidcJsonConfiguration.getRequestObjectEncryptionAlgValue() != null && oidcJsonConfiguration.getRequestObjectEncryptionEncValue() != null) { //both are required to encrypt the request object
oidcClientConfiguration.setRequestObjectEncryptionAlgValue(oidcJsonConfiguration.getRequestObjectEncryptionAlgValue());
oidcClientConfiguration.setRequestObjectEncryptionEncValue(oidcJsonConfiguration.getRequestObjectEncryptionEncValue());
JWKEncPublicKeyLocator encryptionPublicKeyLocator = new JWKEncPublicKeyLocator();
oidcClientConfiguration.setEncryptionPublicKeyLocator(encryptionPublicKeyLocator);
} else if (oidcJsonConfiguration.getRequestObjectEncryptionAlgValue() != null || oidcJsonConfiguration.getRequestObjectEncryptionEncValue() != null) { //if only one is specified, that is not correct
throw log.invalidRequestObjectEncryptionAlgorithmConfiguration();
}
if (oidcJsonConfiguration.getRequestObjectSigningKeyStoreFile() != null
&& oidcJsonConfiguration.getRequestObjectSigningKeyStorePassword() != null
&& oidcJsonConfiguration.getRequestObjectSigningKeyPassword() != null
&& oidcJsonConfiguration.getRequestObjectSigningKeyAlias() != null) {
oidcClientConfiguration.setRequestObjectSigningKeyStoreFile(oidcJsonConfiguration.getRequestObjectSigningKeyStoreFile());
oidcClientConfiguration.setRequestObjectSigningKeyStorePassword(oidcJsonConfiguration.getRequestObjectSigningKeyStorePassword());
oidcClientConfiguration.setRequestObjectSigningKeyPassword(oidcJsonConfiguration.getRequestObjectSigningKeyPassword());
oidcClientConfiguration.setRequestObjectSigningKeyAlias(oidcJsonConfiguration.getRequestObjectSigningKeyAlias());
if (oidcJsonConfiguration.getRequestObjectSigningKeyStoreType() != null) {
oidcClientConfiguration.setRequestObjectSigningKeyStoreType(oidcJsonConfiguration.getRequestObjectSigningKeyStoreType());
}
}
if (oidcJsonConfiguration.getPrincipalAttribute() != null) oidcClientConfiguration.setPrincipalAttribute(oidcJsonConfiguration.getPrincipalAttribute());
oidcClientConfiguration.setResourceCredentials(oidcJsonConfiguration.getCredentials());
oidcClientConfiguration.setClientAuthenticator(ClientCredentialsProviderUtils.bootstrapClientAuthenticator(oidcClientConfiguration));
oidcClientConfiguration.setPublicClient(oidcJsonConfiguration.isPublicClient());
oidcClientConfiguration.setUseResourceRoleMappings(oidcJsonConfiguration.isUseResourceRoleMappings());
oidcClientConfiguration.setUseRealmRoleMappings(oidcJsonConfiguration.isUseRealmRoleMappings());
oidcClientConfiguration.setExposeToken(oidcJsonConfiguration.isExposeToken());
if (oidcJsonConfiguration.isCors()) {
oidcClientConfiguration.setCors(true);
oidcClientConfiguration.setCorsMaxAge(oidcJsonConfiguration.getCorsMaxAge());
oidcClientConfiguration.setCorsAllowedHeaders(oidcJsonConfiguration.getCorsAllowedHeaders());
oidcClientConfiguration.setCorsAllowedMethods(oidcJsonConfiguration.getCorsAllowedMethods());
oidcClientConfiguration.setCorsExposedHeaders(oidcJsonConfiguration.getCorsExposedHeaders());
}
// https://tools.ietf.org/html/rfc7636
if (oidcJsonConfiguration.isPkce()) {
oidcClientConfiguration.setPkce(true);
}
oidcClientConfiguration.setBearerOnly(oidcJsonConfiguration.isBearerOnly());
oidcClientConfiguration.setAutodetectBearerOnly(oidcJsonConfiguration.isAutodetectBearerOnly());
oidcClientConfiguration.setEnableBasicAuth(oidcJsonConfiguration.isEnableBasicAuth());
oidcClientConfiguration.setAlwaysRefreshToken(oidcJsonConfiguration.isAlwaysRefreshToken());
oidcClientConfiguration.setRegisterNodeAtStartup(oidcJsonConfiguration.isRegisterNodeAtStartup());
oidcClientConfiguration.setRegisterNodePeriod(oidcJsonConfiguration.getRegisterNodePeriod());
oidcClientConfiguration.setTokenMinimumTimeToLive(oidcJsonConfiguration.getTokenMinimumTimeToLive());
oidcClientConfiguration.setMinTimeBetweenJwksRequests(oidcJsonConfiguration.getMinTimeBetweenJwksRequests());
oidcClientConfiguration.setPublicKeyCacheTtl(oidcJsonConfiguration.getPublicKeyCacheTtl());
oidcClientConfiguration.setIgnoreOAuthQueryParameter(oidcJsonConfiguration.isIgnoreOAuthQueryParameter());
oidcClientConfiguration.setRewriteRedirectRules(oidcJsonConfiguration.getRedirectRewriteRules());
oidcClientConfiguration.setVerifyTokenAudience(oidcJsonConfiguration.isVerifyTokenAudience());
if (realmKeyPem == null && oidcJsonConfiguration.isBearerOnly()
&& (oidcJsonConfiguration.getAuthServerUrl() == null && oidcJsonConfiguration.getProviderUrl() == null)) {
throw log.invalidConfigurationForBearerAuth();
}
if ((oidcJsonConfiguration.getAuthServerUrl() == null && oidcJsonConfiguration.getProviderUrl() == null) && (!oidcClientConfiguration.isBearerOnly() || realmKeyPem == null)) {
throw log.authServerUrlOrProviderUrlMustBeSet();
}
oidcClientConfiguration.setClient(createHttpClientProducer(oidcJsonConfiguration));
oidcClientConfiguration.setAuthServerBaseUrl(oidcJsonConfiguration);
oidcClientConfiguration.setProviderUrl(oidcJsonConfiguration.getProviderUrl());
if (oidcJsonConfiguration.getTurnOffChangeSessionIdOnLogin() != null) {
oidcClientConfiguration.setTurnOffChangeSessionIdOnLogin(oidcJsonConfiguration.getTurnOffChangeSessionIdOnLogin());
}
oidcClientConfiguration.setTokenSignatureAlgorithm(oidcJsonConfiguration.getTokenSignatureAlgorithm());
return oidcClientConfiguration;
}
private Callable createHttpClientProducer(final OidcJsonConfiguration oidcJsonConfiguration) {
return new Callable() {
private HttpClient client;
@Override
public HttpClient call() {
if (client == null) {
synchronized (oidcClientConfiguration) {
if (client == null) {
client = new HttpClientBuilder().build(oidcJsonConfiguration);
}
}
}
return client;
}
};
}
public static OidcClientConfiguration build(InputStream is) {
OidcJsonConfiguration oidcJsonConfiguration = loadOidcJsonConfiguration(is);
return new OidcClientConfigurationBuilder().internalBuild(oidcJsonConfiguration);
}
public static OidcJsonConfiguration loadOidcJsonConfiguration(InputStream is) {
ObjectMapper mapper = new ObjectMapper(new SystemPropertiesJsonParserFactory());
mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
OidcJsonConfiguration adapterConfig;
try {
adapterConfig = mapper.readValue(is, OidcJsonConfiguration.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
return adapterConfig;
}
public static OidcClientConfiguration build(OidcJsonConfiguration oidcJsonConfiguration) {
return new OidcClientConfigurationBuilder().internalBuild(oidcJsonConfiguration);
}
}