Remove session_state from tokens
Closes #27624 Signed-off-by: Giuseppe Graziano <g.graziano94@gmail.com>
This commit is contained in:
parent
811c70d136
commit
b4f791b632
15 changed files with 154 additions and 43 deletions
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.representations;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.keycloak.TokenCategory;
|
||||
|
@ -66,10 +65,8 @@ public class IDToken extends JsonWebToken {
|
|||
|
||||
protected Long auth_time;
|
||||
|
||||
// session_state is deprecated, sid should be used instead
|
||||
@JsonProperty(SESSION_STATE)
|
||||
@JsonAlias(SESSION_ID)
|
||||
protected String sessionState;
|
||||
@JsonProperty(SESSION_ID)
|
||||
protected String sessionId;
|
||||
|
||||
@JsonProperty(AT_HASH)
|
||||
protected String accessTokenHash;
|
||||
|
@ -177,17 +174,22 @@ public class IDToken extends JsonWebToken {
|
|||
this.auth_time = Long.valueOf(authTime);
|
||||
}
|
||||
|
||||
@JsonProperty(SESSION_ID)
|
||||
|
||||
public String getSessionId() {
|
||||
return sessionState;
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public void setSessionId(String sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getSessionId()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@JsonIgnore
|
||||
public String getSessionState() {
|
||||
return sessionState;
|
||||
}
|
||||
|
||||
public void setSessionState(String sessionState) {
|
||||
this.sessionState = sessionState;
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public String getAccessTokenHash() {
|
||||
|
|
|
@ -43,7 +43,7 @@ public class RefreshToken extends AccessToken {
|
|||
this.issuer = token.issuer;
|
||||
this.subject = token.subject;
|
||||
this.issuedFor = token.issuedFor;
|
||||
this.sessionState = token.sessionState;
|
||||
this.sessionId = token.sessionId;
|
||||
this.nonce = token.nonce;
|
||||
this.audience = new String[] { token.issuer };
|
||||
this.scope = token.scope;
|
||||
|
|
|
@ -75,7 +75,7 @@ Further, when the resource server acquires the PII removed from the access token
|
|||
|
||||
Information that cannot be removed from a lightweight access token::
|
||||
Protocol mappers can controls which information is put onto an access token and the lightweight access token use the protocol mappers. Therefore, the following information cannot be removed from the lightweight access. +
|
||||
`exp`, `iat`, `jti`, `iss`, `sub`, `typ`, `azp`, `nonce`, `session_state`, `sid`, `scope`, `cnf`
|
||||
`exp`, `iat`, `jti`, `iss`, `sub`, `typ`, `azp`, `nonce`, `sid`, `scope`, `cnf`
|
||||
|
||||
Using a lightweight access token in {project_name}::
|
||||
By applying `use-lightweight-access-token` executor of <<_client_policies, client policies>> to a client, the client can receive a lightweight access token instead of an access token. The lightweight access token contains a claim controlled by a protocol mapper where its setting `Add to lightweight access token`(default OFF) is turned ON. Also, by turning ON its setting `Add to token introspection` of the protocol mapper, the client can obtain the claim by sending the access token to {project_name}'s token introspection endpoint.
|
||||
|
|
|
@ -77,4 +77,14 @@ This scope contains preconfigured protocol mappers for the following claims:
|
|||
|
||||
* `auth_time`
|
||||
|
||||
This helps to reduce even more the number of claims in a lightweight access token, but also gives the chance to configure claims that were always added automatically.
|
||||
This provides additional help to reduce the number of claims in a lightweight access token, but also gives the chance to configure claims that were always added automatically.
|
||||
|
||||
= Removed `session_state` claim
|
||||
|
||||
The `session_state` claim, which contains the same value as the `sid` claim, is now removed from all tokens as it is not required according to the OpenID Connect Front-Channel Logout and OpenID Connect Back-Channel Logout specifications. The `session_state` claim remains present in the Access Token Response in accordance with OpenID Connect Session Management specification.
|
||||
|
||||
Note that the `setSessionState()` method is also removed from the `IDToken` class in favor of the `setSessionId()` method, and the `getSessionState()` method is now deprecated.
|
||||
|
||||
A new `Session State (session_state)` mapper is also included and can be assigned to client scopes (for instance `basic` client scope) to revert to the old behavior.
|
||||
|
||||
If an old version of the JS adapter is used, the `Session State (session_state)` mapper should also be used via client scopes as described above.
|
|
@ -301,7 +301,7 @@ describe("Clients test", () => {
|
|||
|
||||
clientDetailsPage.goToClientScopesEvaluateGeneratedUserInfoTab();
|
||||
cy.get("div#generatedIdToken").contains('"preferred_username": "admin"');
|
||||
cy.get("div#generatedIdToken").contains('"session_state"');
|
||||
cy.get("div#generatedIdToken").contains('"sid"');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1009,7 +1009,7 @@ function Keycloak (config) {
|
|||
if (token) {
|
||||
kc.token = token;
|
||||
kc.tokenParsed = jwtDecode(token);
|
||||
kc.sessionId = kc.tokenParsed.session_state;
|
||||
kc.sessionId = kc.tokenParsed.sid;
|
||||
kc.authenticated = true;
|
||||
kc.subject = kc.tokenParsed.sub;
|
||||
kc.realmAccess = kc.tokenParsed.realm_access;
|
||||
|
|
|
@ -32,7 +32,6 @@ import java.util.Set;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.ws.rs.HttpMethod;
|
||||
|
@ -366,7 +365,7 @@ public class AuthorizationTokenService {
|
|||
|
||||
if (accessToken.getSessionState() == null) {
|
||||
// Skip generating refresh token for accessToken without sessionState claim. This is "stateless" accessToken not pointing to any real persistent userSession
|
||||
rpt.setSessionState(null);
|
||||
rpt.setSessionId(null);
|
||||
} else {
|
||||
if (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseRefreshToken()) {
|
||||
responseBuilder.generateRefreshToken();
|
||||
|
|
|
@ -164,7 +164,7 @@ public class AccessTokenIntrospectionProvider implements TokenIntrospectionProvi
|
|||
newToken.issuer(token.getIssuer());
|
||||
newToken.setNonce(token.getNonce());
|
||||
newToken.setScope(token.getScope());
|
||||
newToken.setSessionState(token.getSessionState());
|
||||
newToken.setSessionId(token.getSessionId());
|
||||
|
||||
// In the case of a refresh token, aud is a basic claim.
|
||||
newToken.audience(token.getAudience());
|
||||
|
|
|
@ -991,7 +991,7 @@ public class TokenManager {
|
|||
token.setAcr(acr);
|
||||
}
|
||||
|
||||
token.setSessionState(session.getId());
|
||||
token.setSessionId(session.getId());
|
||||
ClientScopeModel offlineAccessScope = KeycloakModelUtils.getClientScopeByName(realm, OAuth2Constants.OFFLINE_ACCESS);
|
||||
boolean offlineTokenRequested = offlineAccessScope == null ? false
|
||||
: clientSessionCtx.getClientScopeIds().contains(offlineAccessScope.getId());
|
||||
|
@ -1190,7 +1190,7 @@ public class TokenManager {
|
|||
idToken.issuedFor(accessToken.getIssuedFor());
|
||||
idToken.issuer(accessToken.getIssuer());
|
||||
idToken.setNonce(clientSessionCtx.getAttribute(OIDCLoginProtocol.NONCE_PARAM, String.class));
|
||||
idToken.setSessionState(accessToken.getSessionState());
|
||||
idToken.setSessionId(accessToken.getSessionId());
|
||||
idToken.expiration(accessToken.getExpiration());
|
||||
|
||||
// Protocol mapper is supposed to set this in case "step_up_authentication" feature enabled
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.keycloak.events.Details;
|
|||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
|
@ -142,7 +141,7 @@ public class ClientCredentialsGrantType extends OAuth2GrantTypeBase {
|
|||
if (useRefreshToken) {
|
||||
responseBuilder = responseBuilder.generateRefreshToken();
|
||||
} else {
|
||||
responseBuilder.getAccessToken().setSessionState(null);
|
||||
responseBuilder.getAccessToken().setSessionId(null);
|
||||
}
|
||||
|
||||
checkAndBindMtlsHoKToken(responseBuilder, useRefreshToken);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.protocol.oidc.mappers;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.representations.IDToken;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:ggrazian@redhat.com">Giuseppe Graziano</a>
|
||||
*/
|
||||
public class SessionStateMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper, TokenIntrospectionTokenMapper {
|
||||
|
||||
|
||||
public static final String PROVIDER_ID = "oidc-session-state-mapper";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AcrProtocolMapper.class);
|
||||
|
||||
private static final List<ProviderConfigProperty> configProperties = new ArrayList<>();
|
||||
|
||||
public List<ProviderConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Session State (session_state)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCategory() {
|
||||
return TOKEN_MAPPER_CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Add Session State (session_state) claim";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession keycloakSession,
|
||||
ClientSessionContext clientSessionCtx) {
|
||||
if (userSession != null) {
|
||||
token.getOtherClaims().put(IDToken.SESSION_STATE, userSession.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public static ProtocolMapperModel create(String name, boolean accessToken, boolean idToken, boolean userInfo, boolean introspectionEndpoint) {
|
||||
ProtocolMapperModel mapper = new ProtocolMapperModel();
|
||||
mapper.setName(name);
|
||||
mapper.setProtocolMapper(PROVIDER_ID);
|
||||
mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> config = new HashMap<>();
|
||||
if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
|
||||
if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
|
||||
if (userInfo) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
|
||||
if (introspectionEndpoint) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_INTROSPECTION, "true");
|
||||
mapper.setConfig(config);
|
||||
return mapper;
|
||||
}
|
||||
|
||||
}
|
|
@ -755,7 +755,7 @@ public class AuthenticationManager {
|
|||
token.type(TokenUtil.TOKEN_TYPE_KEYCLOAK_ID);
|
||||
|
||||
if (session != null) {
|
||||
token.setSessionState(session.getId());
|
||||
token.setSessionId(session.getId());
|
||||
}
|
||||
|
||||
if (session != null && session.isRememberMe() && realm.getSsoSessionMaxLifespanRememberMe() > 0) {
|
||||
|
|
|
@ -48,3 +48,4 @@ org.keycloak.protocol.oidc.mappers.ClaimsParameterTokenMapper
|
|||
org.keycloak.protocol.saml.mappers.UserAttributeNameIdMapper
|
||||
org.keycloak.protocol.oidc.mappers.ClaimsParameterWithValueIdTokenMapper
|
||||
org.keycloak.protocol.oidc.mappers.NonceBackwardsCompatibleMapper
|
||||
org.keycloak.protocol.oidc.mappers.SessionStateMapper
|
||||
|
|
|
@ -210,7 +210,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
|
|||
JsonNode jsonNode = objectMapper.readTree(tokenResponse);
|
||||
|
||||
assertTrue(jsonNode.get("active").asBoolean());
|
||||
assertEquals(sessionId, jsonNode.get("session_state").asText());
|
||||
assertEquals(sessionId, jsonNode.get("sid").asText());
|
||||
assertEquals("test-app", jsonNode.get("client_id").asText());
|
||||
assertTrue(jsonNode.has("exp"));
|
||||
assertTrue(jsonNode.has("iat"));
|
||||
|
@ -225,7 +225,7 @@ public class TokenIntrospectionTest extends AbstractTestRealmKeycloakTest {
|
|||
|
||||
assertTrue(rep.isActive());
|
||||
assertEquals("test-app", rep.getClientId());
|
||||
assertEquals(jsonNode.get("session_state").asText(), rep.getSessionState());
|
||||
assertEquals(jsonNode.get("sid").asText(), rep.getSessionState());
|
||||
assertEquals(jsonNode.get("exp").asInt(), rep.getExpiration());
|
||||
assertEquals(jsonNode.get("iat").asInt(), rep.getIssuedAt());
|
||||
assertEquals(jsonNode.get("nbf"), rep.getNbf());
|
||||
|
|
|
@ -37,7 +37,9 @@ import org.keycloak.protocol.oidc.mappers.OIDCAttributeMapperHelper;
|
|||
import org.keycloak.protocol.oidc.mappers.RoleNameMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.SHA256PairwiseSubMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.UserSessionNoteMapper;
|
||||
import org.keycloak.protocol.oidc.mappers.SessionStateMapper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -227,12 +229,12 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
OAuthClient.AccessTokenResponse response = oauth.doClientCredentialsGrantAccessTokenRequest(TEST_CLIENT_SECRET);
|
||||
String accessToken = response.getAccessToken();
|
||||
logger.debug("accessToken:" + accessToken);
|
||||
assertAccessToken(oauth.verifyToken(accessToken), false, false, true);
|
||||
assertAccessToken(oauth.verifyToken(accessToken), false, false, false);
|
||||
|
||||
oauth.clientId(RESOURCE_SERVER_CLIENT_ID);
|
||||
String tokenResponse = oauth.introspectAccessTokenWithClientCredential(RESOURCE_SERVER_CLIENT_ID, RESOURCE_SERVER_CLIENT_PASSWORD, accessToken);
|
||||
logger.debug("tokenResponse:" + tokenResponse);
|
||||
assertTokenIntrospectionResponse(JsonSerialization.readValue(tokenResponse, AccessToken.class), false);
|
||||
assertTokenIntrospectionResponse(JsonSerialization.readValue(tokenResponse, AccessToken.class), false, true, false);
|
||||
} finally {
|
||||
deleteProtocolMappers(protocolMappers);
|
||||
}
|
||||
|
@ -257,7 +259,7 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
oauth.clientId(RESOURCE_SERVER_CLIENT_ID);
|
||||
String tokenResponse = oauth.introspectAccessTokenWithClientCredential(RESOURCE_SERVER_CLIENT_ID, RESOURCE_SERVER_CLIENT_PASSWORD, exchangedTokenString);
|
||||
logger.debug("tokenResponse:" + tokenResponse);
|
||||
assertTokenIntrospectionResponse(JsonSerialization.readValue(tokenResponse, AccessToken.class), true, true, true);
|
||||
assertTokenIntrospectionResponse(JsonSerialization.readValue(tokenResponse, AccessToken.class), true, true, false);
|
||||
} finally {
|
||||
deleteProtocolMappers(protocolMappers);
|
||||
}
|
||||
|
@ -406,6 +408,7 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
Assert.assertNotNull(token.getOtherClaims().get("user-session-note"));
|
||||
Assert.assertNotNull(token.getOtherClaims().get("test-claim"));
|
||||
Assert.assertNotNull(token.getOtherClaims().get("group-name"));
|
||||
Assert.assertNotNull(token.getOtherClaims().get(IDToken.SESSION_STATE));
|
||||
}
|
||||
Assert.assertNotNull(token.getAudience());
|
||||
Assert.assertNotNull(token.getAcr());
|
||||
|
@ -424,6 +427,7 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
Assert.assertNull(token.getOtherClaims().get("user-session-note"));
|
||||
Assert.assertNull(token.getOtherClaims().get("test-claim"));
|
||||
Assert.assertNull(token.getOtherClaims().get("group-name"));
|
||||
Assert.assertNull(token.getOtherClaims().get(IDToken.SESSION_STATE));
|
||||
}
|
||||
Assert.assertNull(token.getAcr());
|
||||
Assert.assertNull(token.getAllowedOrigins());
|
||||
|
@ -439,22 +443,26 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
Assert.assertNotNull(token.getIat());
|
||||
Assert.assertNotNull(token.getId());
|
||||
Assert.assertNotNull(token.getType());
|
||||
Assert.assertNotNull(token.getIssuedFor());
|
||||
Assert.assertNotNull(token.getScope());
|
||||
Assert.assertNotNull(token.getIssuer());
|
||||
Assert.assertNotNull(token.getSubject());
|
||||
if (isAuthCodeFlow) {
|
||||
Assert.assertNotNull(token.getSessionId());
|
||||
} else {
|
||||
Assert.assertNull(token.getSessionId());
|
||||
}
|
||||
Assert.assertNotNull(token.getIssuedFor());
|
||||
Assert.assertNotNull(token.getScope());
|
||||
Assert.assertNotNull(token.getIssuer());
|
||||
Assert.assertNotNull(token.getSubject());
|
||||
}
|
||||
|
||||
private void assertBasicClaims(AccessToken token, boolean missing) {
|
||||
private void assertBasicClaims(AccessToken token, boolean isAuthCodeFlow, boolean missing) {
|
||||
if (missing) {
|
||||
Assert.assertNull(token.getAuth_time());
|
||||
} else {
|
||||
if (isAuthCodeFlow) {
|
||||
Assert.assertNotNull(token.getAuth_time());
|
||||
} else {
|
||||
Assert.assertNull(token.getAuth_time());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,18 +476,15 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
Assert.assertNull(token.getNonce());
|
||||
assertMapperClaims(token, isAddToAccessToken, isAuthCodeFlow);
|
||||
assertInitClaims(token, isAuthCodeFlow);
|
||||
assertBasicClaims(token, missingBasicClaims);
|
||||
assertBasicClaims(token, isAuthCodeFlow, missingBasicClaims);
|
||||
}
|
||||
|
||||
private void assertTokenIntrospectionResponse(AccessToken token, boolean isAuthCodeFlow) {
|
||||
assertTokenIntrospectionResponse(token, isAuthCodeFlow, true, false);
|
||||
}
|
||||
|
||||
private void assertTokenIntrospectionResponse(AccessToken token, boolean isAuthCodeFlow, boolean isAddToIntrospect, boolean exchangeToken) {
|
||||
private void assertTokenIntrospectionResponse(AccessToken token, boolean isAuthCodeFlow, boolean isAddToIntrospect, boolean missingBasicClaims) {
|
||||
Assert.assertNull(token.getNonce());
|
||||
assertMapperClaims(token, isAddToIntrospect, isAuthCodeFlow);
|
||||
assertInitClaims(token, isAuthCodeFlow);
|
||||
assertIntrospectClaims(token);
|
||||
assertBasicClaims(token, isAuthCodeFlow, missingBasicClaims);
|
||||
}
|
||||
|
||||
protected RealmResource testRealm() {
|
||||
|
@ -592,6 +597,8 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
}});
|
||||
protocolMapperList.add(pairwiseSubMapper);
|
||||
}
|
||||
ProtocolMapperRepresentation sessionStateMapper = createClaimMapper("session-state-mapper", SessionStateMapper.PROVIDER_ID, config);
|
||||
protocolMapperList.add(sessionStateMapper);
|
||||
}
|
||||
|
||||
private static ProtocolMapperRepresentation createClaimMapper(String name, String providerId, Map<String, String> config) {
|
||||
|
@ -604,7 +611,7 @@ public class LightWeightAccessTokenTest extends AbstractClientPoliciesTest {
|
|||
}
|
||||
|
||||
private void deleteProtocolMappers(ProtocolMappersResource protocolMappers) {
|
||||
List<String> mapperNames = new ArrayList<>(Arrays.asList("reference", "audience", "role-name", "group-member", "hardcoded-claim", "hardcoded-role", "user-session-note", "pairwise-sub-mapper"));
|
||||
List<String> mapperNames = new ArrayList<>(Arrays.asList("reference", "audience", "role-name", "group-member", "hardcoded-claim", "hardcoded-role", "user-session-note", "pairwise-sub-mapper", "session-state-mapper"));
|
||||
List<ProtocolMapperRepresentation> mappers = new ArrayList<>();
|
||||
for (String mapperName : mapperNames) {
|
||||
mappers.add(ProtocolMapperUtil.getMapperByNameAndProtocol(protocolMappers, OIDCLoginProtocol.LOGIN_PROTOCOL, mapperName));
|
||||
|
|
Loading…
Reference in a new issue