Skip to content

Commit

Permalink
feature: Add mapper for hardcoded tenant to OIDC token claims (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
joas8211 authored Aug 28, 2024
1 parent 6237eba commit e17505e
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package dev.sultanov.keycloak.multitenancy.protocol.oidc.mappers;

import dev.sultanov.keycloak.multitenancy.model.TenantMembershipModel;
import dev.sultanov.keycloak.multitenancy.model.TenantModel;
import dev.sultanov.keycloak.multitenancy.model.TenantProvider;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
import org.keycloak.protocol.oidc.mappers.OIDCIDTokenMapper;
import org.keycloak.protocol.oidc.mappers.UserInfoTokenMapper;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.IDToken;

public class HardcodedTenantMapper extends AbstractOIDCProtocolMapper
implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {

private static final String TENANT_ID_PROPERTY_NAME = "hardcoded_tenant_id";

private static final List<ProviderConfigProperty> CONFIG_PROPERTIES = new ArrayList<>(
List.of(new ProviderConfigProperty(
TENANT_ID_PROPERTY_NAME, "Tenant ID", null, ProviderConfigProperty.STRING_TYPE, null, false,
true)));

static {
OIDCAttributeMapperHelper.addTokenClaimNameConfig(CONFIG_PROPERTIES);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(CONFIG_PROPERTIES, HardcodedTenantMapper.class);
}

public static final String PROVIDER_ID = "oidc-hardcoded-tenant-mapper";

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

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

@Override
public String getDisplayType() {
return "Hardcoded tenant";
}

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

@Override
public String getHelpText() {
return "Maps hardcoded tenant to a token claim";
}

@Override
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession,
KeycloakSession keycloakSession,
ClientSessionContext clientSessionCtx) {
var tenantID = mappingModel.getConfig().get(TENANT_ID_PROPERTY_NAME);
var provider = keycloakSession.getProvider(TenantProvider.class);
var optionalTenant = provider.getTenantById(userSession.getRealm(), tenantID);

var claimName = mappingModel.getConfig().get(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
if (claimName != null && optionalTenant.isPresent()) {
var tenant = optionalTenant.get();
var user = userSession.getUser();
var membership = new TenantMembershipModel() {
@Override
public String getId() {
return null;
}

@Override
public TenantModel getTenant() {
return tenant;
}

@Override
public UserModel getUser() {
return user;
}

@Override
public Set<String> getRoles() {
return Collections.emptySet();
}

@Override
public void updateRoles(Set<String> roles) {
throw new RuntimeException("UNSUPPORTED METHOD");
}
};
token.getOtherClaims().put(claimName, ClaimsFactory.toClaim(membership));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
dev.sultanov.keycloak.multitenancy.protocol.oidc.mappers.ActiveTenantMapper
dev.sultanov.keycloak.multitenancy.protocol.oidc.mappers.AllTenantsMapper
dev.sultanov.keycloak.multitenancy.protocol.oidc.mappers.AllTenantsMapper
dev.sultanov.keycloak.multitenancy.protocol.oidc.mappers.HardcodedTenantMapper

0 comments on commit e17505e

Please sign in to comment.