diff --git a/docs/src/main/asciidoc/images/oidc-linkedin-1.png b/docs/src/main/asciidoc/images/oidc-linkedin-1.png new file mode 100644 index 0000000000000..284958a9916fe Binary files /dev/null and b/docs/src/main/asciidoc/images/oidc-linkedin-1.png differ diff --git a/docs/src/main/asciidoc/images/oidc-linkedin-2.png b/docs/src/main/asciidoc/images/oidc-linkedin-2.png new file mode 100644 index 0000000000000..f549326dfe4a4 Binary files /dev/null and b/docs/src/main/asciidoc/images/oidc-linkedin-2.png differ diff --git a/docs/src/main/asciidoc/images/oidc-linkedin-3.png b/docs/src/main/asciidoc/images/oidc-linkedin-3.png new file mode 100644 index 0000000000000..ef0025ca429b4 Binary files /dev/null and b/docs/src/main/asciidoc/images/oidc-linkedin-3.png differ diff --git a/docs/src/main/asciidoc/security-openid-connect-providers.adoc b/docs/src/main/asciidoc/security-openid-connect-providers.adoc index 79a39a1e0aa7a..f4a98eeaa2c4e 100644 --- a/docs/src/main/asciidoc/security-openid-connect-providers.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-providers.adoc @@ -8,7 +8,7 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc include::_attributes.adoc[] :diataxis-type: concept :categories: security,web -:keywords: oidc github twitter google facebook mastodon microsoft apple spotify twitch +:keywords: oidc github twitter google facebook mastodon microsoft apple spotify twitch linkedin :toclevels: 3 :topics: security,oidc,github,twitter,google,facebook,mastodon,microsoft,apple,spotify,twitch :extensions: io.quarkus:quarkus-oidc @@ -501,6 +501,31 @@ quarkus.oidc.client-id= quarkus.oidc.credentials.client-secret= ---- +[[linkedin]] +=== LinkedIn + +Create a https://developer.linkedin.com/[LinkedIn application]: + +image::oidc-linkedin-1.png[role="thumb"] + +Add the `Sign In with LinkedIn using OpenId Connect` product: + +image::oidc-linkedin-2.png[role="thumb"] + +You now can get your client id and secret. Don't forget to also add the authorized redirect URLs for your application: + +image::oidc-linkedin-3.png[role="thumb"] + +You can now configure your `application.properties`: + +[source,properties] +---- +quarkus.oidc.provider=linkedin +quarkus.oidc.client-id= +quarkus.oidc.credentials.client-secret= +---- + + [[provider-scope]] == Provider scopes diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java index 6b913536b709f..8c178262454bc 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/OidcTenantConfig.java @@ -1808,6 +1808,7 @@ public static enum Provider { FACEBOOK, GITHUB, GOOGLE, + LINKEDIN, MASTODON, MICROSOFT, SPOTIFY, diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/providers/KnownOidcProviders.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/providers/KnownOidcProviders.java index c8172f2b1cd91..129262cd29b2b 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/providers/KnownOidcProviders.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/providers/KnownOidcProviders.java @@ -10,31 +10,29 @@ public class KnownOidcProviders { public static OidcTenantConfig provider(OidcTenantConfig.Provider provider) { - switch (provider) { - case APPLE: - return apple(); - case DISCORD: - return discord(); - case FACEBOOK: - return facebook(); - case GITHUB: - return github(); - case GOOGLE: - return google(); - case MASTODON: - return mastodon(); - case MICROSOFT: - return microsoft(); - case SPOTIFY: - return spotify(); - case TWITCH: - return twitch(); - case TWITTER: - case X: - return twitter(); - default: - return null; - } + return switch (provider) { + case APPLE -> apple(); + case DISCORD -> discord(); + case FACEBOOK -> facebook(); + case GITHUB -> github(); + case GOOGLE -> google(); + case LINKEDIN -> linkedIn(); + case MASTODON -> mastodon(); + case MICROSOFT -> microsoft(); + case SPOTIFY -> spotify(); + case TWITCH -> twitch(); + case TWITTER, X -> twitter(); + }; + } + + private static OidcTenantConfig linkedIn() { + OidcTenantConfig ret = new OidcTenantConfig(); + ret.setAuthServerUrl("https://www.linkedin.com/oauth"); + ret.setApplicationType(OidcTenantConfig.ApplicationType.WEB_APP); + ret.getAuthentication().setScopes(List.of("email", "profile")); + ret.getCredentials().getClientSecret().setMethod(Method.POST); + ret.getToken().setPrincipalClaim("name"); + return ret; } private static OidcTenantConfig github() { diff --git a/extensions/oidc/runtime/src/test/java/io/quarkus/oidc/runtime/OidcUtilsTest.java b/extensions/oidc/runtime/src/test/java/io/quarkus/oidc/runtime/OidcUtilsTest.java index c31e38c5197d6..b2ac3a6788151 100644 --- a/extensions/oidc/runtime/src/test/java/io/quarkus/oidc/runtime/OidcUtilsTest.java +++ b/extensions/oidc/runtime/src/test/java/io/quarkus/oidc/runtime/OidcUtilsTest.java @@ -519,6 +519,36 @@ public void testOverrideDiscordProperties() throws Exception { assertEquals(Method.BASIC, config.credentials.clientSecret.method.get()); } + @Test + public void testAcceptLinkedInProperties() throws Exception { + OidcTenantConfig tenant = new OidcTenantConfig(); + tenant.setTenantId(OidcUtils.DEFAULT_TENANT_ID); + OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.LINKEDIN)); + + assertEquals(OidcUtils.DEFAULT_TENANT_ID, config.getTenantId().get()); + assertEquals("https://www.linkedin.com/oauth", config.getAuthServerUrl().get()); + assertEquals(List.of("email", "profile"), config.authentication.scopes.get()); + } + + @Test + public void testOverrideLinkedInProperties() throws Exception { + OidcTenantConfig tenant = new OidcTenantConfig(); + tenant.setTenantId(OidcUtils.DEFAULT_TENANT_ID); + + tenant.setApplicationType(ApplicationType.HYBRID); + tenant.setAuthServerUrl("http://localhost/wiremock"); + tenant.credentials.clientSecret.setMethod(Method.BASIC); + tenant.authentication.setForceRedirectHttpsScheme(false); + + OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.LINKEDIN)); + + assertEquals(OidcUtils.DEFAULT_TENANT_ID, config.getTenantId().get()); + assertEquals(ApplicationType.HYBRID, config.getApplicationType().get()); + assertEquals("http://localhost/wiremock", config.getAuthServerUrl().get()); + assertFalse(config.getAuthentication().isForceRedirectHttpsScheme().get()); + assertEquals(Method.BASIC, config.credentials.clientSecret.method.get()); + } + @Test public void testCorrectTokenType() throws Exception { OidcTenantConfig.Token tokenClaims = new OidcTenantConfig.Token();