This guide covers the Dev Services and UI for OpenId Connect (OIDC) Keycloak provider and explains how to support Dev Services and UI for other OpenId Connect providers. It also describes Dev UI for all OpenId Connect providers which have already been started before Quarkus is launched in a dev mode.
Introduction
Quarkus introduces an experimental Dev Services For Keycloak
feature which is enabled by default when the quarkus-oidc
extension is started in dev mode with mvn quarkus:dev
and when the integration tests are running in test mode, but only when no quarkus.oidc.auth-server-url
property is configured.
It starts a Keycloak container for both the dev and/or test modes and initializes them by registering the existing Keycloak realm or creating a new realm with the client and users for you to start developing your Quarkus application secured by Keycloak immediately. It will restart the container when the application.properties
or the realm file changes have been detected.
Additionally, Dev UI available at /q/dev 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 will be activated, please see Dev UI for all OpenId Connect Providers for more information.
Dev Services for Keycloak
Start your application without configuring quarkus.oidc
properties in application.properties
. You will see in the console something similar to:
$ mvn quarkus:dev
2021-06-04 16:22:47,175 INFO [🐳 .io/keycloak/keycloak:14.0.0]] (build-38) Creating container for image: quay.io/keycloak/keycloak:14.0.0
2021-06-04 16:22:47,243 INFO [🐳 .io/keycloak/keycloak:14.0.0]] (build-38) Starting container with ID: 6469f6db9cec2c855fcc6c8db4273944cc9d69e8f6803a0b47eb2d5b8f5b94fd
2021-06-04 16:22:47,629 INFO [🐳 .io/keycloak/keycloak:14.0.0]] (build-38) Container quay.io/keycloak/keycloak:14.0.0 is starting: 6469f6db9cec2c855fcc6c8db4273944cc9d69e8f6803a0b47eb2d5b8f5b94fd
2021-06-04 16:22:47,643 INFO [org.tes.con.wai.str.HttpWaitStrategy] (build-38) /elastic_lovelace: Waiting for 60 seconds for URL: http://localhost:32812/auth (where port 32812 maps to container port 8080)
2021-06-04 16:23:07,665 INFO [🐳 .io/keycloak/keycloak:14.0.0]] (build-38) Container quay.io/keycloak/keycloak:14.0.0 started in PT5.500489S
2021-06-04 16:23:07,666 INFO [io.qua.oid.dep.dev.key.KeycloakDevServicesProcessor] (build-38) Dev Services for Keycloak started.
...
The quay.io/keycloak/keycloak:14.0.0
Keycloak image is used by default to start a container. quarkus.keycloak.devservices.image-name
can be used to change the Keycloak image used.
Note that by default, Dev Services for Keycloak
will not start a new container if it finds a container with a quarkus-dev-service-keycloak
label and connect to it if this label’s value matches the value of the quarkus.keycloak.devservces.service-name
property (default value is quarkus
). In such cases you will see a slighty different output:
$ mvn quarkus:dev
2021-08-27 18:42:43,530 INFO [io.qua.dev.com.ContainerLocator] (build-15) Dev Services container found: 48fee151a31ddfe32c39965be8f61108587b25ed2f66cdc18bb926d9e2e570c5 (quay.io/keycloak/keycloak:14.0.0). Connecting to: 0.0.0.0:32797.
2021-08-27 18:42:43,600 INFO [io.qua.oid.dep.dev.key.KeycloakDevServicesProcessor] (build-15) Dev Services for Keycloak started.
...
Note that you can disable sharing the containers with quarkus.keycloak.devservices.shared=false
.
Now open the main Dev UI page and you will see the OpenId Connect Card
linking to a Keycloak
page:

Click on the Provider: Keycloak
link and you will see a Keycloak page which will be presented slightly differently depending on how Dev Services for Keycloak
feature has been configured.
Developing Service Applications
By default the Keycloak page can be used to support the development of a Quarkus OIDC service application.
Authorization Code Grant
If you set quarkus.keycloak.devservices.grant.type=code
in applicatin.properties
(this is a default value) then an authorization_code
grant will be used to acquire both access and ID tokens. Using this grant is recommended to emulate a typical flow where a Single Page Application
acquires the tokens and uses them to access Quarkus services.
First you will see an option to Log into Single Page Application
:

Next, after you select this option, you will be redirected to Keycloak to authenticate, example, as alice:alice
and then returned to the page representing the SPA:

You can view the acquired access and ID tokens, for example:

This view shows the encoded JWT token on the left hand side and highlights the headers (red colour), payload/claims (green colour) and signature (blue colour). It also shows the decoded JWT token on the right hand side where you can see the header and claim names and their values.
Next test the service with either the current access or ID token. SPA usually sends the access tokens to the application endpoints but there could be cases where the ID tokens are forwarded to the application frontends for them to be aware about the user who is currently logged into SPA.
Finally you can select a Log Out
image::dev-ui-keycloak-logout.png option if you’d like to log out and authenticate to Keycloak as a different user.
Test with Swagger UI or GrapghQL UI
You can avoid manually entering the service paths and test your service with Swagger UI
or GraphQL UI
if quarkus-smallrye-openapi
and/or quarkus-smallrye-graphql
are used in your project. For example, if you run mvn quarkus-dev
with both quarkus-smallrye-openapi
and quarkus-smallrye-graphql
dependencies then you will see the following options after logging in into Keycloak:

For example, clicking on Swagger UI
will open Swagger UI
in a new browser tab where you can test the service using the token acquired by Dev UI for Keycloak.
and Swagger UI
will not try to re-authenticate again.
Integration with GraphQL UI
works in a similar way, the access token acquired by Dev UI for Keycloak will be used.
You may need to register a redirect URI for the authorization code flow initiated by Dev UI for Keycloak to work because Keycloak may enforce that the authenticated users are redirected only to the configured redirect URI. It is recommended to do in production to avoid the users being redirected to the wrong endpoints which might happen if the correct If Keycloak does enforce it then you will see an authentication error informing you that the In this case select the If the container is shared between multiple applications running on different ports then you will need to register You can set the
|
Implicit Grant
If you set quarkus.keycloak.devservices.grant.type=implicit
in applicatin.properties
then an implicit
grant will be used to acquire both access and ID tokens. Use this grant for emulating a Single Page Application
only if the authorization code grant does not work (for example, a client is configured in Keycloak to support an implicit grant, etc).
Password Grant
If you set quarkus.keycloak.devservices.grant.type=password
in applicatin.properties
then you will see a screen like this one:

Enter a registered user name, a relative service endpoint path, click on Test Service
and you will see a status code such as 200
, 403
, 401
or 404
printed.
You will also see in the Dev UI console something similar to:
2021-07-19 17:58:11,407 INFO [io.qua.oid.dep.dev.key.KeycloakDevConsolePostHandler] (security-openid-connect-quickstart-dev.jar) (DEV Console action) Using password grant to get a token from 'http://localhost:32818/auth/realms/quarkus/protocol/openid-connect/token' for user 'alice' in realm 'quarkus' with client id 'quarkus-app'
2021-07-19 17:58:11,533 INFO [io.qua.oid.dep.dev.key.KeycloakDevConsolePostHandler] (security-openid-connect-quickstart-dev.jar) (DEV Console action) Test token: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ6Z2tDazJQZ1JaYnVlVG5kcTFKSW1sVnNoZ2hhbWhtbnBNcXU0QUt5MnJBIn0.ey...
2021-07-19 17:58:11,536 INFO [io.qua.oid.dep.dev.key.KeycloakDevConsolePostHandler] (security-openid-connect-quickstart-dev.jar) (DEV Console action) Sending token to 'http://localhost:8080/api/admin'
2021-07-19 17:58:11,674 INFO [io.qua.oid.dep.dev.key.KeycloakDevConsolePostHandler] (security-openid-connect-quickstart-dev.jar) (DEV Console action) Result: 200
A token is acquired from Keycloak using a password
grant and is sent to the service endpoint.
Developing OpenId Connect Web App Applications
If you develop a Quarkus OIDC web-app application then you should set quarkus.oidc.application-type=web-app
in application.properties
before starting the application.
You will see a screen like this one:

Set a relative service endpoint path, click on Sign In To Service
and you will be redirected to Keycloak to enter a username and password in a new browser tab and get a response from the Quarkus application.
Running the tests
You can run the tests against a Keycloak container started in a test mode in a Continuous Testing mode.
It is also recommended to run the integration tests against Keycloak using Dev Services for Keycloak
.
Please see Testing OpenId Connect Service Applications with Dev Services and Testing OpenId Connect WebApp Applications with Dev Services for more information.
Keycloak Initialization
You do not need to configure quarkus-oidc-keycloak
to start developing your Quarkus Keycloak OIDC
applications with the only exception being that quarkus.oidc.application-type=web-app
has to be set in application.properties
to give the Keycloak
page a hint it needs to show an option to Sign In To Service
.
By default, the quarkus
, quarkus-app
client with a secret
password, alice
and bob
users (with the passwords matching the names), and user
and admin
roles are created, with alice
given both admin
and user
roles and bob
- the user
role.
Usernames, secrets and their roles can be customized with quarkus.keycloak.devservices.users
(the map which contains usernames and secrets) and quarkus.keycloak.devservices.roles
(the map which contains user names and comma separated role values).
quarkus.oidc.client-id
and quarkus.oidc.credentials.secret
can be used to customize the client id and secret.
However it is likely your Keycloak configuration may be more complex and require setting more properties.
This is why quarkus.keycloak.devservices.realm-path
is always checked first before trying to initialize Keycloak with the default or configured realm, client, user and roles properties. If the realm file exists on the file system or classpath then only this realm will be used to initialize Keycloak.
Also the Keycloak page offers an option to Sign In To Keycloak To Configure Realms
using a Keycloak Admin
option in the right top corner:

Sign in to Keycloak as admin:admin
in order to further customize the realm properties or create a new realm, export the realm and have Keycloak initialized with the custom realm after a restart.
Note that even if you initialize Keycloak from a realm file, it is still needed to set the quarkus.keycloak.devservices.realm-name
property for quarkus.oidc.auth-server-url
to be calculated correctly. Setting the quarkus.keycloak.devservices.users
property is needed if a password
grant is used to acquire the tokens to test the OIDC service
applications.
Disable Dev Services for Keycloak
Dev Services For Keycloak
will not be activated if either quarkus.oidc.auth-server-url
is already initialized or the defaut OIDC tenant is disabled with quarkus.oidc.tenant.enabled=false
, irrespectively of whether you work with Keycloak or not.
If you prefer not to have a Dev Services for Keycloak
container started or do not work with Keycloak then you can also disable this feature with quarkus.keycloak.devservices.enabled=false
- it will only be necessary if you expect to start quarkus:dev
without quarkus.oidc.auth-server-url
.
The main Dev UI page will include an empty OpenId Connect Card
when Dev Services for Keycloak
is disabled and the quarkus.oidc.auth-server-url
property
has not been initialized:

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 may be activated, please see Dev UI for all OpenId Connect Providers for more information.
Dev UI for all OpenId Connect Providers
If quarkus.oidc.auth-server-url
points to an already started OpenId Connect provider (which can be Keycloak or other provider), quarkus.oidc.auth-server-url
is set to service
(which is a default value) and at least quarkus.oidc.client-id
is set then Dev UI for all OpenId Connect Providers
will be activated.
Setting quarkus.oidc.credentials.secret
will mostly likely be required for Keycloak and other providers for the authorization code flow initiated from Dev UI to complete, unless the client identified with quarkus.oidc.client-id
is configured as a public client in your OpenId Connect provider’s administration console.
Run mvn`quarkus:dev
and you will see the following message:
$ mvn quarkus:dev
...
2021-09-07 15:53:42,697 INFO [io.qua.oid.dep.dev.OidcDevConsoleProcessor] (build-41) OIDC Dev Console: discovering the provider metadata at http://localhost:8180/auth/realms/quarkus/.well-known/openid-configuration
...
If the provider metadata discovery has been successful then, after you open the main Dev UI page, you will see the OpenId Connect Card
page linking to Dev Console
:

Follow the link and you’ll be able log in to your provider, get the tokens and test the application. The experience will be the same as described in the Authorization Code Grant for Keycloak section, where Dev Services for Keycloak
container has been started, especially if you work with Keycloak (please also pay attention to a redirect_uri
note in that section).
If you work with other providers then a Dev UI experience described in the Authorization Code Grant for Keycloak section might differ slightly. For example, an access token may not be in a JWT format so it won’t be possibe to show its internal content, though all providers should return an ID Token as JWT.
Some providers such as Auth0
do not support a standard RP initiated logout so a logout option will also be hidden.
At the moment Dev UI for all OpenId Connect Providers
only supports an authorization code grant. More grants may be supported in the future, similarly to how it is done with Dev Services for Keycloak
.
Dev Services and UI Support for other OpenId Connect Providers
Your custom extension would need to extend quarkus-oidc
and add the dependencies required to support your provider to the extension’s deployment
module only.
The build step dealing with the Dev Services
should additionally register two runtime properties into the "io.quarkus.quarkus-oidc" namespace: oidcProviderName
(for example, Google
) and oidcProviderUrlBase
(for example: mycompany.devservices-google
) for the OpenId Connect Card
to link to the Dev UI page representing your provider, for example:
package io.quarkus.oidc.okta.runtime;
import java.util.function.Supplier;
import io.quarkus.runtime.annotations.Recorder;
// This simple recorder is the only code which will be located in the extension's `runtime` module
@Recorder
public class OktaDevServicesRecorder {
public Supplier<String> getProviderName() {
return new Supplier<String>() {
@Override
public String get() {
return "OKTA";
}
};
}
public Supplier<String> getProviderUrlBase() {
return new Supplier<String>() {
@Override
public String get() {
return "io.quarkus" + "." + "quarkus-oidc-okta";
}
};
}
}
package io.quarkus.oidc.okta.deployment.devservices;
import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;
import java.util.Optional;
import io.quarkus.deployment.IsDevelopment;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.Consume;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.RuntimeConfigSetupCompleteBuildItem;
import io.quarkus.devconsole.spi.DevConsoleRouteBuildItem;
import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem;
public class OktaDevConsoleProcessor {
@BuildStep(onlyIf = IsDevelopment.class)
@Record(value = RUNTIME_INIT)
public void setOidcProviderProperties(BuildProducer<DevConsoleRuntimeTemplateInfoBuildItem> provider,
OktaDevServicesRecorder recorder,
Optional<DevServicesConfigBuildItem> configProps) {
if (configProps.isPresent()) {
provider.produce(new DevConsoleRuntimeTemplateInfoBuildItem("io.quarkus", "quarkus-oidc", "oidcProviderName",
recorder.getProviderName()));
provider.produce(new DevConsoleRuntimeTemplateInfoBuildItem("io.quarkus", "quarkus-oidc", "oidcProviderUrlBase",
recorder.getProviderUrlBase()));
}
}
}
Additionally, the extension should produce a io.quarkus.oidc.deployment.devservices.OidcProviderBuildItem
to disable the default Dev Services for Keycloak
, instead of the users having to type quarkus.keycloak.devservices.enabled=false
.
Please follow the Dev UI tutorial as well as check the extensions/oidc/deployment
sources for more ideas.