diff --git a/docs/src/main/asciidoc/images/oidc-mastodon-register-app.png b/docs/src/main/asciidoc/images/oidc-mastodon-register-app.png new file mode 100644 index 0000000000000..7ed1fa8879b7e Binary files /dev/null and b/docs/src/main/asciidoc/images/oidc-mastodon-register-app.png differ diff --git a/docs/src/main/asciidoc/images/oidc-mastodon-registered-apps.png b/docs/src/main/asciidoc/images/oidc-mastodon-registered-apps.png new file mode 100644 index 0000000000000..a0205a4ceca3a Binary files /dev/null and b/docs/src/main/asciidoc/images/oidc-mastodon-registered-apps.png differ diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc index 296d4a8f2a07a..3babb1e0bcdd1 100644 --- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc @@ -8,7 +8,7 @@ With the Quarkus OpenID Connect (OIDC) extension, you can protect application HT To learn more about the OIDC authorization code flow mechanism, see xref:security-oidc-code-flow-authentication.adoc[OIDC code flow mechanism for protecting web applications]. -To learn about how well-known social providers such as Google, GitHub, Microsoft, Twitter, Apple, Facebook, and Spotify can be used with Quarkus OIDC, see xref:security-openid-connect-providers.adoc[Configuring Well-Known OpenID Connect Providers]. +To learn about how well-known social providers such as Apple, Facebook, GitHub, Google, Mastodon, Microsoft, Twitch, Twitter (X), and Spotify can be used with Quarkus OIDC, see xref:security-openid-connect-providers.adoc[Configuring Well-Known OpenID Connect Providers]. See also, xref:security-authentication-mechanisms.adoc#other-supported-authentication-mechanisms[Authentication mechanisms in Quarkus]. If you want to protect your service applications by using OIDC Bearer token authentication, see xref:security-oidc-bearer-token-authentication-concept.adoc[OIDC Bearer token authentication]. diff --git a/docs/src/main/asciidoc/security-openid-connect-providers.adoc b/docs/src/main/asciidoc/security-openid-connect-providers.adoc index 8b7b24c82ea5a..1301972cdb04f 100644 --- a/docs/src/main/asciidoc/security-openid-connect-providers.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-providers.adoc @@ -114,6 +114,39 @@ quarkus.oidc.credentials.secret= TIP: You can also send access tokens issued by `Google` to `quarkus.oidc.application-type=service` or `quarkus.oidc.application-type=hybrid` Quarkus applications. +[[mastodon]] +=== Mastodon + +Create a https://joinmastodon.org/[Mastodon account]. You must https://joinmastodon.org/servers[pick a server], for example, `mastodon.social`. +Select a `Development` option in you account and register an application, for example: + +image::oidc-mastodon-registere-app.png[role="thumb"] + +Select the registered application: + +image::oidc-mastodon-registered-apps.png[role="thumb"] + +and note its client id and client secret properties, use them to configure your `application.properties`: + +[source,properties] +---- +quarkus.oidc.provider=mastodon +quarkus.oidc.client-id= +quarkus.oidc.credentials.client-secret.value= +---- + +By default, `quarkus.oidc.provider=mastodon` sets `quarkus.oidc.auth-server-url` to the `https://mastodon.social` Mastodon server address. + +You can override `quarkus.oidc.auth-server-url` if you have created your account in another Mastodon server, for example: + +[source,properties] +---- +quarkus.oidc.provider=mastodon +quarkus.oidc.auth-server-url=https://infosec.exchange +quarkus.oidc.client-id= +quarkus.oidc.credentials.client-secret.value= +---- + [[microsoft]] === Microsoft 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 093d45fcdb238..c98d7b23cf2d6 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 @@ -1658,6 +1658,7 @@ public static enum Provider { FACEBOOK, GITHUB, GOOGLE, + MASTODON, MICROSOFT, SPOTIFY, TWITCH, 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 13aab4cc933dc..667bf3a54467c 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 @@ -19,6 +19,8 @@ public static OidcTenantConfig provider(OidcTenantConfig.Provider provider) { return github(); case GOOGLE: return google(); + case MASTODON: + return mastodon(); case MICROSOFT: return microsoft(); case SPOTIFY: @@ -75,6 +77,25 @@ private static OidcTenantConfig google() { return ret; } + private static OidcTenantConfig mastodon() { + OidcTenantConfig ret = new OidcTenantConfig(); + ret.setDiscoveryEnabled(false); + ret.setAuthServerUrl("https://mastodon.social"); + ret.setApplicationType(OidcTenantConfig.ApplicationType.WEB_APP); + ret.setAuthorizationPath("/oauth/authorize"); + ret.setTokenPath("/oauth/token"); + + ret.setUserInfoPath("/api/v1/accounts/verify_credentials"); + + OidcTenantConfig.Authentication authentication = ret.getAuthentication(); + authentication.setAddOpenidScope(false); + authentication.setScopes(List.of("read")); + authentication.setUserInfoRequired(true); + authentication.setIdTokenRequired(false); + + return ret; + } + private static OidcTenantConfig microsoft() { OidcTenantConfig ret = new OidcTenantConfig(); ret.setAuthServerUrl("https://login.microsoftonline.com/common/v2.0"); 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 54fbc68e12d5f..52105a54e974d 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 @@ -145,6 +145,59 @@ public void testOverrideTwitterProperties() throws Exception { assertFalse(config.authentication.pkceRequired.get()); } + @Test + public void testAcceptMastodonProperties() throws Exception { + OidcTenantConfig tenant = new OidcTenantConfig(); + tenant.setTenantId(OidcUtils.DEFAULT_TENANT_ID); + OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.MASTODON)); + + assertEquals(OidcUtils.DEFAULT_TENANT_ID, config.getTenantId().get()); + assertEquals(ApplicationType.WEB_APP, config.getApplicationType().get()); + assertFalse(config.isDiscoveryEnabled().get()); + assertEquals("https://mastodon.social", config.getAuthServerUrl().get()); + assertEquals("/oauth/authorize", config.getAuthorizationPath().get()); + assertEquals("/oauth/token", config.getTokenPath().get()); + assertEquals("/api/v1/accounts/verify_credentials", config.getUserInfoPath().get()); + + assertFalse(config.authentication.idTokenRequired.get()); + assertTrue(config.authentication.userInfoRequired.get()); + assertFalse(config.authentication.addOpenidScope.get()); + assertEquals(List.of("read"), config.authentication.scopes.get()); + } + + @Test + public void testOverrideMastodonProperties() throws Exception { + OidcTenantConfig tenant = new OidcTenantConfig(); + tenant.setTenantId(OidcUtils.DEFAULT_TENANT_ID); + + tenant.setApplicationType(ApplicationType.HYBRID); + tenant.setDiscoveryEnabled(true); + tenant.setAuthServerUrl("http://localhost/wiremock"); + tenant.setAuthorizationPath("authorization"); + tenant.setTokenPath("tokens"); + tenant.setUserInfoPath("userinfo"); + + tenant.authentication.setIdTokenRequired(true); + tenant.authentication.setUserInfoRequired(false); + tenant.authentication.setAddOpenidScope(true); + tenant.authentication.setScopes(List.of("write")); + + OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.MASTODON)); + + assertEquals(OidcUtils.DEFAULT_TENANT_ID, config.getTenantId().get()); + assertEquals(ApplicationType.HYBRID, config.getApplicationType().get()); + assertTrue(config.isDiscoveryEnabled().get()); + assertEquals("http://localhost/wiremock", config.getAuthServerUrl().get()); + assertEquals("authorization", config.getAuthorizationPath().get()); + assertEquals("tokens", config.getTokenPath().get()); + assertEquals("userinfo", config.getUserInfoPath().get()); + + assertTrue(config.authentication.idTokenRequired.get()); + assertFalse(config.authentication.userInfoRequired.get()); + assertEquals(List.of("write"), config.authentication.scopes.get()); + assertTrue(config.authentication.addOpenidScope.get()); + } + @Test public void testAcceptXProperties() throws Exception { OidcTenantConfig tenant = new OidcTenantConfig();