Skip to content

Commit

Permalink
Finalize Dev Services for OIDC
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvavrik committed Jan 8, 2025
1 parent ce9b46f commit 0c1a13e
Show file tree
Hide file tree
Showing 31 changed files with 1,868 additions and 749 deletions.
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, oidc-wiremock-providers",
"test-modules": "oidc, oidc-code-flow, oidc-tenancy, oidc-client, oidc-client-reactive, oidc-token-propagation, oidc-wiremock, oidc-client-wiremock, oidc-wiremock-providers, oidc-dev-services",
"os-name": "ubuntu-latest"
},
{
Expand Down
5 changes: 5 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,11 @@
<artifactId>quarkus-devservices-keycloak</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devservices-oidc</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 42 additions & 1 deletion docs/src/main/asciidoc/security-openid-connect-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ The Dev Services for Keycloak feature starts a Keycloak container for both the d
It initializes them by registering the existing Keycloak realm or creating a new realm with the client and users required for you to start developing your Quarkus application secured by Keycloak immediately.
The container restarts when the `application.properties` or the realm file changes have been detected.

Additionally, xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev[/q/dev] complements this feature with a Dev UI page, which helps to acquire the tokens from Keycloak and test your Quarkus application.
Additionally, xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev-ui/extensions[/q/dev-ui/extensions] complements this feature with a Dev UI page, which helps to acquire the tokens from Keycloak and test your Quarkus application.

If `quarkus.oidc.auth-server-url` is already set, then a generic OpenID Connect Dev Console, which can be used with all OpenID Connect providers, is activated.
For more information, see <<dev-ui-all-oidc-providers,Dev UI for all OpenID Connect providers>>.

[[dev-services-for-keycloak]]
== Dev Services for Keycloak

Start your application without configuring `quarkus.oidc` properties in the `application.properties` file:
Expand Down Expand Up @@ -406,6 +407,46 @@ This document refers to the `http://localhost:8080/q/dev-ui` Dev UI URL in sever
If you customize `quarkus.http.root-path` or `quarkus.http.non-application-root-path` properties, then replace `q` accordingly.
For more information, see the https://quarkus.io/blog/path-resolution-in-quarkus/[Path resolution in Quarkus] blog post.

== Dev Services for OIDC

When you work with Keycloak in production, <<dev-services-for-keycloak>> provides the best dev mode experience.
For other OpenID Connect providers, it is recommended to enable the Dev Services for OIDC like in the example below:

[source,properties]
----
quarkus.oidc.devservices.enabled=true
----

NOTE: the Dev Services for OIDC are enabled by default if Docker and Podman are not available.

Once enabled, Quarkus starts a new OIDC server that supports most common OpenID Connect operations.
You can confirm in the Dev UI console that the OIDC server started, you will see output similar to the following:

[source,shell]
----
2025-01-08 20:50:20,900 INFO [io.qua.dev.oid.OidcDevServicesProcessor] (build-16) Dev Services for OIDC started on http://localhost:38139
----

If you navigate to the <<dev-ui-all-oidc-providers>>, you can log into the OIDC server as builtin users `alice` or `bob`:

image::dev-ui-oidc-dev-svc-login-page.png[alt=Dev Services for OIDC builtin user login,role="center"]

As always, default `alice` roles are `admin` and `user`, while default `bob` role is `user`.
Nevertheless, you can configure roles according to your preference:

[source,properties]
----
quarkus.oidc.devservices.roles.alice=root <1>
quarkus.oidc.devservices.roles.bob=guest
----
<1> Assign a `root` role to the user `alice`.

Another option is log in as a custom user with username and roles of your choice:

image::dev-ui-oidc-dev-svc-login-for-custom-users.png[alt=Dev Services for OIDC custom user login,role="center"]

Whichever user you choose, password is not required.

== References

* xref:dev-ui.adoc[Dev UI]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ public interface KeycloakDevServicesConfig {
@WithDefault("true")
boolean enabled();

/**
* Use lightweight dev services instead of Keycloak
*/
@ConfigItem(defaultValue = "false")
public boolean lightweight;

/**
* The container image name for Dev Services providers.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ DevServicesResultBuildItem startKeycloakContainer(
DevServicesConfig devServicesConfig, DockerStatusBuildItem dockerStatusBuildItem) {

if (devSvcRequiredMarkerItems.isEmpty()
|| linuxContainersNotAvailable(dockerStatusBuildItem, devSvcRequiredMarkerItems)) {
|| linuxContainersNotAvailable(dockerStatusBuildItem, devSvcRequiredMarkerItems)
|| oidcDevServicesEnabled()) {
if (devService != null) {
closeDevService();
}
Expand Down Expand Up @@ -248,6 +249,10 @@ public void run() {
return devService.toBuildItem();
}

private static boolean oidcDevServicesEnabled() {
return ConfigProvider.getConfig().getOptionalValue("quarkus.oidc.devservices.enabled", boolean.class).orElse(false);
}

private static boolean linuxContainersNotAvailable(DockerStatusBuildItem dockerStatusBuildItem,
List<KeycloakDevServicesRequiredBuildItem> devSvcRequiredMarkerItems) {
if (dockerStatusBuildItem.isContainerRuntimeAvailable()) {
Expand Down
53 changes: 53 additions & 0 deletions extensions/devservices/oidc/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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-devservices-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-devservices-oidc</artifactId>
<name>Quarkus - DevServices - OIDC</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devservices-common</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-mutiny-vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-jwt-build</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.quarkus.devservices.oidc;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigDocDefault;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;

/**
* OpenID Connect Dev Services configuration.
*/
@ConfigRoot
@ConfigMapping(prefix = "quarkus.oidc.devservices")
public interface OidcDevServicesConfig {

/**
* Use OpenID Connect Dev Services instead of Keycloak.
*/
@ConfigDocDefault("Enabled when Docker and Podman are not available")
Optional<Boolean> enabled();

/**
* A map of roles for OIDC identity provider users.
* <p>
* If empty, default roles are assigned: `alice` receives `admin` and `user` roles, while other users receive
* `user` role.
* This map is used for role creation when no realm file is found at the `realm-path`.
*/
@ConfigDocMapKey("role-name")
Map<String, List<String>> roles();

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package io.quarkus.oidc.deployment.devservices.keycloak;
package io.quarkus.devservices.oidc;

import java.util.Map;

import io.quarkus.builder.item.SimpleBuildItem;

public final class LightweightDevServicesConfigBuildItem extends SimpleBuildItem {
/**
* OIDC Dev Services configuration properties.
*/
public final class OidcDevServicesConfigBuildItem extends SimpleBuildItem {

private final Map<String, String> config;

public LightweightDevServicesConfigBuildItem(Map<String, String> config) {
OidcDevServicesConfigBuildItem(Map<String, String> config) {
this.config = config;
}

public Map<String, String> getConfig() {
return config;
}

}
Loading

0 comments on commit 0c1a13e

Please sign in to comment.