keycloak~scope客戶端模板的使用

张占岭發表於2024-09-03

scope為何物?

scope在oauth2中表示授權的範圍,另外也可以理解為,根據認證時scope的引數,在構建jwt時,返回更多的資訊;比如在keycloak中,你的可選scope(optional scope)中新增了address這個模板,當你透過/auth/realms/{realmId}/protocol/openid-connect/token進行認證時,你的引數scope中出現address,那麼在生成的jwt token中,就會出現address這個內容,如圖:

這種按需求構建jwt的方法就是client scope最大的作用,下面我們具體來說一下步驟。

客戶端模板功能彙總

  1. 在客戶端模板中,可以看到所有的模板列表
  2. 可直接為所有新加的客戶端新增預設模板(Default Client Scopes)
  3. 可以在模板配置中,選擇可選模板,這個功能與認證引數scope配合使用,根據scope引數來擴充套件jwt token的內容
  4. 透過繼承AbstractOIDCProtocolMapper來擴充套件客戶端模板

配置客戶端模板

模板列表,如圖:

預設客戶端模板和可選客戶端模板

  • 預設客戶端模板(Default Client Scopes )
  • 可選客戶端模板(Optional Client Scopes )
  • 以上兩種模板互斥,即,當一個模板select-user被選擇為“預設客戶端模板”後,它將會在“可選客戶端模板”列表中消失,反之,亦然。

可選客戶端模板,可以新增address,openid來對原有jwt進行擴充套件,如圖:

認證請求時,新增scope引數,如openid,address等

  • openid:在jwt中新增id_token相關資訊,即存放使用者的基本資訊的token。
  • address:在jwt中新增address屬性,透過解析user_attribute中的street,locality,region等資訊,來擴充套件jwt token。

自定義客戶端模板

例如,希望寫一個擴充套件,在token中輸出使用者暱稱,但這個暱稱是有業務邏輯的,透過複雜的邏輯計算出一個使用者暱稱,這時,需要你自定義一個模板

  1. 定義一個ExtensionNicknameMapper
public class ExtensionNicknameMapper
    extends AbstractOIDCProtocolMapper
    implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {

  public static final String CONFIG_NAME = "extensionNickname";//配置裡的名稱
  public static final String PROVIDER_ID = "oidc-extension-nick-name-mapper";
  private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
  private static final String NICKNAME = "nickname";

  static {
    configProperties.add(createConfigProperty(CONFIG_NAME, "Token申請名", "在jwt中的屬性名稱,預設nickname"));
    OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, ExtensionNicknameMapper.class);
  }

  protected static ProviderConfigProperty createConfigProperty(String claimName, String label, String help) {
    ProviderConfigProperty property = new ProviderConfigProperty();
    property.setName(claimName);
    property.setLabel(label);
    property.setHelpText(help);
    property.setType(ProviderConfigProperty.STRING_TYPE);
    return property;
  }

  @Override
  protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession,
                          KeycloakSession keycloakSession, ClientSessionContext clientSessionCtx) {
  
      String nickname="";
       // 複雜的業務方法,計算出nickname變數的值
      token.setOtherClaims(tokenAttribute, nickname);
  }

  public List<ProviderConfigProperty> getConfigProperties() {
    return configProperties;
  }

  @Override
  public String getId() {
    return PROVIDER_ID;
  }

  @Override
  public String getDisplayType() {
    return "Extension Nickname";
  }

  @Override
  public String getDisplayCategory() {
    return TOKEN_MAPPER_CATEGORY;
  }

  @Override
  public String getHelpText() {
    return "Maps Extension Nickname claim.";
  }

}

  1. 將ExtensionNicknameMapper新增到Jboss的SPI中
  • /resources/META-INF/services/org.keycloak.protocol.ProtocolMapper檔案
your.package.ExtensionNicknameMapper
  1. 在keycloak管理後臺,新增一個新的模板,然後在模板裡的mapper選項卡中,新增一個新的mapper中選你的ExtensionNicknameMapper

好了,到這裡,keycloak的client scope(客戶端模板)就介紹完了,希望對各位有所幫助。

相關文章