1. 概要

Keycloak は、当社のWebまたはモバイルアプリケーションのユーザーを管理するサードパーティの認証サーバーです。

これは、特定のユーザーに保存される名、姓、電子メールなどのいくつかのデフォルト属性を提供します。 しかし、多くの場合、これらは十分ではなく、アプリケーションに固有のユーザー属性を追加する必要がある場合があります。

このチュートリアルでは、 Keycloak認証サーバーにカスタムユーザー属性を追加し、Springベースのバックエンドでそれらにアクセスする方法を説明します。

最初に、スタンドアロン Keycloakサーバーでこれを確認し、次に埋め込みサーバーでこれを確認します。

2. スタンドアロンサーバー

2.1. カスタムユーザー属性の追加

ここでの最初のステップは、Keycloakの管理コンソールに移動することです。 そのためには、Keycloakディストリビューションのbinフォルダーから次のコマンドを実行してサーバーを起動する必要があります。

./standalone.sh -Djboss.socket.binding.port-offset=100

次に、管理コンソールに移動し、 initial1 / zaq1!QAZ資格情報を入力する必要があります。

次に、管理タブの下のユーザーをクリックしてから、すべてのユーザーを表示をクリックします。

ここに、以前に追加したユーザーuser1が表示されます。

次に、 ID をクリックし、属性タブに移動して、新しい誕生日DOBを追加します。

保存をクリックすると、カスタム属性がユーザーの情報に追加されます。

次に、この属性のマッピングをカスタムクレームとして追加して、ユーザーのトークンのJSONペイロードで使用できるようにする必要があります。

そのためには、管理コンソールでアプリケーションのクライアントに移動する必要があります。 以前にクライアントlogin-appを作成したことを思い出してください。

それでは、それをクリックしてマッパータブに移動し、新しいマッピングを作成しましょう。

まず、マッパータイプユーザー属性として選択し、名前ユーザー属性トークンクレームを設定しますDOBという名前を付けます。 Claim JSONTypeStringとして設定する必要があります。

保存をクリックすると、マッピングの準備が整います。 これで、Keycloak側から、カスタムユーザー属性としてDOBを受け取ることができるようになりました。

次のセクションでは、API呼び出しを介してアクセスする方法を説明します。

2.2. カスタムユーザー属性へのアクセス

Spring Bootアプリケーションの上に構築して、新しいRESTコントローラーを追加して、追加したユーザー属性を取得しましょう。

@Controller
public class CustomUserAttrController {

    @GetMapping(path = "/users")
    public String getUserInfo(Model model) {
        KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken) 
          SecurityContextHolder.getContext().getAuthentication();
        
        Principal principal = (Principal) authentication.getPrincipal();        
        String dob="";
        
        if (principal instanceof KeycloakPrincipal) {
            KeycloakPrincipal kPrincipal = (KeycloakPrincipal) principal;
            IDToken token = kPrincipal.getKeycloakSecurityContext().getIdToken();

            Map<String, Object> customClaims = token.getOtherClaims();

            if (customClaims.containsKey("DOB")) {
                dob = String.valueOf(customClaims.get("DOB"));
            }
        }
        
        model.addAttribute("username", principal.getName());
        model.addAttribute("dob", dob);
        return "userInfo";
    }
}

ご覧のとおり、ここでは最初にセキュリティコンテキストから KeycloakAuthenticationToken を取得し、次にPrincipalを抽出しました。 KeycloakPrincipal としてキャストした後、IDTokenを取得しました。

DOB は、このIDTokenOtherClaimsから抽出できます。

この情報を表示するために使用するuserInfo.html、という名前のテンプレートは次のとおりです。

<div id="container">
    <h1>Hello, <span th:text="${username}">--name--</span>.</h1>
    <h3>Your Date of Birth as per our records is <span th:text="${dob}"/>.</h3>
</div>

2.3. テスト

ブートアプリケーションを起動すると、次の場所に移動する必要があります http:// localhost:8081/users。 まず、資格情報の入力を求められます。

user1 のクレデンシャルを入力すると、次のページが表示されます。

3. 組み込みサーバー

次に、埋め込まれたKeycloakインスタンスで同じことを実現する方法を見てみましょう。

3.1. カスタムユーザー属性の追加

基本的に、ここで同じ手順を実行する必要がありますが、レルム定義ファイルbaeldung-realm.jsonに事前構成として保存する必要があるだけです。

属性DOBをユーザーjohn@test.comに追加するには、まず、その属性を構成する必要があります。

"attributes" : {
    "DOB" : "1984-07-01"
},

次に、DOBのプロトコルマッパーを追加します。

"protocolMappers": [
    {
    "id": "c5237a00-d3ea-4e87-9caf-5146b02d1a15",
    "name": "DOB",
    "protocol": "openid-connect",
    "protocolMapper": "oidc-usermodel-attribute-mapper",
    "consentRequired": false,
    "config": {
        "userinfo.token.claim": "true",
        "user.attribute": "DOB",
        "id.token.claim": "true",
        "access.token.claim": "true",
        "claim.name": "DOB",
        "jsonType.label": "String"
        }
    }
]

ここで必要なのはそれだけです。

カスタムユーザー属性を追加する認証サーバーの部分を確認したので、リソースサーバーがユーザーのDOBにアクセスする方法を見てみましょう。

3.2. カスタムユーザー属性へのアクセス

リソースサーバー側では、カスタム属性はAuthenticationPrincipalのクレーム値として簡単に利用できます。

そのためのAPIをコーディングしましょう:

@RestController
public class CustomUserAttrController {
    @GetMapping("/user/info/custom")
    public Map<String, Object> getUserInfo(@AuthenticationPrincipal Jwt principal) {
        return Collections.singletonMap("DOB", principal.getClaimAsString("DOB"));
    }
}

3.3. テスト

それでは、JUnitを使用してテストしてみましょう。

最初にアクセストークンを取得してから、リソースサーバーで / user / info / customAPIエンドポイントを呼び出す必要があります。

@Test
public void givenUserWithReadScope_whenGetUserInformationResource_thenSuccess() {
    String accessToken = obtainAccessToken("read");
    Response response = RestAssured.given()
      .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
      .get(userInfoResourceUrl);

    assertThat(response.as(Map.class)).containsEntry("DOB", "1984-07-01");
}

ご覧のとおり、ここでは、ユーザーの属性に追加したのと同じDOB値を取得していることを確認しました。

4. 結論

このチュートリアルでは、 Keycloakでユーザーに属性を追加する方法を学びました。

これは、スタンドアロンインスタンスと組み込みインスタンスの両方で見られました。 また、両方のシナリオで、バックエンドのRESTAPIでこれらのカスタムクレームにアクセスする方法も確認しました。

いつものように、ソースコードはGitHubで入手できます。 スタンドアロンサーバーの場合はチュートリアルGitHubにあり、組み込みインスタンスの場合は OAuthGitHubにあります。