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

OpenID Connect (OIDC) の開発サービスと UI

このガイドでは、OpenID Connect(OIDC)のKeycloakプロバイダのDev ServicesとUIを取り上げ、他のOpenID ConnectプロバイダのDevサービスとUIをサポートする方法について説明します。また、Quarkusを開発モードで起動する前にすでに開始されているすべてのOpenID ConnectプロバイダのDev UIについても説明しています。

はじめに

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

さらに、 /q/dev で入手可能な Dev UI は、Dev UI ページでこの機能を補完します。これは、Keycloak からトークンを取得して Quarkus アプリケーションをテストする際に役立ちます。

quarkus.oidc.auth-server-url がすでに設定されている場合は、すべての OpenIDConnect プロバイダーで使用できる汎用 OpenIDConnectDevConsole がアクティブ化されます。詳細は Dev UI for all OpenID Connect Providers を参照してください。

Dev Services for Keycloak

次のコマンドを使用して、application.propertiesquarkus.oidc プロパティーを設定せずにアプリケーションを起動します。

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

コンソールには以下のように表示されます。

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.

Keycloak 管理コンソールにログインする場合、ユーザー名は admin、パスワードは admin です。

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.devservices.service-name property (default value is quarkus). In such cases you will see a slightly different output when running:

CLI
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: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.
...

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:

Dev

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.

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

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

認可コード グラント

application.propertiesquarkus.oidc.devui.grant.type=code (デフォルト値) を設定すると、authorization_code 許可を使用してアクセストークンと ID トークンの両方が取得されます。この許可を使用して、Single Page Application がトークンを取得し、それらを使用して Quarkus サービスにアクセスする一般的なフローをエミュレートすることをお勧めします。

まず、Log into Single Page Application オプションが表示されます。

Dev

次に、このオプションを選択すると Keycloak にリダイレクトされ、たとえば alice:alice として認証され、SPA 表示ページに戻ります。

Dev

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

Dev

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.

次に、現在のアクセスまたは ID トークンを使用してサービスをテストします。SPA は通常、アクセストークンをアプリケーションエンドポイントに送信しますが、ID トークンがアプリケーションフロントエンドに転送され、現在 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.

シングルページアプリケーションにログインしようとすると、Keycloak がエラーを返す場合があることに注意してください。たとえば、quarkus.oidc.client-id が Keycloak にインポートされたレルムのクライアント ID と一致しない場合や、このレルムのクライアントが認証コードフローをサポートするように正しく設定されていない場合などです。このような場合、Keycloak は error_description クエリーパラメーターと DevUI も、このエラーの説明を表示します。以下はその例です。

Dev

If the error occurs then log into Keycloak using the Keycloak Admin option and update the realm configuration as necessary and also check the application.properties.

Test with Swagger UI or GraphQL UI

プロジェクトで quarkus-smallrye-openapiquarkus-smallrye-graphql が使用されている場合、サービスパスを手動で入力することを避け、Swagger UI または GraphQL UI を使用してサービスをテストできます。たとえば、quarkus-smallrye-openapiquarkus-smallrye-graphql の両方の依存関係を使用して開発モードで Quarkus を起動すると、Keycloak にログインした後に次のオプションが表示されます。

テスト

たとえば、Swagger UI をクリックすると、新しいブラウザータブで Swagger UI が開き、Dev UI for Keycloak によって取得されたトークンを使用してサービスをテストできます。また、`Swagger UI`は再認証を試みません。

GraphQL UI との統合も同様に機能し、Keycloak 用に Dev UI によって取得されたアクセストークンが使用されます。

Keycloak は、認証されたユーザーが設定されたリダイレクト URI にのみリダイレクトされるように強制する場合があるため、Keycloak が機能するためには Dev UI によって開始される認証コードフローのリダイレクト URI を登録する必要がある場合があります。認証要求内の正しい redirect_uri パラメーターが操作されると、ユーザーが間違ったエンドポイントにリダイレクトされる可能性があるため、本番環境ではこれを行うことを推奨します。

Keycloak がそれを強制する場合は、redirect_uri 値が間違っていることを通知する認証エラーが表示されます。

この場合、右上隅の Keycloak Admin オプションを選択し、admin:admin としてログインし、Dev UI for Keycloak が設定されているテストレルムとクライアントを選択して、Valid Redirect URIshttp://localhost:8080/q/dev/io.quarkus.quarkus-oidc/provider を追加します。Quarkus の起動に -Dquarkus.http.port を使用した場合は、8080quarkus.http.port の値に変更します。

コンテナーが異なるポートで実行されている複数のアプリケーション間で共有されている場合は、これらのアプリケーションごとに redirect_uri 値を登録する必要があります。

特にコンテナーが複数のアプリケーション間で共有されている場合は、テスト目的でのみ redirect_uri 値を * に設定できます。

カスタムレルムがインポートされていない場合、* redirect_uri の値はデフォルトのレルムを作成するときに`Dev Services for Keycloak`によって設定されます。

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

application.propertiesquarkus.oidc.devui.grant.type=implicit を設定すると、アクセストークンと ID トークンの両方を取得するために implicit グラントが使用されます。認証コードグラントが機能しない場合に限り (暗示的グラントをサポートするためにクライントが Keycloak に設定されている場合など)、このグラントを使用して Single Page Application をエミュレートします。

パスワード・グラント

application.propertiesquarkus.oidc.devui.grant.type=password を設定すると、次のような画面が表示されます。

Dev

Enter a registered username, user password, a relative service endpoint path, click on Test Service and you will see a status code such as 200, 403, 401 or 404 printed. If the username is also set in quarkus.keycloak.devservices.users map property containing usernames and passwords then you do not have to set a password when testing the service. But note, you do not have to initialize quarkus.keycloak.devservices.users to test the service using the password grant.

また、Dev UI コンソールには以下のように表示されます。

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

トークンは password グラントを使用して Keycloak から取得され、サービスエンドポイントに送信されます。

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

quarkus.oidc.devui.grant.type=client を設定すると、トークンの取得に client_credentials グラントが使用されます。この場合、ページに User フィールドは表示されません。

Dev

Password グラントと同じ方法でサービスをテストできます。

OpenID Connect Web App アプリケーションの開発

Quarkus OIDC web-app アプリケーション を開発する場合は、アプリケーションを開始する前に application.propertiesquarkus.oidc.application-type=web-app を設定する必要があります。

次のような画面が表示されます。

Dev

相対的なサービスエンドポイントパスを設定し、Sign In To Service をクリックすると Keycloak にリダイレクトされます。新しいブラウザータブにユーザー名とパスワードを入力し、Quarkus アプリケーションからレスポンスを取得します。

この場合、Dev UI は認証コードフローを制御してトークンを取得する Quarkus OIDC の web-app アプリケーションであるため、開発エクスペリエンスを充実させるものではないことに注意してください。

Dev UI が OIDC web-app アプリケーションの開発をより便利にサポートできるようにするために、quarkus.oidc.application-type のプロファイル固有値を設定することを検討してください。

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

It will ensure that all Dev UI options described in Developing OpenID Connect Service Applications will be 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 will be sent to the endpoint as HTTP Bearer tokens - which will not work well if your endpoint requires the injection of IdToken. However, it will work 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.

テストの実行

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

また、Dev Services for Keycloak を使用して、Keycloak に対して統合テストを実行することをお勧めします。詳細は、Dev Services を使用した OpenID Connect サービスアプリケーションのテスト および Dev Services を使用した OpenID Connect WebApp アプリケーションのテスト を参照してください。

Keycloak の初期化

Quarkus を利用した Keycloak ディストリビューションを含む quay.io/keycloak/keycloak:17.0.0 イメージは、デフォルトでコンテナーを起動するために使用されます。quarkus.keycloak.devservices.image-name を使用して、Keycloak イメージ名を変更できます。たとえば、WildFly を利用した Keycloak ディストリビューションを使用するには、これを quay.io/keycloak/keycloak:17.0.0-legacy に設定します。

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

デフォルトでは、quarkussecret パスワードを持つ quarkus-app クライアント、alice および bob ユーザー (名前と一致するパスワードを持つ)、user および admin ロールが作成されます。このとき、alice には adminuser の両方のロールが与えられ、bob には `user`のロールが与えられます。

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

quarkus.oidc.client-idquarkus.oidc.credentials.secret を使用して、クライアント ID とシークレットをカスタマイズできます。

However, it is likely your Keycloak configuration may be more complex and require setting more properties.

これが、デフォルトまたは設定されたレルム、クライアント、ユーザー、およびロールのプロパティーを使用して Keycloak を初期化する前に、quarkus.keycloak.devservices.realm-path が常に最初にチェックされる理由です。レルムファイルがファイルシステムまたはクラスパスに存在する場合、このレルムのみが 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:

Dev

レルムのプロパティーのカスタマイズ、新規レルムの作成またはインポート、レルムのエクスポートを実行するには、Keycloak に admin:admin としてサインインします。

レルムファイルから Keycloak を初期化する場合でも、トークンを取得して OIDC service アプリケーションをテストするために password グラントが使用される場合は、quarkus.keycloak.devservices.users プロパティーを設定する必要があることに注意してください。

Dev Services for Keycloak の無効化

quarkus.oidc.auth-server-url がすでに初期化されているか、デフォルトの OIDC テナントが quarkus.oidc.tenant.enabled=false で無効になっている場合、Keycloak を使用するかどうかにかかわらず、Dev Services ForKeycloak はアクティブ化されません。

Dev Services for Keycloak コンテナーを起動させない、または使用しない場合も、quarkus.keycloak.devservices.enabled=false を使用してこの機能を無効化できます。これは、quarkus.oidc.auth-server-url なしで quarkus:dev を起動する予定がある場合にのみ必要です。

Dev Services for Keycloak が無効で quarkus.oidc.auth-server-url プロパティーが初期化されていない場合、メインの Dev UI ページには空の OpenIDConnectCard が含まれます。

Dev

quarkus.oidc.auth-server-url がすでに設定されている場合は、すべての OpenIDConnect プロバイダーで使用できる汎用 OpenIDConnectDevConsole をアクティブ化できます。詳細は Dev UI for all OpenID Connect Providers を参照してください。

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

quarkus.oidc.auth-server-url が、すでに起動されている OpenID Connect プロバイダー (Keycloak または他のプロバイダーも可) を指し、quarkus.oidc.auth-server-urlservice (デフォルト値) に設定され、少なくとも quarkus.oidc.client-id が設定されている場合、すべての OpenID Connect プロバイダーの Dev UI (Dev UI for all OpenID Connect Providers) がアクティブになります。

Keycloak や その他のプロバイダーでは、quarkus.oidc.client-id で指定されたクライアントが使用している OpenID Connect プロバイダーの管理コンソールでパブリッククライアントとして設定されていない限り、Dev UI から開始された認可コードフローを完了するには`quarkus.oidc.credentials.secret` の設定が必要です。

実行:

CLI
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

以下のメッセージが表示されます。

...
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/realms/quarkus/.well-known/openid-configuration
...

プロバイダーメタデータの検出が成功した場合、メインの Dev UI ページ を開くと、Dev Console にリンクされた OpenID Connect Card ページが表示されます。

ジェネリック

Follow the link, and you will be able to 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.

You will most likely need to configure your OpenId Connect provider to support redirecting back to the Dev Console. Add http://localhost:8080/q/dev/io.quarkus.quarkus-oidc/provider as one of the supported redirect and logout URLs.

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 possible to show its internal content, though all providers should return an ID Token as JWT.

デフォルトでは、現在のアクセストークンを使用して、Swagger UI または GrapghQL UI でサービスをテストします。プロバイダー (Keycloak 以外) がバイナリーアクセストークンを返す場合、このプロバイダーにトークンイントロスペクションエンドポイントがある場合にのみ Swagger UI または GrapghQL UI で使用されます。それ以外の場合は、常に JWT 形式の IdTokenSwagger UI または GrapghQL UI に渡されます。このような場合、手動の Dev UI テストで、現在のバイナリーアクセストークンに対して常に 401 が返されることを確認できます。また、これらの UI のいずれかでフォールバックとして Id Token を使用することは、認可コードフローでのみ可能であることに注意してください。

Some providers such as Auth0 do not support a standard RP initiated logout so the provider specific logout properties will have to be configured for a logout option be visible, please see OpenID Connect User-Initiated Logout for more information.

同様に、Dev UI に password または client_credentials グラントを使用してトークンを取得する場合は、次のような追加のプロバイダー固有プロパティーを設定する必要があります。

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

その他の OpenID Connect プロバイダーの Dev Services と UI サポート

カスタムエクステンションは、quarkus-oidc を拡張し、プロバイダーをサポートするために必要な依存関係をエクステンションの deployment モジュールにのみ追加する必要があります。

Dev Services を処理するビルドステップでは、OpenID Connect Card をプロバイダーを示す Dev UI ページにリンクするために、2 つのランタイムプロパティーを "io.quarkus.quarkus-oidc" 名前空間に追加で登録する必要があります: oidcProviderName (例: Google) と oidcProviderUrlBase (例: mycompany.devservices-google)。

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()));
        }
    }
}

さらに、ユーザーが quarkus.keycloak.devservices.enabled=false を入力するのではなく、エクステンションが io.quarkus.oidc.deployment.devservices.OidcProviderBuildItem を生成してデフォルトの Dev Services for Keycloak を無効にする必要があります。

Dev UI チュートリアルと extensions/oidc/deployment ソースで他のアイデアも確認してください。

アプリケーション以外のルートパスに関する考慮事項

このドキュメントでは、繰り返し http://localhost:8080/q/dev Dev UI URL を参照していますが、この q はデフォルトの非アプリケーションルートパスです。quarkus.http.root-pathquarkus.http.non-application-root-path プロパティーをカスタマイズした場合、q を適宜置き換えてください。詳細については、 Quarkus を使用したパスの解決 を参照してください。