Skip to content

Commit

Permalink
[ELY-2584] Add the ability to specify that the OIDC Authentication Re…
Browse files Browse the repository at this point in the history
…quest should include request and request_uri parameters
  • Loading branch information
PrarthonaPaul committed Sep 28, 2023
1 parent ab0080b commit 3ce624a
Show file tree
Hide file tree
Showing 11 changed files with 851 additions and 24 deletions.
11 changes: 11 additions & 0 deletions http/oidc/pom.xml
Expand Up @@ -128,6 +128,12 @@
<artifactId>keycloak-admin-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>3.1.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
Expand Down Expand Up @@ -173,6 +179,11 @@
<artifactId>jmockit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wildfly.security</groupId>
<artifactId>wildfly-elytron-credential-source-impl</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

Expand Down
Expand Up @@ -156,7 +156,7 @@ protected JwtClaims createRequestToken(String clientId, String tokenUrl) {
return jwtClaims;
}

private static KeyPair loadKeyPairFromKeyStore(String keyStoreFile, String storePassword, String keyPassword, String keyAlias, String keyStoreType) {
public static KeyPair loadKeyPairFromKeyStore(String keyStoreFile, String storePassword, String keyPassword, String keyAlias, String keyStoreType) {
InputStream stream = findFile(keyStoreFile);
try {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
Expand Down
40 changes: 40 additions & 0 deletions http/oidc/src/main/java/org/wildfly/security/http/oidc/Oidc.java
Expand Up @@ -52,10 +52,14 @@ public class Oidc {
public static final String TEXT_CONTENT_TYPE = "text/*";
public static final String DISCOVERY_PATH = ".well-known/openid-configuration";
public static final String KEYCLOAK_REALMS_PATH = "realms/";
public static final String KEYSTORE_PASS = "password";
public static final String JKS_KEYSTORE_TYPE = "JKS";
public static final String JSON_CONFIG_CONTEXT_PARAM = "org.wildfly.security.http.oidc.json.config";
static final String ACCOUNT_PATH = "account";
public static final String CLIENTS_MANAGEMENT_REGISTER_NODE_PATH = "clients-managements/register-node";
public static final String CLIENTS_MANAGEMENT_UNREGISTER_NODE_PATH = "clients-managements/unregister-node";
public static final String ADMIN_CONSOLE_PATH = "admin/master/console/#";
public static final String REALM_SETTING_KEYS_PATH = "realm-settings/keys";
public static final String SLASH = "/";
public static final String OIDC_CLIENT_CONTEXT_KEY = OidcClientContext.class.getName();
public static final String CLIENT_ID = "client_id";
Expand All @@ -73,12 +77,17 @@ public class Oidc {
public static final String PARTIAL = "partial/";
public static final String PASSWORD = "password";
public static final String PROMPT = "prompt";
public static final String REQUEST = "request";
public static final String REQUEST_URI = "request_uri";
public static final String SCOPE = "scope";
public static final String UI_LOCALES = "ui_locales";
public static final String USERNAME = "username";
public static final String OIDC_SCOPE = "openid";
public static final String REDIRECT_URI = "redirect_uri";
public static final String REFRESH_TOKEN = "refresh_token";
public static final String REQUEST_TYPE_OAUTH2 = "oauth2";
public static final String REQUEST_TYPE_REQUEST = "request";
public static final String REQUEST_TYPE_REQUEST_URI = "request_uri";
public static final String RESPONSE_TYPE = "response_type";
public static final String SESSION_STATE = "session_state";
public static final String SOAP_ACTION = "SOAPAction";
Expand Down Expand Up @@ -116,6 +125,35 @@ public class Oidc {
public static final String X_REQUESTED_WITH = "X-Requested-With";
public static final String XML_HTTP_REQUEST = "XMLHttpRequest";

/* Accepted Request Object Signing Algorithms for KeyCloak*/
public static final String NONE = "none";
public static final String RS_256 = "RS256";
public static final String HS_256 = "HS256";
public static final String HS_384 = "HS384";
public static final String HS_512 = "HS512";
public static final String ES_256 = "ES256";
public static final String ES_384 = "ES384";
public static final String ES_512 = "ES512";
public static final String ES_256K = "ES256K";
public static final String RS_384 = "RS384";
public static final String RS_512 = "RS512";
public static final String PS_256 = "PS256";
public static final String PS_384 = "PS384";
public static final String PS_512 = "PS512";

/* Accepted Request Object Encrypting Algorithms for KeyCloak*/
public static final String RSA_OAEP = "RSA-OAEP";
public static final String RSA_OAEP_256 = "RSA-OAEP-256";
public static final String RSA1_5 = "RSA1_5";

/* Accepted Request Object Encryption Methods for KeyCloak*/
public static final String A256GCM = "A256GCM";
public static final String A192GCM = "A192GCM";
public static final String A128GCM = "A128GCM";
public static final String A128CBC_HS256 = "A128CBC-HS256";
public static final String A192CBC_HS384 = "A192CBC-HS384";
public static final String A256CBC_HS512 = "A256CBC-HS512";

/**
* Bearer token pattern.
* The Bearer token authorization header is of the form "Bearer", followed by optional whitespace, followed by
Expand Down Expand Up @@ -276,6 +314,8 @@ public static String getJavaAlgorithm(String algorithm) {
return ES384;
case AlgorithmIdentifiers.ECDSA_USING_P521_CURVE_AND_SHA512:
return ES512;
case AlgorithmIdentifiers.NONE:
return NONE;
default:
throw log.unknownAlgorithm(algorithm);
}
Expand Down
Expand Up @@ -30,9 +30,16 @@
import static org.wildfly.security.http.oidc.Oidc.SLASH;
import static org.wildfly.security.http.oidc.Oidc.SSLRequired;
import static org.wildfly.security.http.oidc.Oidc.TokenStore;
import static org.wildfly.security.jose.util.JsonSerialization.readValue;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

Expand All @@ -41,7 +48,7 @@
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.wildfly.security.jose.util.JsonSerialization;
import org.jose4j.jwk.JsonWebKeySet;

/**
* The OpenID Connect (OIDC) configuration for a client application. This class is based on
Expand Down Expand Up @@ -80,7 +87,13 @@ public enum RelativeUrlsUsed {
protected String unregisterNodeUrl;
protected String jwksUrl;
protected String issuerUrl;
protected String authorizationEndpoint;
protected String principalAttribute = "sub";
protected List<String> requestObjectSigningAlgValuesSupported;
protected List<String> requestObjectEncryptionEncValuesSupported;
protected List<String> requestObjectEncryptionAlgValuesSupported;
protected boolean requestParameterSupported;
protected boolean requestUriParameterSupported;

protected String resource;
protected String clientId;
Expand Down Expand Up @@ -126,6 +139,19 @@ public enum RelativeUrlsUsed {
protected boolean verifyTokenAudience = false;

protected String tokenSignatureAlgorithm = DEFAULT_TOKEN_SIGNATURE_ALGORITHM;
protected String authenticationRequestFormat;
protected String requestSignatureAlgorithm;
protected String requestEncryptAlgorithm;
protected String requestEncryptEncValue;
protected String pushedAuthorizationRequestEndpoint;
protected String clientKeyStoreFile;
protected String clientKeyStorePass;
protected String clientKeyPass;
protected String clientKeyAlias;
protected String clientKeystoreType;

protected String realmKey;
protected JsonWebKeySet realmKeySet = new JsonWebKeySet();

public OidcClientConfiguration() {
}
Expand Down Expand Up @@ -223,6 +249,15 @@ protected void resolveUrls() {
tokenUrl = config.getTokenEndpoint();
logoutUrl = config.getLogoutEndpoint();
jwksUrl = config.getJwksUri();
authorizationEndpoint = config.getAuthorizationEndpoint();
requestParameterSupported = config.getRequestParameterSupported();
requestObjectSigningAlgValuesSupported = config.getRequestObjectSigningAlgValuesSupported();
requestObjectEncryptionEncValuesSupported = config.getRequestObjectEncryptionEncValuesSupported();
requestObjectEncryptionAlgValuesSupported = config.getRequestObjectEncryptionAlgValuesSupported();
requestUriParameterSupported = config.getRequestUriParameterSupported();
realmKeySet = createrealmKeySet();
pushedAuthorizationRequestEndpoint = config.getPushedAuthorizationRequestEndpoint();

if (authServerBaseUrl != null) {
// keycloak-specific properties
accountUrl = getUrl(issuerUrl, ACCOUNT_PATH);
Expand All @@ -237,6 +272,26 @@ protected void resolveUrls() {
}
}

private JsonWebKeySet createrealmKeySet() throws Exception{
HttpGet request = new HttpGet(jwksUrl);
request.addHeader(ACCEPT, JSON_CONTENT_TYPE);
HttpResponse response = getClient().execute(request);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
EntityUtils.consumeQuietly(response.getEntity());
throw new Exception(response.getStatusLine().getReasonPhrase());
}
InputStream inputStream = response.getEntity().getContent();
StringBuilder textBuilder = new StringBuilder();
try (Reader reader = new BufferedReader(new InputStreamReader
(inputStream, StandardCharsets.UTF_8))) {
int c = 0;
while ((c = reader.read()) != -1) {
textBuilder.append((char) c);
}
}
return new JsonWebKeySet(textBuilder.toString());
}

protected OidcProviderMetadata getOidcProviderMetadata(String discoveryUrl) throws Exception {
HttpGet request = new HttpGet(discoveryUrl);
request.addHeader(ACCEPT, JSON_CONTENT_TYPE);
Expand All @@ -246,7 +301,7 @@ protected OidcProviderMetadata getOidcProviderMetadata(String discoveryUrl) thro
EntityUtils.consumeQuietly(response.getEntity());
throw new Exception(response.getStatusLine().getReasonPhrase());
}
return JsonSerialization.readValue(response.getEntity().getContent(), OidcProviderMetadata.class);
return readValue(response.getEntity().getContent(), OidcProviderMetadata.class);
} finally {
request.releaseConnection();
}
Expand Down Expand Up @@ -329,6 +384,22 @@ public String getIssuerUrl() {
return issuerUrl;
}

public List<String> getRequestObjectSigningAlgValuesSupported() {
return requestObjectSigningAlgValuesSupported;
}

public boolean getRequestParameterSupported() {
return requestParameterSupported;
}

public boolean getRequestUriParameterSupported() {
return requestUriParameterSupported;
}

public String getAuthorizationEndpoint() {
return authorizationEndpoint;
}

public void setResource(String resource) {
this.resource = resource;
}
Expand Down Expand Up @@ -651,4 +722,99 @@ public String getTokenSignatureAlgorithm() {
return tokenSignatureAlgorithm;
}

public String getAuthenticationRequestFormat() {
return authenticationRequestFormat;
}

public void setAuthenticationRequestFormat(String requestObjectType ) {
this.authenticationRequestFormat = requestObjectType;
}

public String getRequestSignatureAlgorithm() {
return requestSignatureAlgorithm;
}

public void setRequestSignatureAlgorithm(String algorithm) {
this.requestSignatureAlgorithm = algorithm;
}

public String getRequestEncryptAlgorithm() {
return requestEncryptAlgorithm;
}

public void setRequestEncryptAlgorithm(String algorithm) {
this.requestEncryptAlgorithm = algorithm;
}

public String getRequestEncryptEncValue() {
return requestEncryptEncValue;
}

public void setRequestEncryptEncValue (String enc) {
this.requestEncryptEncValue = enc;
}

public String getRealmKey () {
return realmKey;
}

public void setRealmKey(String key) {
this.realmKey = key;
}

public String getClientKeyStore () {
return clientKeyStoreFile;
}

public void setClientKeyStore(String keyStoreFile) {
this.clientKeyStoreFile = keyStoreFile;
}

public String getClientKeyStorePassword () {
return clientKeyStorePass;
}

public void setClientKeyStorePassword(String pass) {
this.clientKeyStorePass = pass;
}

public String getClientKeyPassword () {
return clientKeyPass;
}

public void setClientKeyPassword(String pass) {
this.clientKeyPass = pass;
}

public String getClientKeystoreType() {
return clientKeystoreType;
}

public void setClientKeystoreType(String type) {
this.clientKeystoreType = type;
}

public String getClientKeyAlias() {
return clientKeyAlias;
}

public void setClientKeyAlias(String alias) {
this.clientKeyAlias = alias;
}

public JsonWebKeySet getrealmKeySet() {
return realmKeySet;
}

public void setrealmKeySet(JsonWebKeySet keySet) {
this.realmKeySet = keySet;
}

public String getPushedAuthorizationRequestEndpoint() {
return pushedAuthorizationRequestEndpoint;
}

public void setPushedAuthorizationRequestEndpoint(String url) {
this.pushedAuthorizationRequestEndpoint = url;
}
}
Expand Up @@ -19,6 +19,8 @@
package org.wildfly.security.http.oidc;

import static org.wildfly.security.http.oidc.ElytronMessages.log;
import static org.wildfly.security.http.oidc.Oidc.NONE;
import static org.wildfly.security.http.oidc.Oidc.REQUEST_TYPE_OAUTH2;
import static org.wildfly.security.http.oidc.Oidc.SSLRequired;
import static org.wildfly.security.http.oidc.Oidc.TokenStore;

Expand Down Expand Up @@ -100,6 +102,30 @@ protected OidcClientConfiguration internalBuild(final OidcJsonConfiguration oidc
if (oidcJsonConfiguration.getTokenCookiePath() != null) {
oidcClientConfiguration.setOidcStateCookiePath(oidcJsonConfiguration.getTokenCookiePath());
}
if (oidcJsonConfiguration.getAuthenticationRequestFormat() != null) {
oidcClientConfiguration.setAuthenticationRequestFormat(oidcJsonConfiguration.getAuthenticationRequestFormat());
} else {
oidcClientConfiguration.setAuthenticationRequestFormat(REQUEST_TYPE_OAUTH2);
}
if (oidcJsonConfiguration.getRequestSignatureAlgorithm() != null) {
oidcClientConfiguration.setRequestSignatureAlgorithm(oidcJsonConfiguration.getRequestSignatureAlgorithm());
} else {
oidcClientConfiguration.setRequestSignatureAlgorithm(NONE);
}
if (oidcJsonConfiguration.getRequestEncryptAlgorithm() != null && oidcJsonConfiguration.getRequestEncryptEncValue() != null) { //both are required to encrypt the request object
oidcClientConfiguration.setRequestEncryptAlgorithm(oidcJsonConfiguration.getRequestEncryptAlgorithm());
oidcClientConfiguration.setRequestEncryptEncValue(oidcJsonConfiguration.getRequestEncryptEncValue());
}
if (oidcJsonConfiguration.getClientKeystore() != null && oidcJsonConfiguration.getClientKeystorePassword() != null &&
oidcJsonConfiguration.getClientKeyPassword() != null && oidcJsonConfiguration.getClientKeyAlias() != null) {
oidcClientConfiguration.setClientKeyStore(oidcJsonConfiguration.getClientKeystore());
oidcClientConfiguration.setClientKeyStorePassword(oidcJsonConfiguration.getClientKeystorePassword());
oidcClientConfiguration.setClientKeyPassword(oidcJsonConfiguration.getClientKeyPassword());
oidcClientConfiguration.setClientKeyAlias(oidcJsonConfiguration.getClientKeyAlias());
if (oidcJsonConfiguration.getClientKeystoreType() != null) {
oidcClientConfiguration.setClientKeystoreType(oidcJsonConfiguration.getClientKeystoreType());
}
}
if (oidcJsonConfiguration.getPrincipalAttribute() != null) oidcClientConfiguration.setPrincipalAttribute(oidcJsonConfiguration.getPrincipalAttribute());

oidcClientConfiguration.setResourceCredentials(oidcJsonConfiguration.getCredentials());
Expand Down Expand Up @@ -190,7 +216,6 @@ public static OidcJsonConfiguration loadOidcJsonConfiguration(InputStream is) {
return adapterConfig;
}


public static OidcClientConfiguration build(OidcJsonConfiguration oidcJsonConfiguration) {
return new OidcClientConfigurationBuilder().internalBuild(oidcJsonConfiguration);
}
Expand Down

0 comments on commit 3ce624a

Please sign in to comment.