keycloak-uncached
Changes
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/hok/HoKTest.java 6(+3 -3)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/AbstractOIDCResponseTypeTest.java 18(+14 -4)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTest.java 6(+3 -3)
Details
diff --git a/core/src/main/java/org/keycloak/crypto/AsymmetricSignatureSignerContext.java b/core/src/main/java/org/keycloak/crypto/AsymmetricSignatureSignerContext.java
index 7956fa9..0eae6ec 100644
--- a/core/src/main/java/org/keycloak/crypto/AsymmetricSignatureSignerContext.java
+++ b/core/src/main/java/org/keycloak/crypto/AsymmetricSignatureSignerContext.java
@@ -38,6 +38,11 @@ public class AsymmetricSignatureSignerContext implements SignatureSignerContext
}
@Override
+ public String getHashAlgorithm() {
+ return JavaAlgorithm.getJavaAlgorithmForHash(key.getAlgorithm());
+ }
+
+ @Override
public byte[] sign(byte[] data) throws SignatureException {
try {
Signature signature = Signature.getInstance(JavaAlgorithm.getJavaAlgorithm(key.getAlgorithm()));
diff --git a/core/src/main/java/org/keycloak/crypto/HashException.java b/core/src/main/java/org/keycloak/crypto/HashException.java
new file mode 100644
index 0000000..a858cc6
--- /dev/null
+++ b/core/src/main/java/org/keycloak/crypto/HashException.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HashException extends RuntimeException {
+
+ public HashException(String message) {
+ super(message);
+ }
+
+ public HashException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/src/main/java/org/keycloak/crypto/JavaAlgorithm.java b/core/src/main/java/org/keycloak/crypto/JavaAlgorithm.java
index 7ffc78c..8d5ad0a 100644
--- a/core/src/main/java/org/keycloak/crypto/JavaAlgorithm.java
+++ b/core/src/main/java/org/keycloak/crypto/JavaAlgorithm.java
@@ -29,6 +29,10 @@ public class JavaAlgorithm {
public static final String ES512 = "SHA512withECDSA";
public static final String AES = "AES";
+ public static final String SHA256 = "SHA-256";
+ public static final String SHA384 = "SHA-384";
+ public static final String SHA512 = "SHA-512";
+
public static String getJavaAlgorithm(String algorithm) {
switch (algorithm) {
case Algorithm.RS256:
@@ -56,4 +60,32 @@ public class JavaAlgorithm {
}
}
+
+ public static String getJavaAlgorithmForHash(String algorithm) {
+ switch (algorithm) {
+ case Algorithm.RS256:
+ return SHA256;
+ case Algorithm.RS384:
+ return SHA384;
+ case Algorithm.RS512:
+ return SHA512;
+ case Algorithm.HS256:
+ return SHA256;
+ case Algorithm.HS384:
+ return SHA384;
+ case Algorithm.HS512:
+ return SHA512;
+ case Algorithm.ES256:
+ return SHA256;
+ case Algorithm.ES384:
+ return SHA384;
+ case Algorithm.ES512:
+ return SHA512;
+ case Algorithm.AES:
+ return AES;
+ default:
+ throw new IllegalArgumentException("Unknown algorithm " + algorithm);
+ }
+ }
+
}
diff --git a/core/src/main/java/org/keycloak/crypto/MacSignatureSignerContext.java b/core/src/main/java/org/keycloak/crypto/MacSignatureSignerContext.java
index 8656f89..873e821 100644
--- a/core/src/main/java/org/keycloak/crypto/MacSignatureSignerContext.java
+++ b/core/src/main/java/org/keycloak/crypto/MacSignatureSignerContext.java
@@ -37,6 +37,11 @@ public class MacSignatureSignerContext implements SignatureSignerContext {
}
@Override
+ public String getHashAlgorithm() {
+ return JavaAlgorithm.getJavaAlgorithmForHash(key.getAlgorithm());
+ }
+
+ @Override
public byte[] sign(byte[] data) throws SignatureException {
try {
Mac mac = Mac.getInstance(JavaAlgorithm.getJavaAlgorithm(key.getAlgorithm()));
diff --git a/core/src/main/java/org/keycloak/crypto/SignatureSignerContext.java b/core/src/main/java/org/keycloak/crypto/SignatureSignerContext.java
index e09b730..104e0d8 100644
--- a/core/src/main/java/org/keycloak/crypto/SignatureSignerContext.java
+++ b/core/src/main/java/org/keycloak/crypto/SignatureSignerContext.java
@@ -22,6 +22,8 @@ public interface SignatureSignerContext {
String getAlgorithm();
+ String getHashAlgorithm();
+
byte[] sign(byte[] data) throws SignatureException;
}
diff --git a/core/src/test/java/org/keycloak/AtHashTest.java b/core/src/test/java/org/keycloak/AtHashTest.java
index 1d3cc54..0b4fc83 100644
--- a/core/src/test/java/org/keycloak/AtHashTest.java
+++ b/core/src/test/java/org/keycloak/AtHashTest.java
@@ -20,8 +20,8 @@ package org.keycloak;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.jose.jws.Algorithm;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.crypto.Algorithm;
+import org.keycloak.jose.jws.crypto.HashUtils;
import java.security.Security;
@@ -37,13 +37,19 @@ public class AtHashTest {
}
@Test
- public void testAtHash() throws Exception {
- verifyHash("jHkWEdUXMU1BwAsC4vtUsZwnNvTIxEl0z9K3vx5KF0Y", "77QmUPtjPfzWtF2AnpK9RQ");
- verifyHash("ya29.eQETFbFOkAs8nWHcmYXKwEi0Zz46NfsrUU_KuQLOLTwWS40y6Fb99aVzEXC0U14m61lcPMIr1hEIBA", "aUAkJG-u6x4RTWuILWy-CA");
+ public void testAtHashRsa() throws Exception {
+ verifyHash(Algorithm.RS256,"jHkWEdUXMU1BwAsC4vtUsZwnNvTIxEl0z9K3vx5KF0Y", "77QmUPtjPfzWtF2AnpK9RQ");
+ verifyHash(Algorithm.RS256,"ya29.eQETFbFOkAs8nWHcmYXKwEi0Zz46NfsrUU_KuQLOLTwWS40y6Fb99aVzEXC0U14m61lcPMIr1hEIBA", "aUAkJG-u6x4RTWuILWy-CA");
}
- private void verifyHash(String accessToken, String expectedAtHash) {
- String atHash = HashProvider.oidcHash(Algorithm.RS256, accessToken);
+ @Test
+ public void testAtHashEs() throws Exception {
+ verifyHash(Algorithm.ES256,"jHkWEdUXMU1BwAsC4vtUsZwnNvTIxEl0z9K3vx5KF0Y", "77QmUPtjPfzWtF2AnpK9RQ");
+ verifyHash(Algorithm.ES256,"ya29.eQETFbFOkAs8nWHcmYXKwEi0Zz46NfsrUU_KuQLOLTwWS40y6Fb99aVzEXC0U14m61lcPMIr1hEIBA", "aUAkJG-u6x4RTWuILWy-CA");
+ }
+
+ private void verifyHash(String jwtAlgorithm, String accessToken, String expectedAtHash) {
+ String atHash = HashUtils.oidcHash(jwtAlgorithm, accessToken);
Assert.assertEquals(expectedAtHash, atHash);
}
}
diff --git a/server-spi-private/src/main/java/org/keycloak/crypto/HashProvider.java b/server-spi-private/src/main/java/org/keycloak/crypto/HashProvider.java
new file mode 100644
index 0000000..d320195
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/crypto/HashProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import java.io.UnsupportedEncodingException;
+
+import org.keycloak.provider.Provider;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface HashProvider extends Provider {
+
+
+ default byte[] hash(String input) throws HashException {
+ try {
+ byte[] inputBytes = input.getBytes("UTF-8");
+ return hash(inputBytes);
+ } catch (UnsupportedEncodingException e) {
+ throw new HashException("Unsupported encoding when trying to hash", e);
+ }
+ }
+
+
+ byte[] hash(byte[] input) throws HashException;
+
+
+ @Override
+ default void close() {
+ }
+
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/crypto/HashProviderFactory.java b/server-spi-private/src/main/java/org/keycloak/crypto/HashProviderFactory.java
new file mode 100644
index 0000000..c13d5b7
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/crypto/HashProviderFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.Config;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ProviderFactory;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public interface HashProviderFactory extends ProviderFactory<HashProvider> {
+
+ @Override
+ default void init(Config.Scope config) {
+ }
+
+ @Override
+ default void postInit(KeycloakSessionFactory factory) {
+ }
+
+ @Override
+ default void close() {
+ }
+}
diff --git a/server-spi-private/src/main/java/org/keycloak/crypto/HashSpi.java b/server-spi-private/src/main/java/org/keycloak/crypto/HashSpi.java
new file mode 100644
index 0000000..f08ea20
--- /dev/null
+++ b/server-spi-private/src/main/java/org/keycloak/crypto/HashSpi.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.provider.Provider;
+import org.keycloak.provider.ProviderFactory;
+import org.keycloak.provider.Spi;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class HashSpi implements Spi {
+
+ @Override
+ public boolean isInternal() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return "hash";
+ }
+
+ @Override
+ public Class<? extends Provider> getProviderClass() {
+ return HashProvider.class;
+ }
+
+ @Override
+ public Class<? extends ProviderFactory> getProviderFactoryClass() {
+ return HashProviderFactory.class;
+ }
+}
diff --git a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 560d15a..bb4c6c3 100755
--- a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -73,4 +73,5 @@ org.keycloak.keys.PublicKeyStorageSpi
org.keycloak.keys.KeySpi
org.keycloak.storage.client.ClientStorageProviderSpi
org.keycloak.crypto.SignatureSpi
-org.keycloak.crypto.ClientSignatureVerifierSpi
\ No newline at end of file
+org.keycloak.crypto.ClientSignatureVerifierSpi
+org.keycloak.crypto.HashSpi
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/crypto/JavaAlgorithmHashProvider.java b/services/src/main/java/org/keycloak/crypto/JavaAlgorithmHashProvider.java
new file mode 100644
index 0000000..d82f197
--- /dev/null
+++ b/services/src/main/java/org/keycloak/crypto/JavaAlgorithmHashProvider.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.jose.jws.crypto.HashUtils;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class JavaAlgorithmHashProvider implements HashProvider {
+
+ private final String javaAlgorithm;
+
+ public JavaAlgorithmHashProvider(String javaAlgorithm) {
+ this.javaAlgorithm = javaAlgorithm;
+ }
+
+ @Override
+ public byte[] hash(byte[] input) throws HashException {
+ return HashUtils.hash(javaAlgorithm, input);
+ }
+}
diff --git a/services/src/main/java/org/keycloak/crypto/SHA256HashProviderFactory.java b/services/src/main/java/org/keycloak/crypto/SHA256HashProviderFactory.java
new file mode 100644
index 0000000..bd20822
--- /dev/null
+++ b/services/src/main/java/org/keycloak/crypto/SHA256HashProviderFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class SHA256HashProviderFactory implements HashProviderFactory {
+
+ public static final String ID = JavaAlgorithm.SHA256;
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public HashProvider create(KeycloakSession session) {
+ return new JavaAlgorithmHashProvider(ID);
+ }
+
+}
diff --git a/services/src/main/java/org/keycloak/crypto/SHA384HashProviderFactory.java b/services/src/main/java/org/keycloak/crypto/SHA384HashProviderFactory.java
new file mode 100644
index 0000000..29c11e5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/crypto/SHA384HashProviderFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class SHA384HashProviderFactory implements HashProviderFactory {
+
+ public static final String ID = JavaAlgorithm.SHA384;
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public HashProvider create(KeycloakSession session) {
+ return new JavaAlgorithmHashProvider(ID);
+ }
+}
diff --git a/services/src/main/java/org/keycloak/crypto/SHA512HashProviderFactory.java b/services/src/main/java/org/keycloak/crypto/SHA512HashProviderFactory.java
new file mode 100644
index 0000000..54c27c5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/crypto/SHA512HashProviderFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 Red Hat, Inc. and/or its affiliates
+ * and other 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.keycloak.crypto;
+
+import org.keycloak.models.KeycloakSession;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class SHA512HashProviderFactory implements HashProviderFactory {
+
+ public static final String ID = JavaAlgorithm.SHA512;
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public HashProvider create(KeycloakSession session) {
+ return new JavaAlgorithmHashProvider(ID);
+ }
+}
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
index 710a1e0..c6a1423 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java
@@ -25,11 +25,13 @@ import org.keycloak.TokenCategory;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Time;
+import org.keycloak.crypto.HashProvider;
+import org.keycloak.crypto.SignatureProvider;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInputException;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.jose.jws.crypto.HashUtils;
import org.keycloak.migration.migrators.MigrationUtils;
import org.keycloak.models.AuthenticatedClientSessionModel;
import org.keycloak.models.ClientModel;
@@ -763,14 +765,14 @@ public class TokenManager {
}
public AccessTokenResponseBuilder generateCodeHash(String code) {
- codeHash = HashProvider.oidcHash(session.tokens().signatureAlgorithm(TokenCategory.ID), code);
+ codeHash = generateOIDCHash(code);
return this;
}
// Financial API - Part 2: Read and Write API Security Profile
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
public AccessTokenResponseBuilder generateStateHash(String state) {
- stateHash = HashProvider.oidcHash(session.tokens().signatureAlgorithm(TokenCategory.ID), state);
+ stateHash = generateOIDCHash(state);
return this;
}
@@ -801,7 +803,7 @@ public class TokenManager {
}
if (generateAccessTokenHash) {
- String atHash = HashProvider.oidcHash(session.tokens().signatureAlgorithm(TokenCategory.ID), res.getToken());
+ String atHash = generateOIDCHash(res.getToken());
idToken.setAccessTokenHash(atHash);
}
if (codeHash != null) {
@@ -838,6 +840,18 @@ public class TokenManager {
return res;
}
+
+ private String generateOIDCHash(String input) {
+ String signatureAlgorithm = session.tokens().signatureAlgorithm(TokenCategory.ID);
+ SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, signatureAlgorithm);
+ String hashAlgorithm = signatureProvider.signer().getHashAlgorithm();
+
+ HashProvider hashProvider = session.getProvider(HashProvider.class, hashAlgorithm);
+ byte[] hash = hashProvider.hash(input);
+
+ return HashUtils.encodeHashToOIDC(hash);
+ }
+
}
public class RefreshResult {
diff --git a/services/src/main/resources/META-INF/services/org.keycloak.crypto.HashProviderFactory b/services/src/main/resources/META-INF/services/org.keycloak.crypto.HashProviderFactory
new file mode 100644
index 0000000..3ac152c
--- /dev/null
+++ b/services/src/main/resources/META-INF/services/org.keycloak.crypto.HashProviderFactory
@@ -0,0 +1,20 @@
+#
+# Copyright 2017 Red Hat, Inc. and/or its affiliates
+# and other 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.
+#
+
+org.keycloak.crypto.SHA256HashProviderFactory
+org.keycloak.crypto.SHA384HashProviderFactory
+org.keycloak.crypto.SHA512HashProviderFactory
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/hok/HoKTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/hok/HoKTest.java
index 8700353..28bf78b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/hok/HoKTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/hok/HoKTest.java
@@ -37,13 +37,13 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.common.util.KeystoreUtil;
+import org.keycloak.crypto.Algorithm;
import org.keycloak.events.Details;
import org.keycloak.events.EventType;
-import org.keycloak.jose.jws.Algorithm;
import org.keycloak.jose.jws.JWSHeader;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.jose.jws.crypto.HashUtils;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.AccessToken;
@@ -579,7 +579,7 @@ public class HoKTest extends AbstractTestRealmKeycloakTest {
// Validate "c_hash"
Assert.assertNull(idToken.getAccessTokenHash());
Assert.assertNotNull(idToken.getCodeHash());
- Assert.assertEquals(idToken.getCodeHash(), HashProvider.oidcHash(Algorithm.RS256, authzResponse.getCode()));
+ Assert.assertEquals(idToken.getCodeHash(), HashUtils.oidcHash(Algorithm.RS256, authzResponse.getCode()));
// IDToken exchanged for the code
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/AbstractOIDCResponseTypeTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/AbstractOIDCResponseTypeTest.java
index e585bf5..df5d887 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/AbstractOIDCResponseTypeTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/AbstractOIDCResponseTypeTest.java
@@ -23,7 +23,6 @@ import org.junit.Test;
import org.keycloak.OAuthErrorException;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
-import org.keycloak.jose.jws.Algorithm;
import org.keycloak.jose.jws.JWSHeader;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.representations.IDToken;
@@ -56,9 +55,6 @@ import static org.junit.Assert.assertNull;
*/
public abstract class AbstractOIDCResponseTypeTest extends AbstractTestRealmKeycloakTest {
- // Harcoded for now
- Algorithm jwsAlgorithm = Algorithm.RS256;
-
@Rule
public AssertEvents events = new AssertEvents(this);
@@ -263,6 +259,20 @@ public abstract class AbstractOIDCResponseTypeTest extends AbstractTestRealmKeyc
TokenSignatureUtil.changeClientIdTokenSignatureProvider(ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app"), "RS256");
}
}
+
+ @Test
+ public void oidcFlow_RealmES256_ClientES384_EffectiveES384() throws Exception {
+ try {
+ setSignatureAlgorithm("ES384");
+ TokenSignatureUtil.changeRealmTokenSignatureProvider(adminClient, "ES256");
+ TokenSignatureUtil.changeClientIdTokenSignatureProvider(ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app"), "ES384");
+ oidcFlow("ES256", "ES384");
+ } finally {
+ setSignatureAlgorithm("RS256");
+ TokenSignatureUtil.changeClientIdTokenSignatureProvider(ApiUtil.findClientByClientId(adminClient.realm("test"), "test-app"), "RS256");
+ }
+ }
+
private String sigAlgName = "RS256";
private void setSignatureAlgorithm(String sigAlgName) {
this.sigAlgName = sigAlgName;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTest.java
index 8049bd6..030d129 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTest.java
@@ -20,7 +20,7 @@ package org.keycloak.testsuite.oidc.flows;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.events.Details;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.jose.jws.crypto.HashUtils;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.EventRepresentation;
@@ -64,14 +64,14 @@ public class OIDCHybridResponseTypeCodeIDTokenTest extends AbstractOIDCResponseT
Assert.assertNull(idToken.getAccessTokenHash());
Assert.assertNotNull(idToken.getCodeHash());
- Assert.assertEquals(idToken.getCodeHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getCode()));
+ Assert.assertEquals(idToken.getCodeHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getCode()));
// Financial API - Part 2: Read and Write API Security Profile
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
// Validate "s_hash"
Assert.assertNotNull(idToken.getStateHash());
- Assert.assertEquals(idToken.getStateHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getState()));
+ Assert.assertEquals(idToken.getStateHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getState()));
// IDToken exchanged for the code
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTokenTest.java
index 33d3ff2..178a32b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCHybridResponseTypeCodeIDTokenTokenTest.java
@@ -20,7 +20,7 @@ package org.keycloak.testsuite.oidc.flows;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.events.Details;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.jose.jws.crypto.HashUtils;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.EventRepresentation;
@@ -63,17 +63,17 @@ public class OIDCHybridResponseTypeCodeIDTokenTokenTest extends AbstractOIDCResp
// Validate "at_hash" and "c_hash"
Assert.assertNotNull(idToken.getAccessTokenHash());
- Assert.assertEquals(idToken.getAccessTokenHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getAccessToken()));
+ Assert.assertEquals(idToken.getAccessTokenHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getAccessToken()));
Assert.assertNotNull(idToken.getCodeHash());
- Assert.assertEquals(idToken.getCodeHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getCode()));
+ Assert.assertEquals(idToken.getCodeHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getCode()));
// Financial API - Part 2: Read and Write API Security Profile
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
// Validate "s_hash"
Assert.assertNotNull(idToken.getStateHash());
- Assert.assertEquals(idToken.getStateHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getState()));
+ Assert.assertEquals(idToken.getStateHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getState()));
// IDToken exchanged for the code
IDToken idToken2 = sendTokenRequestAndGetIDToken(loginEvent);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCImplicitResponseTypeIDTokenTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCImplicitResponseTypeIDTokenTokenTest.java
index d226aef..374724a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCImplicitResponseTypeIDTokenTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oidc/flows/OIDCImplicitResponseTypeIDTokenTokenTest.java
@@ -20,7 +20,7 @@ package org.keycloak.testsuite.oidc.flows;
import org.junit.Before;
import org.junit.Test;
import org.keycloak.events.Details;
-import org.keycloak.jose.jws.crypto.HashProvider;
+import org.keycloak.jose.jws.crypto.HashUtils;
import org.keycloak.protocol.oidc.utils.OIDCResponseType;
import org.keycloak.representations.IDToken;
import org.keycloak.representations.idm.EventRepresentation;
@@ -62,7 +62,7 @@ public class OIDCImplicitResponseTypeIDTokenTokenTest extends AbstractOIDCRespon
// Validate "at_hash"
Assert.assertNotNull(idToken.getAccessTokenHash());
- Assert.assertEquals(idToken.getAccessTokenHash(), HashProvider.oidcHash(getSignatureAlgorithm(), authzResponse.getAccessToken()));
+ Assert.assertEquals(idToken.getAccessTokenHash(), HashUtils.oidcHash(getSignatureAlgorithm(), authzResponse.getAccessToken()));
Assert.assertNull(idToken.getCodeHash());
return Collections.singletonList(idToken);