diff --git a/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java b/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java index 7bb5382..cf7d6c8 100644 --- a/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java +++ b/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java @@ -114,6 +114,12 @@ List search(@QueryParam("emailVerified") Boolean emailVerifi @Consumes(MediaType.APPLICATION_JSON) List searchByAttributes(@QueryParam("q") String searchQuery); + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + List searchByAttributes(@QueryParam("q") String searchQuery, + @QueryParam("exact") Boolean exact); + @GET @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) diff --git a/authz-client/pom.xml b/authz-client/pom.xml index c38c107..6874cb3 100644 --- a/authz-client/pom.xml +++ b/authz-client/pom.xml @@ -101,9 +101,20 @@ ${project.build.directory}/unpacked org/**/*, - META-INF/services/* + + org.keycloak + keycloak-authz-client-tests + ${keycloak.version} + jar + sources + true + ${project.build.directory}/unpacked-resources + + META-INF/services/**/* + + false true diff --git a/authz-client/src/main/java/org/keycloak/authorization/client/AuthzClient.java b/authz-client/src/main/java/org/keycloak/authorization/client/AuthzClient.java index f3768ed..d20c227 100644 --- a/authz-client/src/main/java/org/keycloak/authorization/client/AuthzClient.java +++ b/authz-client/src/main/java/org/keycloak/authorization/client/AuthzClient.java @@ -30,6 +30,7 @@ import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.authorization.client.util.Http; import org.keycloak.authorization.client.util.TokenCallable; +import org.keycloak.common.crypto.CryptoIntegration; import org.keycloak.common.util.KeycloakUriBuilder; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.util.SystemPropertiesJsonParserFactory; @@ -91,6 +92,7 @@ public static AuthzClient create(InputStream configStream) throws RuntimeExcepti * @return a new instance */ public static AuthzClient create(Configuration configuration) { + CryptoIntegration.init(AuthzClient.class.getClassLoader()); return new AuthzClient(configuration); } diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Decoder.java b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Decoder.java similarity index 87% rename from testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Decoder.java rename to authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Decoder.java index c7f9a15..01ea3bc 100644 --- a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Decoder.java +++ b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Decoder.java @@ -1,20 +1,23 @@ /* * Copyright 2024 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. + * 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 + * 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 + * 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. * - * 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.client.testsuite.authz.util; + +package org.keycloak.authorization.client.util.crypto; import java.io.ByteArrayInputStream; import java.io.EOFException; @@ -197,3 +200,4 @@ int read() { return tmp; } } + diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Encoder.java b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Encoder.java similarity index 74% rename from testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Encoder.java rename to authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Encoder.java index e70b098..2bfda3a 100644 --- a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/ASN1Encoder.java +++ b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/ASN1Encoder.java @@ -1,20 +1,23 @@ /* * Copyright 2024 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. + * 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 + * 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 + * 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. * - * 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.client.testsuite.authz.util; + +package org.keycloak.authorization.client.util.crypto; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -95,3 +98,4 @@ byte[] concatenate(ASN1Encoder... objects) throws IOException { return tmp.toByteArray(); } } + diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/DummyCryptoProvider.java b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/AuthzClientCryptoProvider.java similarity index 89% rename from testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/DummyCryptoProvider.java rename to authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/AuthzClientCryptoProvider.java index 8e02c85..90c9c81 100644 --- a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/util/DummyCryptoProvider.java +++ b/authz-client/src/main/java/org/keycloak/authorization/client/util/crypto/AuthzClientCryptoProvider.java @@ -1,20 +1,23 @@ /* * Copyright 2024 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. + * 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 + * 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 + * 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. * - * 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.client.testsuite.authz.util; + +package org.keycloak.authorization.client.util.crypto; import java.io.IOException; import java.math.BigInteger; @@ -48,11 +51,11 @@ import org.keycloak.common.util.KeystoreUtil; /** - *

Dummy crypto provider to be used with the authz-client.

+ *

Simple crypto provider to be used with the authz-client.

* * @author rmartinc */ -public class DummyCryptoProvider implements CryptoProvider { +public class AuthzClientCryptoProvider implements CryptoProvider { @Override public Provider getBouncyCastleProvider() { @@ -63,6 +66,11 @@ public Provider getBouncyCastleProvider() { } } + @Override + public int order() { + return 100; + } + @Override public T getAlgorithmProvider(Class clazz, String algorithm) { throw new UnsupportedOperationException("Not supported yet."); @@ -215,4 +223,4 @@ public Signature getSignature(String sigAlgName) throws NoSuchAlgorithmException public SSLSocketFactory wrapFactoryForTruststore(SSLSocketFactory delegate) { throw new UnsupportedOperationException("Not supported yet."); } -} \ No newline at end of file +} diff --git a/authz-client/src/main/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider b/authz-client/src/main/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider new file mode 100644 index 0000000..41f9972 --- /dev/null +++ b/authz-client/src/main/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider @@ -0,0 +1,20 @@ +# +# Copyright 2024 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.authorization.client.util.crypto.AuthzClientCryptoProvider diff --git a/client-common-synced/src/main/java/org/keycloak/OAuth2Constants.java b/client-common-synced/src/main/java/org/keycloak/OAuth2Constants.java index b03dd25..389aab1 100755 --- a/client-common-synced/src/main/java/org/keycloak/OAuth2Constants.java +++ b/client-common-synced/src/main/java/org/keycloak/OAuth2Constants.java @@ -93,6 +93,7 @@ public interface OAuth2Constants { String SCOPE_PHONE = "phone"; String ORGANIZATION = "organization"; + String ORGANIZATION_ID = "id"; String UI_LOCALES_PARAM = "ui_locales"; diff --git a/client-common-synced/src/main/java/org/keycloak/common/Profile.java b/client-common-synced/src/main/java/org/keycloak/common/Profile.java index f725f1f..a4c9095 100755 --- a/client-common-synced/src/main/java/org/keycloak/common/Profile.java +++ b/client-common-synced/src/main/java/org/keycloak/common/Profile.java @@ -51,17 +51,17 @@ public enum Feature { ACCOUNT_API("Account Management REST API", Type.DEFAULT), - ACCOUNT3("Account Console version 3", Type.DEFAULT, Feature.ACCOUNT_API), + ACCOUNT_V3("Account Console version 3", Type.DEFAULT, 3, Feature.ACCOUNT_API), ADMIN_FINE_GRAINED_AUTHZ("Fine-Grained Admin Permissions", Type.PREVIEW), ADMIN_API("Admin API", Type.DEFAULT), - ADMIN2("New Admin Console", Type.DEFAULT, Feature.ADMIN_API), + ADMIN_V2("New Admin Console", Type.DEFAULT, 2, Feature.ADMIN_API), - LOGIN2("New Login Theme", Type.DEFAULT), + LOGIN_V2("New Login Theme", Type.DEFAULT, 2), - LOGIN1("Legacy Login Theme", Type.DEPRECATED), + LOGIN_V1("Legacy Login Theme", Type.DEPRECATED, 1), DOCKER("Docker Registry protocol", Type.DISABLED_BY_DEFAULT), @@ -92,8 +92,6 @@ public enum Feature { UPDATE_EMAIL("Update Email Action", Type.PREVIEW), - JS_ADAPTER("Host keycloak.js and keycloak-authz.js through the Keycloak server", Type.DEFAULT), - FIPS("FIPS 140-2 mode", Type.DISABLED_BY_DEFAULT), DPOP("OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer", Type.PREVIEW), diff --git a/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoIntegration.java b/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoIntegration.java index 404cf01..c12ea3e 100644 --- a/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoIntegration.java +++ b/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoIntegration.java @@ -3,6 +3,7 @@ import java.security.KeyStore; import java.security.Provider; import java.security.Security; +import java.util.Comparator; import java.util.List; import java.util.ServiceLoader; import java.util.stream.Collectors; @@ -53,15 +54,20 @@ public static CryptoProvider getProvider() { // Try to auto-detect provider private static CryptoProvider detectProvider(ClassLoader classLoader) { List foundProviders = StreamSupport.stream(ServiceLoader.load(CryptoProvider.class, classLoader).spliterator(), false) + .sorted(Comparator.comparingInt(CryptoProvider::order).reversed()) .collect(Collectors.toList()); if (foundProviders.isEmpty()) { throw new IllegalStateException("Not able to load any cryptoProvider with the classLoader: " + classLoader); - } else if (foundProviders.size() > 1) { - throw new IllegalStateException("Multiple crypto providers loaded with the classLoader: " + classLoader + - ". Make sure only one cryptoProvider available on the classpath. Available providers: " +foundProviders); } else { logger.debugf("Detected crypto provider: %s", foundProviders.get(0).getClass().getName()); + if (foundProviders.size() > 1) { + StringBuilder builder = new StringBuilder("Ignored crypto providers: "); + for (int i = 1 ; i < foundProviders.size() ; i++) { + builder.append(foundProviders.get(i).getClass().getName() + ", "); + } + logger.debugf(builder.toString()); + } return foundProviders.get(0); } } diff --git a/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoProvider.java b/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoProvider.java index 0b2448f..283836c 100644 --- a/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoProvider.java +++ b/client-common-synced/src/main/java/org/keycloak/common/crypto/CryptoProvider.java @@ -36,6 +36,13 @@ public interface CryptoProvider { */ Provider getBouncyCastleProvider(); + /** + * Order of this provider. This allows to specify which CryptoProvider will have preference in case that more of them are on the classpath. + * + * The higher number has preference over the lower number + */ + int order(); + /** * Get some algorithm provider implementation. Returned implementation can be dependent according to if we have * non-fips bouncycastle or fips bouncycastle on the classpath. @@ -84,7 +91,7 @@ public interface CryptoProvider { KeyFactory getKeyFactory(String algorithm) throws NoSuchAlgorithmException, NoSuchProviderException; Cipher getAesCbcCipher() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException; - + Cipher getAesGcmCipher() throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException; SecretKeyFactory getSecretKeyFact(String keyAlgorithm) throws NoSuchAlgorithmException, NoSuchProviderException; diff --git a/client-common-synced/src/main/java/org/keycloak/common/util/ConcurrentMultivaluedHashMap.java b/client-common-synced/src/main/java/org/keycloak/common/util/ConcurrentMultivaluedHashMap.java index 125e51a..703ef91 100755 --- a/client-common-synced/src/main/java/org/keycloak/common/util/ConcurrentMultivaluedHashMap.java +++ b/client-common-synced/src/main/java/org/keycloak/common/util/ConcurrentMultivaluedHashMap.java @@ -18,6 +18,7 @@ package org.keycloak.common.util; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -28,6 +29,15 @@ @SuppressWarnings("serial") public class ConcurrentMultivaluedHashMap extends ConcurrentHashMap> implements MultivaluedMap { + public ConcurrentMultivaluedHashMap() { + } + + public ConcurrentMultivaluedHashMap(Map> map) { + if (map == null) { + throw new IllegalArgumentException("Map can not be null"); + } + putAll(map); + } @Override public List createListInstance() { diff --git a/client-common-synced/src/main/java/org/keycloak/jose/jwk/JWKParser.java b/client-common-synced/src/main/java/org/keycloak/jose/jwk/JWKParser.java index e57d0ef..10fe8f4 100755 --- a/client-common-synced/src/main/java/org/keycloak/jose/jwk/JWKParser.java +++ b/client-common-synced/src/main/java/org/keycloak/jose/jwk/JWKParser.java @@ -27,14 +27,14 @@ public class JWKParser extends AbstractJWKParser { private JWKParser() { } - public JWKParser(JWK jwk) { - this.jwk = jwk; - } - public static JWKParser create() { return new JWKParser(); } + public JWKParser(JWK jwk) { + this.jwk = jwk; + } + public static JWKParser create(JWK jwk) { return new JWKParser(jwk); } diff --git a/client-common-synced/src/main/java/org/keycloak/representations/idm/OrganizationRepresentation.java b/client-common-synced/src/main/java/org/keycloak/representations/idm/OrganizationRepresentation.java index 5d0cf29..0c22cd5 100644 --- a/client-common-synced/src/main/java/org/keycloak/representations/idm/OrganizationRepresentation.java +++ b/client-common-synced/src/main/java/org/keycloak/representations/idm/OrganizationRepresentation.java @@ -32,6 +32,7 @@ public class OrganizationRepresentation { private String alias; private boolean enabled = true; private String description; + private String redirectUrl; private Map> attributes; private Set domains; private List members; @@ -77,6 +78,14 @@ public void setDescription(String description) { this.description = description; } + public String getRedirectUrl() { + return redirectUrl; + } + + public void setRedirectUrl(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + public Map> getAttributes() { return attributes; } diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/AuthzClientCredentialsTest.java b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/AuthzClientCredentialsTest.java index 50cbf16..e8bd745 100644 --- a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/AuthzClientCredentialsTest.java +++ b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/AuthzClientCredentialsTest.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.keycloak.admin.client.resource.AuthorizationResource; @@ -31,7 +30,6 @@ import org.keycloak.authorization.client.AuthzClient; import org.keycloak.authorization.client.resource.ProtectionResource; import org.keycloak.authorization.client.util.HttpResponseException; -import org.keycloak.common.crypto.CryptoIntegration; import org.keycloak.common.util.Time; import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessToken; @@ -85,11 +83,6 @@ public List getRealmsForImport() { return testRealms; } - @BeforeAll - public static void initDummyCryptoProvider() { - CryptoIntegration.init(AuthzClientCredentialsTest.class.getClassLoader()); - } - @BeforeEach public void beforeAbstractKeycloakTest() throws Exception { getRealmsForImport().forEach(realmRepresentation -> { diff --git a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/ECDSAAlgorithmTest.java b/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/ECDSAAlgorithmTest.java deleted file mode 100644 index 02ab61e..0000000 --- a/testsuite/authz-tests/src/test/java/org/keycloak/client/testsuite/authz/ECDSAAlgorithmTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2024 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.client.testsuite.authz; - -import java.nio.charset.StandardCharsets; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import org.junit.jupiter.api.Test; -import java.security.Signature; -import org.junit.jupiter.api.Assertions; -import org.keycloak.client.testsuite.authz.util.DummyCryptoProvider; -import org.keycloak.crypto.ECDSAAlgorithm; -import org.keycloak.crypto.JavaAlgorithm; - -/** - * - * @author rmartinc - */ -public class ECDSAAlgorithmTest { - - private final KeyPair keyPair; - - public ECDSAAlgorithmTest() throws Exception { - keyPair = KeyPairGenerator.getInstance("EC").genKeyPair(); - } - - - private void test(ECDSAAlgorithm algorithm) throws Exception { - DummyCryptoProvider prov = new DummyCryptoProvider(); - byte[] data = "Something to sign".getBytes(StandardCharsets.UTF_8); - Signature signature = Signature.getInstance(JavaAlgorithm.getJavaAlgorithm(algorithm.name())); - signature.initSign(keyPair.getPrivate()); - signature.update(data); - byte[] sign = signature.sign(); - byte[] rsConcat = prov.getEcdsaCryptoProvider().asn1derToConcatenatedRS(sign, algorithm.getSignatureLength()); - byte[] asn1Des = prov.getEcdsaCryptoProvider().concatenatedRSToASN1DER(rsConcat, algorithm.getSignatureLength()); - byte[] rsConcat2 = prov.getEcdsaCryptoProvider().asn1derToConcatenatedRS(asn1Des, algorithm.getSignatureLength()); - Assertions.assertArrayEquals(rsConcat, rsConcat2); - } - - @Test - public void testES256() throws Exception { - test(ECDSAAlgorithm.ES256); - } - - @Test - public void testES384() throws Exception { - test(ECDSAAlgorithm.ES384); - } - - @Test - public void testES512() throws Exception { - test(ECDSAAlgorithm.ES512); - } -} diff --git a/testsuite/authz-tests/src/test/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider b/testsuite/authz-tests/src/test/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider deleted file mode 100644 index 60eb59d..0000000 --- a/testsuite/authz-tests/src/test/resources/META-INF/services/org.keycloak.common.crypto.CryptoProvider +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright 2024 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.client.testsuite.authz.util.DummyCryptoProvider