Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/native-tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
{
"category": "Security2",
"timeout": 75,
"test-modules": "oidc, oidc-code-flow, oidc-tenancy, oidc-client, oidc-client-reactive, oidc-token-propagation, oidc-wiremock, oidc-client-wiremock",
"test-modules": "oidc, oidc-code-flow, oidc-tenancy, oidc-client, oidc-client-reactive, oidc-token-propagation, oidc-wiremock, oidc-client-wiremock, oidc-wiremock-providers",
"os-name": "ubuntu-latest"
},
{
Expand Down
Binary file added docs/src/main/asciidoc/images/oidc-slack-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/main/asciidoc/images/oidc-slack-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/main/asciidoc/images/oidc-slack-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/main/asciidoc/images/oidc-slack-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/src/main/asciidoc/images/oidc-slack-5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions docs/src/main/asciidoc/security-openid-connect-providers.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,42 @@ quarkus.oidc.token.customizer-name=azure-access-token-customizer

====

[[slack]]
=== Slack

Create a https://api.slack.com/authentication/sign-in-with-slack#setup[Slack application]:

image::oidc-slack-1.png[role="thumb"]

Select application name, workspace, and remember it, you will need it later:

image::oidc-slack-2.png[role="thumb"]

Please save client id and secret displayed on the next page, you will need them later:

image::oidc-slack-3.png[role="thumb"]

Configure redirect URLs.
Slack provider requires HTTPS protocol, for development purposes, you can use ngrok:

image::oidc-slack-4.png[role="thumb"]

You can now configure your `application.properties`:

[source,properties]
----
quarkus.oidc.provider=slack
quarkus.oidc.client-id=<Client ID>
quarkus.oidc.credentials.secret=<Client Secret>
quarkus.oidc.authentication.extra-params.team=quarkus-slack <1>
----
<1> Use the `team` parameter to refer to the workspace you chose during the Slack OIDC application registration.

Open your browser and navigate to your application `https://<your ngrok instance>.ngrok-free.app/`.
Quarkus will redirect you to Slack provider on the first request where you can grant required permissions:

image::oidc-slack-5.png[role="thumb"]

[[spotify]]
=== Spotify

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,7 @@ public static enum Provider {
LINKEDIN,
MASTODON,
MICROSOFT,
SLACK,
SPOTIFY,
STRAVA,
TWITCH,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,24 @@ public static OidcTenantConfig provider(OidcTenantConfig.Provider provider) {
case LINKEDIN -> linkedIn();
case MASTODON -> mastodon();
case MICROSOFT -> microsoft();
case SLACK -> slack();
case SPOTIFY -> spotify();
case STRAVA -> strava();
case TWITCH -> twitch();
case TWITTER, X -> twitter();
};
}

private static OidcTenantConfig slack() {
OidcTenantConfig ret = new OidcTenantConfig();
ret.setAuthServerUrl("https://slack.com");
ret.setApplicationType(OidcTenantConfig.ApplicationType.WEB_APP);
ret.getToken().setPrincipalClaim("name");
ret.getAuthentication().setScopes(List.of("profile", "email"));
ret.getAuthentication().setForceRedirectHttpsScheme(true);
return ret;
}

private static OidcTenantConfig linkedIn() {
OidcTenantConfig ret = new OidcTenantConfig();
ret.setAuthServerUrl("https://www.linkedin.com/oauth");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,4 +588,42 @@ public void testOverrideLinkedInProperties() throws Exception {
assertFalse(config.getAuthentication().isForceRedirectHttpsScheme().get());
assertEquals(Method.BASIC, config.credentials.clientSecret.method.get());
}

@Test
public void testAcceptSlackProperties() {
OidcTenantConfig tenant = new OidcTenantConfig();
tenant.setTenantId(OidcUtils.DEFAULT_TENANT_ID);
OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.SLACK));

assertEquals(OidcUtils.DEFAULT_TENANT_ID, config.getTenantId().get());
assertEquals(ApplicationType.WEB_APP, config.getApplicationType().get());
assertTrue(config.isDiscoveryEnabled().orElse(true));
assertEquals("https://slack.com", config.getAuthServerUrl().get());

assertEquals("name", config.token.principalClaim.get());
assertTrue(config.authentication.forceRedirectHttpsScheme.orElse(false));
assertEquals(List.of("profile", "email"), config.authentication.scopes.get());
}

@Test
public void testOverrideSlackProperties() {
OidcTenantConfig tenant = new OidcTenantConfig();
tenant.setTenantId("PattiSmith");
tenant.setApplicationType(ApplicationType.SERVICE);
tenant.setDiscoveryEnabled(false);
tenant.setAuthServerUrl("https://private-slack.com");
tenant.getToken().setPrincipalClaim("I you my own principal");
tenant.getAuthentication().setForceRedirectHttpsScheme(false);
tenant.getAuthentication().setScopes(List.of("profile"));
OidcTenantConfig config = OidcUtils.mergeTenantConfig(tenant, KnownOidcProviders.provider(Provider.SLACK));

assertEquals("PattiSmith", config.getTenantId().get());
assertEquals(ApplicationType.SERVICE, config.getApplicationType().get());
assertFalse(config.isDiscoveryEnabled().orElse(true));
assertEquals("https://private-slack.com", config.getAuthServerUrl().get());

assertEquals("I you my own principal", config.token.principalClaim.get());
assertFalse(config.authentication.forceRedirectHttpsScheme.orElse(false));
assertEquals(List.of("profile"), config.authentication.scopes.get());
}
}
106 changes: 106 additions & 0 deletions integration-tests/oidc-wiremock-providers/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-integration-tests-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-integration-test-oidc-wiremock-providers</artifactId>
<name>Quarkus - Integration Tests - OpenID Connect Adapter WireMock - Well-known Providers</name>
<description>Module that contains OpenID Connect Well-known Providers related tests using WireMock</description>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-oidc-server</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate-code</goal>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.it.oidc.providers;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.SecurityContext;

import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.oidc.AuthorizationCodeFlow;
import io.quarkus.oidc.IdToken;

@Path("slack")
public class SlackResource {

public record ProvidersResponseDto(String userPrincipalName, String userInfoEmail) {
}

@Inject
@IdToken
JsonWebToken idToken;

@AuthorizationCodeFlow
@GET
public ProvidersResponseDto getPrincipalAndEmailFromSlackProvider(SecurityContext securityContext) {
return new ProvidersResponseDto(securityContext.getUserPrincipal().getName(), idToken.getClaim("email"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
quarkus.http.auth.proactive=false
quarkus.log.category."org.htmlunit".level=ERROR
quarkus.log.category."com.github".level=ERROR
quarkus.keycloak.devservices.enabled=false

quarkus.oidc.slack.provider=slack
quarkus.oidc.slack.auth-server-url=${keycloak.url}/slack
quarkus.oidc.slack.client-id=7925551513107.7922794171477
quarkus.oidc.slack.credentials.secret=2b82d6039bc97946460fdec75fadd9b2
quarkus.oidc.slack.authentication.extra-params.team=quarkus-oidc-slack-demo
quarkus.oidc.slack.authentication.force-redirect-https-scheme=false
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.it.oidc.providers;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class OidcSlackProviderIT extends OidcSlackProviderTest {
}
Loading
Loading