Skip to content

Commit

Permalink
Add OIDC Slack known provider
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvavrik authored and sberyozkin committed Oct 31, 2024
1 parent 45dbff7 commit 5a05d9a
Show file tree
Hide file tree
Showing 17 changed files with 388 additions and 1 deletion.
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

0 comments on commit 5a05d9a

Please sign in to comment.