The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

OpenID Connect (OIDC)のDev ServicesとDev UI

You can use Dev Services for Keycloak and the Dev UI for the OpenID Connect (OIDC) Keycloak provider and adapt these services for other OpenID Connect providers. You can also use the Dev UI with OpenID Connect providers that have already been started before you run Quarkus in development mode.

はじめに

Quarkusには、Dev Services for Keycloak機能があります。この機能は、 quarkus-oidc エクステンションがdevモードで開始され、結合テストがtestモードで実行され、 quarkus.oidc.auth-server-url プロパティが設定されていない場合にデフォルトで有効になります。 Dev Services for Keycloak機能は、devモードとtestモードの両方でKeycloakコンテナを起動します。 既存のKeycloakレルムを登録するか、Keycloakでセキュリティ保護されたQuarkusアプリケーションの開発をすぐに開始するために必要なクライアントとユーザーを含む新しいレルムを作成することで、これらのレルムを初期化します。 application.properties 、あるいはレルムファイルの変更が検出されると、コンテナは再起動します。

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, is activated. For more information, see Dev UI for all OpenID Connect providers.

Dev Services for Keycloak

Start your application without configuring quarkus.oidc properties in the application.properties file:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

The console displays output similar to this:

KeyCloak Dev Services Starting:
2021-11-02 17:14:24,864 INFO  [org.tes.con.wai.str.HttpWaitStrategy] (build-10) /unruffled_agnesi: Waiting for 60 seconds for URL: http://localhost:32781 (where port 32781 maps to container port 8080)
2021-11-02 17:14:44,170 INFO  [io.qua.oid.dep.dev.key.KeycloakDevServicesProcessor] (build-10) Dev Services for Keycloak started.

When logging in to the Keycloak admin console, the username is admin, and the password is admin.

Be aware that Dev Services for Keycloak defaults to not initiating a new container if it detects an existing container labeled quarkus-dev-service-keycloak. It connects to this container provided the value of the quarkus.keycloak.devservices.service-name property matches the label’s value (default quarkus). In such cases, expect a slightly altered output when you run the following:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev
2021-08-27 18:42:43,530 INFO  [io.qua.dev.com.ContainerLocator] (build-15) Dev Services container found: 48fee151a31ddfe32c39965be8f61108587b25ed2f66cdc18bb926d9e2e570c5 (quay.io/keycloak/keycloak:21.0.2). 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.
...

If the Keycloak container is not ready within the default 60-second timeout, you can resolve this by extending the timeout period. For instance, set it to 2 minutes with quarkus.devservices.timeout=2M.

You can turn off sharing of the containers by specifying quarkus.keycloak.devservices.shared=false.

Now, open the main Dev UI page and observe the OpenID Connect card linking to a Keycloak page. For example:

Dev UI OpenID Connect card

Click the Keycloak provider link. This action opens a Keycloak page whose appearance varies depending on how the Dev Services for Keycloak feature is configured.

サービスアプリケーションの開発

By default, the Keycloak page can be used to support the development of a Quarkus OIDC service application.

認可コード グラント

If you set quarkus.oidc.devui.grant.type=code in the application.properties file (this is a default value), then an authorization_code grant is used to acquire both access and ID tokens. Using this grant is recommended to emulate a typical flow where a single page application (SPA) acquires the tokens and uses them to access Quarkus services.

First, you see an option to Log into Single Page Application. For example:

Dev UI OpenID Connect Keycloak Page - Log into Single Page Application

Choose the Keycloak realm and client ID to use during the authentication process.

This SPA represents a public OpenID Connect client; therefore, the client IDs you enter must identify public Keycloak clients that have no secrets. This is because SPA is not a web application and cannot securely handle the secrets it needs to complete the authorization code flow if the client secret is also expected to complete the authorization code flow.

The clients requiring secrets can only be supported with this SPA if a default realm has been created or if quarkus.oidc.credentials.secret is configured and a single custom realm is used. In both cases, the SPA can figure out the client secret it might need to complete the authorization code flow after Keycloak redirects the user back to it.

Next, after selecting Log into Single Page Application, you are redirected to Keycloak to authenticate, for example, as alice:alice. Then, you are returned to the page representing the SPA:

Dev UI OpenID Connect Keycloak Single Page Application

取得したアクセストークンやIDトークンなどを確認することができます。

Dev UI OpenID Connect Keycloak Decoded Tokens View

This view shows the encoded JSON Web Token (JWT) token on the left side and highlights the headers in red, payload or claims in green, and signature in blue. It also shows the decoded JWT token on the right side, where you can see the header, claim names, and their values.

Next, test the service by entering a relative service path and sending a token. SPA usually sends access tokens to the application endpoint, so choose the With Access Token option, for example:

Dev UI Keycloak - With Access Token

To clear the test results area, use the eraser icon in the lower right corner.

Sometimes, ID tokens are forwarded to application frontends as bearer tokens. This helps endpoints identify the user logged into SPA or perform out-of-band token verification. Choose the With ID Token option in such cases.

Manually entering the service paths is not ideal. For information about enabling Swagger or GraphQL UI for testing the service with the access token already acquired by the OIDC Dev UI, see the Test with Swagger UI or GraphQL UI section.

Finally, you can click Log Out image::dev-ui-keycloak-logout.png[alt=Dev UI Keycloak - Log Out,role="center"] so you can authenticate to Keycloak as a different user.

Keycloak might return an error when you try to Log into Single Page Application. For example, quarkus.oidc.client-id might not match the client ID in the realm imported to Keycloak, or the client in this realm might not be configured correctly to support the authorization code flow. In such cases, Keycloak returns an error_description query parameter, and the Dev UI also shows this error description. For example:

Dev UI Keycloak Login Error

If the error occurs, log in to Keycloak by using the Keycloak Admin option, update the realm configuration as necessary, and check the application.properties.

Swagger UI または GraphQL UI を使用したテスト

You can avoid manually entering the service paths and test your service with Swagger UI or GraphQL UI if quarkus-smallrye-openapi or quarkus-smallrye-graphql are used in your project. For example, start Quarkus in dev mode with both quarkus-smallrye-openapi and quarkus-smallrye-graphql dependencies. You can see the following options after logging in to Keycloak:

Test your service with Swagger UI or GraphQL UI

For example, clicking Swagger UI opens the Swagger UI in a new browser tab where you can test the service by using the token acquired by Dev UI for Keycloak. The Swagger UI does not try to re-authenticate again. In the Swagger UI, do not choose a Swagger UI Authorize option; the OIDC Dev UI has authorized and provided the access token for Swagger UI to use for testing.

Integration with GraphQL UI works similarly; the access token acquired by Dev UI for Keycloak is used.

You might need to register a redirect URI for the authorization code flow initiated by Dev UI for Keycloak to work. This is because Keycloak might enforce that the authenticated users are redirected only to the configured redirect URI. It is recommended to do this in production to avoid the users being redirected to the wrong endpoints, which might happen if the correct redirect_uri parameter in the authentication request URI has been manipulated.

If Keycloak enforces it, you see an authentication error informing you that the redirect_uri value is wrong.

In this case, select the Keycloak Admin option in the top right corner, login as admin:admin, select the test realm and the client which Dev UI for Keycloak is configured with, and add http://localhost:8080/q/dev-ui/io.quarkus.quarkus-oidc/keycloak-provider to Valid Redirect URIs. If you used -Dquarkus.http.port when starting Quarkus, then change 8080 to the value of quarkus.http.port

If the container is shared between multiple applications running on different ports, you must register redirect_uri values for each application.

You can set the redirect_uri value to * only for test purposes, especially when the containers are shared between multiple applications.

If no custom realm is imported, Dev Services for Keycloak sets the redirect_uri value to * when it creates a default realm.

インプリシット・グラント

If you set quarkus.oidc.devui.grant.type=implicit in the application.properties file, then an implicit grant is used to acquire both access and ID tokens. Use this grant to emulate a single page application only if the authorization code grant does not work; for example, when a client is configured in Keycloak to support an implicit grant.

パスワード・グラント

If you set quarkus.oidc.devui.grant.type=password in the application.properties file, then you see a screen similar to this one:

Dev UI OpenID Connect Keycloak Page - Password Grant

Select a realm, enter a client ID and secret, user name and password, a relative service endpoint path, and click Test service. It returns a status code, such as 200, 403, 401, or 404. If the username is also set in the quarkus.keycloak.devservices.users map property containing usernames and passwords, then you do not have to set a password when testing the service. Be aware that you do not have to initialize quarkus.keycloak.devservices.users to test the service by using the password grant.

In the Dev UI console, you can also see output similar to the following:

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/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 by using a password grant and is sent to the service endpoint.

クライアントクレデンシャル・グラント

If you set quarkus.oidc.devui.grant.type=client, then a client_credentials grant is used to acquire a token, with the page showing no User field in this case:

Dev UI OpenID Connect Keycloak Page - Client Credentials Grant

Select a realm, enter the client ID and secret, a relative service endpoint path, and click Test service. It returns a status code, such as 200, 403, 401, or 404.

OpenID Connectウェブアプリケーション開発

Quarkus OIDCウェブアプリケーション を開発するには、アプリケーションを開始する前に、 application.properties ファイルで quarkus.oidc.application-type=web-app を設定します。

アプリケーションを起動すると、このような画面が表示されます:

Dev UI OpenID Connect Keycloak Sign In

Set a relative service endpoint path and click Log in to your web application. You are redirected to Keycloak to enter a username and password in a new browser tab before you get a response from the Quarkus application.

In this case, the Dev UI is not very helpful because the Quarkus OIDC web-app application controls the authorization code flow and acquires the tokens.

To make Dev UI more helpful in supporting the development of OIDC web-app applications, consider setting profile-specific values for quarkus.oidc.application-type:

%prod.quarkus.oidc.application-type=web-app
%test.quarkus.oidc.application-type=web-app
%dev.quarkus.oidc.application-type=service

This profile ensures that all Dev UI options described in Developing service applications are available when your web-app application is run in dev mode. The limitation of this approach is that both access and ID tokens returned with the code flow and acquired with Dev UI are sent to the endpoint as HTTP Bearer tokens - which does not work well if your endpoint requires the injection of IdToken. However, it works as expected if your web-app application only uses the access token, for example, as a source of roles or to get UserInfo, even if it is assumed to be a service application in dev mode.

For dev mode, an even better option is to set the application-type property to hybrid:

%prod.quarkus.oidc.application-type=web-app
%test.quarkus.oidc.application-type=web-app
%dev.quarkus.oidc.application-type=hybrid

This type ensures that if you access the application from the browser in dev mode without the OIDC Dev UI, Quarkus OIDC also performs the authorization code flow as in the production mode. The OIDC Dev UI is also more beneficial because hybrid applications can also accept the bearer access tokens.

テストの実行

テストモードで起動した Keycloak コンテナーに対して、継続テスト モードでテストを実行できます。

It is also recommended to run the integration tests against Keycloak by using Dev Services for Keycloak. For more information, see Testing OpenID Connect Service Applications with Dev Services and Testing OpenID Connect WebApp Applications with Dev Services.

Keycloak 初期化

The quay.io/keycloak/keycloak:23.0.7 image which contains a Keycloak distribution powered by Quarkus is used to start a container by default. quarkus.keycloak.devservices.image-name can be used to change the Keycloak image name. For example, set it to quay.io/keycloak/keycloak:19.0.3-legacy to use a Keycloak distribution powered by WildFly. Be aware that a Quarkus-based Keycloak distribution is only available starting from Keycloak 20.0.0.

Dev Services for Keycloakは、起動したKeycloakサーバーを次に初期化します。

By default, the quarkus and 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 usernames and comma-separated role values).

例えば、以下のようになります。

%dev.quarkus.keycloak.devservices.users.duke=dukePassword
%dev.quarkus.keycloak.devservices.roles.duke=reader
%dev.quarkus.keycloak.devservices.users.john=johnPassword
%dev.quarkus.keycloak.devservices.roles.john=reader,writer

この設定により、2人のユーザーが作成されます: * dukePassword パスワードと reader ロールを持つ duke * johnPassword パスワードと reader および writer ロールを持つ john

To customize the client ID and secret, you can use the quarkus.oidc.client-id and quarkus.oidc.credentials.secret properties.

However, it is likely that your Keycloak configuration is more complex and requires setting more properties.

This is why quarkus.keycloak.devservices.realm-path is always checked before initializing 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 is used to initialize Keycloak, for example:

quarkus.keycloak.devservices.realm-path=quarkus-realm.json

quarkus.keycloak.devservices.realm-path を使って、カンマで区切られたファイルのリストを提供することで、複数のレルムファイルでKeycloakを初期化することができます:

quarkus.keycloak.devservices.realm-path=quarkus-realm1.json,quarkus-realm2.json

Also, the Keycloak page offers an option to Sign In To Keycloak To Configure Realms by using a Keycloak Admin option in the right top corner:

Dev UI OpenID Connect Keycloak Page - Keycloak Admin

Sign in to Keycloak as admin:admin to further customize the realm properties, create or import a new realm, or export the realm.

You can also copy classpath and file system resources to the container. For example, if your application configures Keycloak authorization with JavaScript policies that are deployed to Keycloak in a jar file, then you can configure Dev Services for Keycloak to copy this jar to the Keycloak container as follows:

quarkus.keycloak.devservices.resource-aliases.policies=/policies.jar (1)
quarkus.keycloak.devservices.resource-mappings.policies=/opt/keycloak/providers/policies.jar (2)
1 policies alias is created for the classpath /policies.jar resource.

Policy jars can also be located in the file system. <2> The policies jar is mapped to the /opt/keycloak/providers/policies.jar container location.

Keycloak の Dev サービスを無効にする

Dev Services for Keycloak is not activated if either quarkus.oidc.auth-server-url is already initialized or the default OIDC tenant is disabled with quarkus.oidc.tenant.enabled=false, regardless 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 is only necessary if you expect to start quarkus:dev without quarkus.oidc.auth-server-url.

The main Dev UI page includes an empty OpenID Connect card when Dev Services for Keycloak is disabled and the quarkus.oidc.auth-server-url property has not been initialized:

Dev UI OpenID Connect card

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, can be activated. For more information, see the Dev UI for all OpenID Connect providers section.

すべてのOpenID ConnectプロバイダーのためのDev UI

以下の条件を満たす場合、すべての OpenID Connect プロバイダーの Dev UI が有効になります:

  • The quarkus.oidc.auth-server-url points to an already started OpenID Connect provider, which can be Keycloak or other provider.

  • The quarkus.oidc.auth-server-url is set to service, the default value, or hybrid.

  • The quarkus.oidc.client-id is set.

Setting quarkus.oidc.credentials.secret is most likely 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.

For example, you can use Dev UI to test Google authentication with this configuration:

quarkus.oidc.provider=google
quarkus.oidc.application-type=hybrid
quarkus.oidc.client-id=${google-client-id}
quarkus.oidc.credentials.secret=${google-client-secret}

実行:

コマンドラインインタフェース
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

This command outputs a message similar to the following example:

...
2021-09-07 15:53:42,697 INFO  [io.qua.oid.dep.dev.OidcDevConsoleProcessor] (build-41) OIDC Dev Console: discovering the provider metadata at https://accounts.google.com/.well-known/openid-configuration
...

If the provider metadata discovery has been successful, then after you open the main Dev UI page, you can see the following OpenID Connect card referencing a Google provider:

Generic Dev UI OpenID Connect card

Follow the link to log in to your provider, get the tokens, and test the application. The experience is the same as described in the Authorization code grant for Keycloak section, where the Dev Services for Keycloak container has been started, especially if you work with Keycloak.

You likely need to configure your OpenID Connect provider to support redirecting back to the Dev Console. You add http://localhost:8080/q/dev-ui/io.quarkus.quarkus-oidc/<providerName>-provider as one of the supported redirect and logout URLs, where <providerName> must be replaced by the name of the provider shown in the Dev UI, for example, auth0.

The Dev UI experience described in the Authorization code grant for Keycloak section might differ slightly if you work with other providers. For example, an access token might not be in JWT format, so it would not be possible to show its internal content. However, all providers should return ID tokens in the JWT format.

The current access token is used by default to test the service with Swagger UI or GrapghQL UI. If the provider (other than Keycloak) returns a binary access token, then it is used with Swagger UI or GrapghQL UI only if this provider has a token introspection endpoint; otherwise, an IdToken, which is always in a JWT format is passed to Swagger UI or GrapghQL UI. In such cases, you can verify with the manual Dev UI test that 401 is always returned for the current binary access token. Also, note that using IdToken as a fallback with either of these user interfaces is only possible with the authorization code flow.

Some providers, such as Auth0 do not support a standard RP-initiated logout, so the provider-specific logout properties must be configured for a logout option to be visible. For more information, see User-initiated logout section in the "OpenID Connect authorization code flow mechanism for protecting web applications" guide.

Similarly, if you want to use a password or client_credentials grant for Dev UI to acquire the tokens, then you might need to configure some extra provider-specific properties, for example:

quarkus.oidc.devui.grant.type=password
quarkus.oidc.devui.grant-options.password.audience=http://localhost:8080

Non-application root path considerations

This document refers to the http://localhost:8080/q/dev-ui Dev UI URL in several places where q is a default non-application root path. If you customize quarkus.http.root-path or quarkus.http.non-application-root-path properties, then replace q accordingly. For more information, see the Path resolution in Quarkus blog post.

関連コンテンツ