From 8887be7887572d026a8356df6f1c140e6c854477 Mon Sep 17 00:00:00 2001 From: rmartinc Date: Mon, 4 Sep 2023 18:05:35 +0200 Subject: [PATCH] Add a new identity provider for LinkedIn based on OIDC Closes https://github.com/keycloak/keycloak/issues/22383 --- .../java/org/keycloak/util/JWKSUtils.java | 10 +- .../linked-in-add-identity-provider.png | Bin 44775 -> 44687 bytes .../identity-broker/social/linked-in.adoc | 13 +- .../topics/keycloak/changes-22_0_2.adoc | 6 + .../locales/en/identity-providers-help.json | 1 + .../public/locales/en/identity-providers.json | 1 + .../add/ExtendedNonDiscoverySettings.tsx | 1 + js/libs/ui-shared/src/icons/IconMapper.tsx | 1 + .../broker/oidc/OIDCIdentityProvider.java | 22 ++-- .../oidc/OIDCIdentityProviderConfig.java | 12 ++ .../oidc/mappers/UsernameTemplateMapper.java | 2 + .../linkedin/LinkedInIdentityProvider.java | 1 + .../LinkedInIdentityProviderFactory.java | 3 +- .../LinkedInOIDCIdentityProvider.java | 56 +++++++++ .../LinkedInOIDCIdentityProviderFactory.java | 114 ++++++++++++++++++ .../linkedin/LinkedInPublicKeyLoader.java | 51 ++++++++ .../linkedin/LinkedInUserAttributeMapper.java | 2 +- ...roker.social.SocialIdentityProviderFactory | 3 +- .../testsuite/admin/IdentityProviderTest.java | 7 +- .../KcOidcBrokerNonceParameterTest.java | 43 ++++++- .../testsuite/broker/SocialLoginTest.java | 23 ++-- 21 files changed, 330 insertions(+), 42 deletions(-) create mode 100644 services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProvider.java create mode 100644 services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProviderFactory.java create mode 100644 services/src/main/java/org/keycloak/social/linkedin/LinkedInPublicKeyLoader.java diff --git a/core/src/main/java/org/keycloak/util/JWKSUtils.java b/core/src/main/java/org/keycloak/util/JWKSUtils.java index fc88232206..e80f81f240 100644 --- a/core/src/main/java/org/keycloak/util/JWKSUtils.java +++ b/core/src/main/java/org/keycloak/util/JWKSUtils.java @@ -65,13 +65,19 @@ public class JWKSUtils { } public static PublicKeysWrapper getKeyWrappersForUse(JSONWebKeySet keySet, JWK.Use requestedUse) { + return getKeyWrappersForUse(keySet, requestedUse, false); + } + + public static PublicKeysWrapper getKeyWrappersForUse(JSONWebKeySet keySet, JWK.Use requestedUse, boolean useRequestedUseWhenNull) { List result = new ArrayList<>(); for (JWK jwk : keySet.getKeys()) { JWKParser parser = JWKParser.create(jwk); - if (jwk.getPublicKeyUse() == null) { + if (jwk.getPublicKeyUse() == null && !useRequestedUseWhenNull) { logger.debugf("Ignoring JWK key '%s'. Missing required field 'use'.", jwk.getKeyId()); - } else if (requestedUse.asString().equals(jwk.getPublicKeyUse()) && parser.isKeyTypeSupported(jwk.getKeyType())) { + } else if ((requestedUse.asString().equals(jwk.getPublicKeyUse()) || (jwk.getPublicKeyUse() == null && useRequestedUseWhenNull)) + && parser.isKeyTypeSupported(jwk.getKeyType())) { KeyWrapper keyWrapper = wrap(jwk, parser); + keyWrapper.setUse(getKeyUse(requestedUse.asString())); result.add(keyWrapper); } } diff --git a/docs/documentation/server_admin/images/linked-in-add-identity-provider.png b/docs/documentation/server_admin/images/linked-in-add-identity-provider.png index aca916d5422983fe83e97423ba112647fb71a3d6..d9fa0ed7a85296a66901b053ad5865a8e218fb49 100644 GIT binary patch literal 44687 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 UQHMB^De)_^==BS6=WpHrAJjn|B>(^b literal 44775 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�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 VUa>o|K|C_ytKwG@F5i0azW~yWz|8;v diff --git a/docs/documentation/server_admin/topics/identity-broker/social/linked-in.adoc b/docs/documentation/server_admin/topics/identity-broker/social/linked-in.adoc index 45c0311c5f..6de26c0d81 100644 --- a/docs/documentation/server_admin/topics/identity-broker/social/linked-in.adoc +++ b/docs/documentation/server_admin/topics/identity-broker/social/linked-in.adoc @@ -5,24 +5,17 @@ .Procedure . Click *Identity Providers* in the menu. -. From the `Add provider` list, select `LinkedIn`. +. From the `Add provider` list, select `LinkedIn OpenID Connect`. + .Add identity provider image:images/linked-in-add-identity-provider.png[Add Identity Provider] + . Copy the value of *Redirect URI* to your clipboard. -. In a separate browser tab, https://www.linkedin.com/developer/apps[create an app]. +. In a separate browser tab, https://developer.linkedin.com[create an app] in the LinkedIn developer portal. .. After you create the app, click the *Auth* tab. .. Enter the value of *Redirect URI* into the *Authorized redirect URLs for your app* field. .. Note *Your Client ID* and *Your Client Secret*. +.. Click the *Products* tab and *Request access* for the *Sign In with LinkedIn using OpenID Connect* product. . In {project_name}, paste the value of the *Client ID* into the *Client ID* field. . In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field. . Click *Add*. - -.Configuration -* With `Profile Projection` you can configure the `projection` parameter for profile requests. -* For example, `(id,firstName,lastName,profilePicture(displayImage~:playableStreams))` produces the following profile request URL: -[source,txt] ----- -https://api.linkedin.com/v2/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams)) ----- \ No newline at end of file diff --git a/docs/documentation/upgrading/topics/keycloak/changes-22_0_2.adoc b/docs/documentation/upgrading/topics/keycloak/changes-22_0_2.adoc index b32b6681d4..7cff9286e6 100644 --- a/docs/documentation/upgrading/topics/keycloak/changes-22_0_2.adoc +++ b/docs/documentation/upgrading/topics/keycloak/changes-22_0_2.adoc @@ -1,3 +1,9 @@ = Never expires option removed from client advanced settings combos The option `Never expires` is now removed from all the combos of the Advanced Settings client tab. This option was misleading because the different lifespans or idle timeouts were never infinite, but limited by the general user session or realm values. Therefore, this option is removed in favor of the other two remaining options: `Inherits from the realm settings` (the client uses general realm timeouts) and `Expires in` (the value is overriden for the client). Internally the `Never expires` was represented by `-1`. Now that value is shown with a warning in the Admin Console and cannot be set directly by the administrator. + += New LinkedIn OpenID Connect social provider + +A new social identity provider called *LinkedIn OpenID Connect* has been introduced for the business and employment-focused platform. LinkedIn released recently a new product for developers called link:https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin-v2[Sign In with LinkedIn using OpenID Connect]. The product provides a new way to authenticate members using OpenID Connect, but the default *OpenID Connect v1.0* identity provider does not work with it at present time. For that reason, {project_name} adds this new identity provider as the specific social provider for the new product. + +The old LinkedIn way based on OAuth seems to be completely removed from the link:https://developer.linkedin.com[developer portal]. How the existing LinkedIn social provider is working with current applications is not clear. {project_name} maintains the old provider but deprecated, and it will be removed in future versions. Its name was changed to *LinkedIn (deprecated)* to avoid misunderstandings. \ No newline at end of file diff --git a/js/apps/admin-ui/public/locales/en/identity-providers-help.json b/js/apps/admin-ui/public/locales/en/identity-providers-help.json index 225b444fd1..1ab8608f6c 100644 --- a/js/apps/admin-ui/public/locales/en/identity-providers-help.json +++ b/js/apps/admin-ui/public/locales/en/identity-providers-help.json @@ -14,6 +14,7 @@ "passCurrentLocale": "Pass the current locale to the identity provider as a ui_locales parameter.", "logoutUrl": "End session endpoint to use to logout user from external IDP.", "backchannelLogout": "Does the external IDP support backchannel logout?", + "disableNonce": "Do not send the nonce parameter in the authentication request. The nonce parameter is sent and verified by default.", "disableUserInfo": "Disable usage of User Info service to obtain additional user information? Default is to use this OIDC service.", "isAccessTokenJWT": "The Access Token received from the Identity Provider is a JWT and its claims will be accessible for mappers.", "userInfoUrl": "The User Info Url. This is optional.", diff --git a/js/apps/admin-ui/public/locales/en/identity-providers.json b/js/apps/admin-ui/public/locales/en/identity-providers.json index 5839772d57..86be9a1161 100644 --- a/js/apps/admin-ui/public/locales/en/identity-providers.json +++ b/js/apps/admin-ui/public/locales/en/identity-providers.json @@ -98,6 +98,7 @@ "tokenUrl": "Token URL", "logoutUrl": "Logout URL", "backchannelLogout": "Backchannel logout", + "disableNonce": "Disable nonce", "disableUserInfo": "Disable user info", "isAccessTokenJWT": "Access Token is JWT", "userInfoUrl": "User Info URL", diff --git a/js/apps/admin-ui/src/identity-providers/add/ExtendedNonDiscoverySettings.tsx b/js/apps/admin-ui/src/identity-providers/add/ExtendedNonDiscoverySettings.tsx index e5d778fe03..7c417362df 100644 --- a/js/apps/admin-ui/src/identity-providers/add/ExtendedNonDiscoverySettings.tsx +++ b/js/apps/admin-ui/src/identity-providers/add/ExtendedNonDiscoverySettings.tsx @@ -46,6 +46,7 @@ export const ExtendedNonDiscoverySettings = () => { label="backchannelLogout" /> + 0) { @@ -584,11 +586,15 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider { private static final Logger log = Logger.getLogger(LinkedInIdentityProvider.class); diff --git a/services/src/main/java/org/keycloak/social/linkedin/LinkedInIdentityProviderFactory.java b/services/src/main/java/org/keycloak/social/linkedin/LinkedInIdentityProviderFactory.java index f067ea2de8..69f5e2abe5 100755 --- a/services/src/main/java/org/keycloak/social/linkedin/LinkedInIdentityProviderFactory.java +++ b/services/src/main/java/org/keycloak/social/linkedin/LinkedInIdentityProviderFactory.java @@ -29,6 +29,7 @@ import java.util.List; /** * @author Vlastimil Elias (velias at redhat dot com) */ +@Deprecated public class LinkedInIdentityProviderFactory extends AbstractIdentityProviderFactory implements SocialIdentityProviderFactory { @@ -36,7 +37,7 @@ public class LinkedInIdentityProviderFactory extends AbstractIdentityProviderFac @Override public String getName() { - return "LinkedIn"; + return "LinkedIn (deprecated)"; } @Override diff --git a/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProvider.java b/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProvider.java new file mode 100644 index 0000000000..2a4e10bf67 --- /dev/null +++ b/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProvider.java @@ -0,0 +1,56 @@ +/* + * Copyright 2023 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.social.linkedin; + +import org.keycloak.broker.oidc.OIDCIdentityProvider; +import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; +import org.keycloak.broker.social.SocialIdentityProvider; +import org.keycloak.crypto.KeyWrapper; +import org.keycloak.jose.jws.JWSInput; +import org.keycloak.keys.PublicKeyLoader; +import org.keycloak.keys.PublicKeyStorageProvider; +import org.keycloak.keys.PublicKeyStorageUtils; +import org.keycloak.models.KeycloakSession; + +/** + *

Specific OIDC LinkedIn provider for Sign In with LinkedIn using OpenID Connect + * product app.

+ * + * @author rmartinc + */ +public class LinkedInOIDCIdentityProvider extends OIDCIdentityProvider implements SocialIdentityProvider { + + public static final String DEFAULT_SCOPE = "openid profile email"; + + public LinkedInOIDCIdentityProvider(KeycloakSession session, OIDCIdentityProviderConfig config) { + super(session, config); + } + + @Override + protected String getDefaultScopes() { + return DEFAULT_SCOPE; + } + + @Override + protected KeyWrapper getIdentityProviderKeyWrapper(JWSInput jws) { + // workaround to load keys published with no "use" as signature + PublicKeyLoader loader = new LinkedInPublicKeyLoader(session, getConfig()); + PublicKeyStorageProvider keyStorage = session.getProvider(PublicKeyStorageProvider.class); + String modelKey = PublicKeyStorageUtils.getIdpModelCacheKey(session.getContext().getRealm().getId(), getConfig().getInternalId()); + return keyStorage.getPublicKey(modelKey, jws.getHeader().getKeyId(), jws.getHeader().getRawAlgorithm(), loader); + } +} diff --git a/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProviderFactory.java b/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProviderFactory.java new file mode 100644 index 0000000000..9130062a57 --- /dev/null +++ b/services/src/main/java/org/keycloak/social/linkedin/LinkedInOIDCIdentityProviderFactory.java @@ -0,0 +1,114 @@ +/* + * Copyright 2023 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.social.linkedin; + +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import java.io.IOException; +import java.util.List; +import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; +import org.keycloak.broker.provider.AbstractIdentityProviderFactory; +import org.keycloak.broker.provider.util.SimpleHttp; +import org.keycloak.broker.social.SocialIdentityProviderFactory; +import org.keycloak.models.IdentityProviderModel; +import org.keycloak.models.KeycloakSession; +import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation; +import org.keycloak.provider.ProviderConfigProperty; +import org.keycloak.provider.ProviderConfigurationBuilder; + +/** + *

Specific OIDC LinkedIn provider for Sign In with LinkedIn using OpenID Connect + * product app. LinkedIn currently has two issues with default OIDC provider + * implementation:

+ * + *
    + *
  1. The jwks endpoint does not contain use claim for the signature key.
  2. + *
  3. The nonce in the authentication request is not returned back in the ID Token.
  4. + *
+ * + *

This factory workarounds the default provider to overcome the issues.

+ * + * @author rmartinc + */ +public class LinkedInOIDCIdentityProviderFactory extends AbstractIdentityProviderFactory implements SocialIdentityProviderFactory { + + public static final String PROVIDER_ID = "linkedin-openid-connect"; + public static final String WELL_KNOWN_URL = "https://www.linkedin.com/oauth/.well-known/openid-configuration"; + + // well known oidc metadata is cached as static property + private static OIDCConfigurationRepresentation metadata; + + @Override + public String getName() { + return "LinkedIn OpenID Connect"; + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + public LinkedInOIDCIdentityProvider create(KeycloakSession session, IdentityProviderModel model) { + OIDCConfigurationRepresentation local = metadata; + if (local == null) { + local = getWellKnownMetadata(session); + if (local.getIssuer() == null || local.getTokenEndpoint() == null || local.getAuthorizationEndpoint()== null || local.getJwksUri() == null) { + throw new RuntimeException("Invalid data in the OIDC LinkedIn well-known address."); + } + metadata = local; + } + OIDCIdentityProviderConfig config = new OIDCIdentityProviderConfig(model); + config.setIssuer(local.getIssuer()); + config.setAuthorizationUrl(local.getAuthorizationEndpoint()); + config.setTokenUrl(local.getTokenEndpoint()); + if (local.getUserinfoEndpoint() != null) { + config.setUserInfoUrl(local.getUserinfoEndpoint()); + } + config.setUseJwksUrl(true); + config.setJwksUrl(local.getJwksUri()); + config.setValidateSignature(true); + config.setDisableNonce(true); // linkedin does not manage nonce correctly + return new LinkedInOIDCIdentityProvider(session, config); + } + + @Override + public OIDCIdentityProviderConfig createConfig() { + return new OIDCIdentityProviderConfig(); + } + + private static OIDCConfigurationRepresentation getWellKnownMetadata(KeycloakSession session) { + try (SimpleHttp.Response response = SimpleHttp.doGet(WELL_KNOWN_URL, session) + .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON) + .asResponse()) { + if (Response.Status.fromStatusCode(response.getStatus()).getFamily() != Response.Status.Family.SUCCESSFUL) { + throw new RuntimeException("Error calling the OIDC LinkedIn well-known address. Http status " + response.getStatus()); + } + return response.asJson(OIDCConfigurationRepresentation.class); + } catch (IOException e) { + throw new RuntimeException("Error calling the OIDC LinkedIn well-known address.", e); + } + } + + @Override + public List getConfigProperties() { + // we can add some common OIDC config parameters here if needed + return ProviderConfigurationBuilder.create() + .build(); + } +} diff --git a/services/src/main/java/org/keycloak/social/linkedin/LinkedInPublicKeyLoader.java b/services/src/main/java/org/keycloak/social/linkedin/LinkedInPublicKeyLoader.java new file mode 100644 index 0000000000..48e4bb29db --- /dev/null +++ b/services/src/main/java/org/keycloak/social/linkedin/LinkedInPublicKeyLoader.java @@ -0,0 +1,51 @@ +/* + * Copyright 2023 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.social.linkedin; + +import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; +import org.keycloak.crypto.PublicKeysWrapper; +import org.keycloak.jose.jwk.JSONWebKeySet; +import org.keycloak.jose.jwk.JWK; +import org.keycloak.keys.PublicKeyLoader; +import org.keycloak.models.KeycloakSession; +import org.keycloak.protocol.oidc.utils.JWKSHttpUtils; +import org.keycloak.util.JWKSUtils; + +/** + *

Specific public key loader that assumes that use for the keys is the requested one. + * The LinkedIn OpenID Connect implementation does not add the compulsory + * use claim in the jwks endpoint.

+ * + * @author rmartinc + */ +public class LinkedInPublicKeyLoader implements PublicKeyLoader { + + private final KeycloakSession session; + private final OIDCIdentityProviderConfig config; + + public LinkedInPublicKeyLoader(KeycloakSession session, OIDCIdentityProviderConfig config) { + this.session = session; + this.config = config; + } + + @Override + public PublicKeysWrapper loadKeys() throws Exception { + String jwksUrl = config.getJwksUrl(); + JSONWebKeySet jwks = JWKSHttpUtils.sendJwksRequest(session, jwksUrl); + return JWKSUtils.getKeyWrappersForUse(jwks, JWK.Use.SIG, true); + } +} diff --git a/services/src/main/java/org/keycloak/social/linkedin/LinkedInUserAttributeMapper.java b/services/src/main/java/org/keycloak/social/linkedin/LinkedInUserAttributeMapper.java index 43ec4b2577..35a695b372 100644 --- a/services/src/main/java/org/keycloak/social/linkedin/LinkedInUserAttributeMapper.java +++ b/services/src/main/java/org/keycloak/social/linkedin/LinkedInUserAttributeMapper.java @@ -25,7 +25,7 @@ import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper; */ public class LinkedInUserAttributeMapper extends AbstractJsonUserAttributeMapper { - private static final String[] cp = new String[] { LinkedInIdentityProviderFactory.PROVIDER_ID }; + private static final String[] cp = new String[] { LinkedInIdentityProviderFactory.PROVIDER_ID, LinkedInOIDCIdentityProviderFactory.PROVIDER_ID }; @Override public String[] getCompatibleProviders() { diff --git a/services/src/main/resources/META-INF/services/org.keycloak.broker.social.SocialIdentityProviderFactory b/services/src/main/resources/META-INF/services/org.keycloak.broker.social.SocialIdentityProviderFactory index 8281160020..8bcc24617a 100755 --- a/services/src/main/resources/META-INF/services/org.keycloak.broker.social.SocialIdentityProviderFactory +++ b/services/src/main/resources/META-INF/services/org.keycloak.broker.social.SocialIdentityProviderFactory @@ -20,6 +20,7 @@ org.keycloak.social.paypal.PayPalIdentityProviderFactory org.keycloak.social.github.GitHubIdentityProviderFactory org.keycloak.social.google.GoogleIdentityProviderFactory org.keycloak.social.linkedin.LinkedInIdentityProviderFactory +org.keycloak.social.linkedin.LinkedInOIDCIdentityProviderFactory org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory org.keycloak.social.twitter.TwitterIdentityProviderFactory org.keycloak.social.microsoft.MicrosoftIdentityProviderFactory @@ -27,4 +28,4 @@ org.keycloak.social.openshift.OpenshiftV3IdentityProviderFactory org.keycloak.social.openshift.OpenshiftV4IdentityProviderFactory org.keycloak.social.gitlab.GitLabIdentityProviderFactory org.keycloak.social.bitbucket.BitbucketIdentityProviderFactory -org.keycloak.social.instagram.InstagramIdentityProviderFactory \ No newline at end of file +org.keycloak.social.instagram.InstagramIdentityProviderFactory diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java index 186e9bb9b5..50a4f33a32 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/IdentityProviderTest.java @@ -897,7 +897,12 @@ public class IdentityProviderTest extends AbstractAdminTest { response = realm.identityProviders().getIdentityProviders("linkedin"); Assert.assertEquals("Status", 200, response.getStatus()); body = response.readEntity(Map.class); - assertProviderInfo(body, "linkedin", "LinkedIn"); + assertProviderInfo(body, "linkedin", "LinkedIn (deprecated)"); + + response = realm.identityProviders().getIdentityProviders("linkedin-openid-connect"); + Assert.assertEquals("Status", 200, response.getStatus()); + body = response.readEntity(Map.class); + assertProviderInfo(body, "linkedin-openid-connect", "LinkedIn OpenID Connect"); response = realm.identityProviders().getIdentityProviders("microsoft"); Assert.assertEquals("Status", 200, response.getStatus()); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerNonceParameterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerNonceParameterTest.java index cec7734d8d..3bbd82c63a 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerNonceParameterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/KcOidcBrokerNonceParameterTest.java @@ -2,15 +2,25 @@ package org.keycloak.testsuite.broker; import org.junit.Assert; import org.junit.Test; +import org.keycloak.admin.client.resource.IdentityProviderResource; +import org.keycloak.broker.oidc.OIDCIdentityProvider; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.JWSInputException; +import org.keycloak.protocol.ProtocolMapperUtils; +import org.keycloak.protocol.oidc.OIDCLoginProtocol; +import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper; +import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper; import org.keycloak.representations.IDToken; import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.IdentityProviderRepresentation; +import org.keycloak.representations.idm.ProtocolMapperRepresentation; import org.keycloak.testsuite.util.ClientBuilder; import org.keycloak.testsuite.util.OAuthClient; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; import static org.keycloak.testsuite.broker.BrokerTestTools.getConsumerRoot; @@ -23,11 +33,23 @@ public class KcOidcBrokerNonceParameterTest extends AbstractBrokerTest { public List createConsumerClients() { List clients = new ArrayList<>(super.createConsumerClients()); - clients.add(ClientBuilder.create().clientId("consumer-client") + ClientRepresentation client = ClientBuilder.create().clientId("consumer-client") .publicClient() .redirectUris(getConsumerRoot() + "/auth/realms/master/app/auth/*") - .publicClient().build()); - + .publicClient().build(); + + // add the federated ID token to the protocol ID token + ProtocolMapperRepresentation consumerSessionNoteToClaimMapper = new ProtocolMapperRepresentation(); + consumerSessionNoteToClaimMapper.setName(OIDCIdentityProvider.FEDERATED_ID_TOKEN); + consumerSessionNoteToClaimMapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); + consumerSessionNoteToClaimMapper.setProtocolMapper(UserSessionNoteMapper.PROVIDER_ID); + consumerSessionNoteToClaimMapper.setConfig(Map.of(ProtocolMapperUtils.USER_SESSION_NOTE, OIDCIdentityProvider.FEDERATED_ID_TOKEN, + OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME, OIDCIdentityProvider.FEDERATED_ID_TOKEN, + OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.TRUE.toString())); + client.setProtocolMappers(Arrays.asList(consumerSessionNoteToClaimMapper)); + + clients.add(client); + return clients; } }; @@ -48,12 +70,23 @@ public class KcOidcBrokerNonceParameterTest extends AbstractBrokerTest { IDToken idToken = toIdToken(response.getIdToken()); Assert.assertEquals("123456", idToken.getNonce()); + String federatedIdTokenString = (String) idToken.getOtherClaims().get(OIDCIdentityProvider.FEDERATED_ID_TOKEN); + Assert.assertNotNull(federatedIdTokenString); + IDToken federatedIdToken = toIdToken(federatedIdTokenString); + Assert.assertNotNull(federatedIdToken.getNonce()); } @Test public void testNonceNotSet() { updateExecutions(AbstractBrokerTest::disableUpdateProfileOnFirstLogin); + // do not send nonce at IDP provider level either + IdentityProviderResource idpRes = adminClient.realm(bc.consumerRealmName()).identityProviders().get(BrokerTestConstants.IDP_OIDC_ALIAS); + IdentityProviderRepresentation idpRep = idpRes.toRepresentation(); + OIDCIdentityProviderConfigRep cfg = new OIDCIdentityProviderConfigRep(idpRep); + cfg.setDisableNonce(true); + idpRes.update(idpRep); + oauth.realm(bc.consumerRealmName()); oauth.clientId("consumer-client"); oauth.nonce(null); @@ -65,6 +98,10 @@ public class KcOidcBrokerNonceParameterTest extends AbstractBrokerTest { IDToken idToken = toIdToken(response.getIdToken()); Assert.assertNull(idToken.getNonce()); + String federatedIdTokenString = (String) idToken.getOtherClaims().get(OIDCIdentityProvider.FEDERATED_ID_TOKEN); + Assert.assertNotNull(federatedIdTokenString); + IDToken federatedIdToken = toIdToken(federatedIdTokenString); + Assert.assertNull(federatedIdToken.getNonce()); } protected IDToken toIdToken(String encoded) { diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java index d271c51075..9bcd6acc58 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/SocialLoginTest.java @@ -83,7 +83,6 @@ import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.GOOGLE_HOST import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.GOOGLE_NON_MATCHING_HOSTED_DOMAIN; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.INSTAGRAM; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.LINKEDIN; -import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.LINKEDIN_WITH_PROJECTION; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.MICROSOFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4; @@ -125,8 +124,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { GITHUB("github", GitHubLoginPage.class), GITHUB_PRIVATE_EMAIL("github", "github-private-email", GitHubLoginPage.class), TWITTER("twitter", TwitterConsentLoginPage.class), - LINKEDIN("linkedin", LinkedInLoginPage.class), - LINKEDIN_WITH_PROJECTION("linkedin", LinkedInLoginPage.class), + LINKEDIN("linkedin-openid-connect", LinkedInLoginPage.class), MICROSOFT("microsoft", MicrosoftLoginPage.class), PAYPAL("paypal", PayPalLoginPage.class), STACKOVERFLOW("stackoverflow", StackOverflowLoginPage.class), @@ -395,15 +393,7 @@ public class SocialLoginTest extends AbstractKeycloakTest { @Test public void linkedinLogin() { setTestProvider(LINKEDIN); - performLogin(); - appPage.assertCurrent(); - } - - @Test - public void linkedinLoginWithProjection() { - setTestProvider(LINKEDIN_WITH_PROJECTION); - addAttributeMapper("picture", - "profilePicture.displayImage~.elements[0].identifiers[0].identifier"); + addAttributeMapper("picture", "picture", "linkedin-user-attribute-mapper"); performLogin(); appPage.assertCurrent(); assertAttribute("picture", getConfig("profile.picture")); @@ -451,9 +441,6 @@ public class SocialLoginTest extends AbstractKeycloakTest { if (provider == GOOGLE_NON_MATCHING_HOSTED_DOMAIN) { idp.getConfig().put("hostedDomain", "non-matching-hosted-domain"); } - if (provider == LINKEDIN_WITH_PROJECTION) { - idp.getConfig().put("profileProjection", "(id,firstName,lastName,profilePicture(displayImage~:playableStreams))"); - } if (provider == STACKOVERFLOW) { idp.getConfig().put("key", getConfig(provider, "clientKey")); } @@ -471,13 +458,17 @@ public class SocialLoginTest extends AbstractKeycloakTest { } private void addAttributeMapper(String name, String jsonField) { + addAttributeMapper(name, jsonField, currentTestProvider.id + "-user-attribute-mapper"); + } + + private void addAttributeMapper(String name, String jsonField, String mapperName) { IdentityProviderResource identityProvider = adminClient.realm(REALM).identityProviders().get(currentTestProvider.id); IdentityProviderRepresentation identityProviderRepresentation = identityProvider.toRepresentation(); //Add birthday mapper IdentityProviderMapperRepresentation mapperRepresentation = new IdentityProviderMapperRepresentation(); mapperRepresentation.setName(name); mapperRepresentation.setIdentityProviderAlias(identityProviderRepresentation.getAlias()); - mapperRepresentation.setIdentityProviderMapper(currentTestProvider.id + "-user-attribute-mapper"); + mapperRepresentation.setIdentityProviderMapper(mapperName); mapperRepresentation.setConfig(ImmutableMap.builder() .put(IdentityProviderMapperModel.SYNC_MODE, IdentityProviderMapperSyncMode.IMPORT.toString()) .put(AbstractJsonUserAttributeMapper.CONF_JSON_FIELD, jsonField)