keycloak-service
クラス | 公開メンバ関数 | 静的公開メンバ関数 | 限定公開メンバ関数 | 非公開メンバ関数 | 静的非公開メンバ関数 | 静的非公開変数類 | 全メンバ一覧
org.keycloak.protocol.oidc.TokenManager クラス
org.keycloak.protocol.oidc.TokenManager 連携図
Collaboration graph

クラス

class  AccessTokenResponseBuilder
 
class  RefreshResult
 
class  TokenValidation
 

公開メンバ関数

TokenValidation validateToken (KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException
 
boolean checkTokenValidForIntrospection (KeycloakSession session, RealmModel realm, AccessToken token) throws OAuthErrorException
 
RefreshResult refreshAccessToken (KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers, HttpRequest request) throws OAuthErrorException
 
RefreshToken verifyRefreshToken (KeycloakSession session, RealmModel realm, String encodedRefreshToken) throws OAuthErrorException
 
RefreshToken verifyRefreshToken (KeycloakSession session, RealmModel realm, String encodedRefreshToken, boolean checkExpiration) throws OAuthErrorException
 
RefreshToken verifyRefreshToken (KeycloakSession session, RealmModel realm, ClientModel client, HttpRequest request, String encodedRefreshToken, boolean checkExpiration) throws OAuthErrorException
 
RefreshToken toRefreshToken (KeycloakSession session, String encodedRefreshToken) throws JWSInputException, OAuthErrorException
 
IDToken verifyIDToken (KeycloakSession session, RealmModel realm, String encodedIDToken) throws OAuthErrorException
 
IDToken verifyIDTokenSignature (KeycloakSession session, String encodedIDToken) throws OAuthErrorException
 
AccessToken createClientAccessToken (KeycloakSession session, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
 
AccessToken transformAccessToken (KeycloakSession session, AccessToken token, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
 
AccessToken transformUserInfoAccessToken (KeycloakSession session, AccessToken token, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
 
void transformIDToken (KeycloakSession session, IDToken token, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
 
AccessTokenResponseBuilder responseBuilder (RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
 

静的公開メンバ関数

static void applyScope (RoleModel role, RoleModel scope, Set< RoleModel > visited, Set< RoleModel > requested)
 
static ClientSessionContext attachAuthenticationSession (KeycloakSession session, UserSessionModel userSession, AuthenticationSessionModel authSession)
 
static void dettachClientSession (UserSessionProvider sessions, RealmModel realm, AuthenticatedClientSessionModel clientSession)
 
static Set< RoleModel > getAccess (UserModel user, ClientModel client, Set< ClientScopeModel > clientScopes)
 
static Set< ClientScopeModel > getRequestedClientScopes (String scopeParam, ClientModel client)
 
static boolean verifyConsentStillAvailable (KeycloakSession session, UserModel user, ClientModel client, Set< ClientScopeModel > requestedClientScopes)
 

限定公開メンバ関数

AccessToken initToken (RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionContext clientSessionCtx, UriInfo uriInfo)
 
void addComposites (AccessToken token, RoleModel role)
 

非公開メンバ関数

boolean isUserValid (KeycloakSession session, RealmModel realm, AccessToken token, UserSessionModel userSession)
 
void validateTokenReuse (KeycloakSession session, RealmModel realm, RefreshToken refreshToken, TokenValidation validation) throws OAuthErrorException
 
void verifyAccess (AccessToken token, AccessToken newToken) throws OAuthErrorException
 
int getTokenExpiration (RealmModel realm, ClientModel client, UserSessionModel userSession, AuthenticatedClientSessionModel clientSession)
 

静的非公開メンバ関数

static void addGroupRoles (GroupModel group, Set< RoleModel > roleMappings)
 

静的非公開変数類

static final Logger logger = Logger.getLogger(TokenManager.class)
 
static final String JWT = "JWT"
 

詳解

Stateless object that creates tokens and manages oauth access codes

著者
Bill Burke
バージョン
Revision
1

関数詳解

◆ addComposites()

void org.keycloak.protocol.oidc.TokenManager.addComposites ( AccessToken  token,
RoleModel  role 
)
inlineprotected
712  {
713  AccessToken.Access access = null;
714  if (role.getContainer() instanceof RealmModel) {
715  access = token.getRealmAccess();
716  if (token.getRealmAccess() == null) {
717  access = new AccessToken.Access();
718  token.setRealmAccess(access);
719  } else if (token.getRealmAccess().getRoles() != null && token.getRealmAccess().isUserInRole(role.getName()))
720  return;
721 
722  } else {
723  ClientModel app = (ClientModel) role.getContainer();
724  access = token.getResourceAccess(app.getClientId());
725  if (access == null) {
726  access = token.addAccess(app.getClientId());
727  if (app.isSurrogateAuthRequired()) access.verifyCaller(true);
728  } else if (access.isUserInRole(role.getName())) return;
729 
730  }
731  access.addRole(role.getName());
732  if (!role.isComposite()) return;
733 
734  for (RoleModel composite : role.getComposites()) {
735  addComposites(token, composite);
736  }
737 
738  }
void addComposites(AccessToken token, RoleModel role)
Definition: TokenManager.java:712

◆ addGroupRoles()

static void org.keycloak.protocol.oidc.TokenManager.addGroupRoles ( GroupModel  group,
Set< RoleModel >  roleMappings 
)
inlinestaticprivate
474  {
475  roleMappings.addAll(group.getRoleMappings());
476  if (group.getParentId() == null) return;
477  addGroupRoles(group.getParent(), roleMappings);
478  }
static void addGroupRoles(GroupModel group, Set< RoleModel > roleMappings)
Definition: TokenManager.java:474

◆ applyScope()

static void org.keycloak.protocol.oidc.TokenManager.applyScope ( RoleModel  role,
RoleModel  scope,
Set< RoleModel >  visited,
Set< RoleModel >  requested 
)
inlinestatic
88  {
89  if (visited.contains(scope)) return;
90  visited.add(scope);
91  if (role.hasRole(scope)) {
92  requested.add(scope);
93  return;
94  }
95  if (!scope.isComposite()) return;
96 
97  for (RoleModel contained : scope.getComposites()) {
98  applyScope(role, contained, visited, requested);
99  }
100  }
static void applyScope(RoleModel role, RoleModel scope, Set< RoleModel > visited, Set< RoleModel > requested)
Definition: TokenManager.java:88

◆ attachAuthenticationSession()

static ClientSessionContext org.keycloak.protocol.oidc.TokenManager.attachAuthenticationSession ( KeycloakSession  session,
UserSessionModel  userSession,
AuthenticationSessionModel  authSession 
)
inlinestatic
427  {
428  ClientModel client = authSession.getClient();
429 
430  AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
431  if (clientSession == null) {
432  clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
433  }
434 
435  clientSession.setRedirectUri(authSession.getRedirectUri());
436  clientSession.setProtocol(authSession.getProtocol());
437 
438  Set<String> clientScopeIds = authSession.getClientScopes();
439 
440  Map<String, String> transferredNotes = authSession.getClientNotes();
441  for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
442  clientSession.setNote(entry.getKey(), entry.getValue());
443  }
444 
445  Map<String, String> transferredUserSessionNotes = authSession.getUserSessionNotes();
446  for (Map.Entry<String, String> entry : transferredUserSessionNotes.entrySet()) {
447  userSession.setNote(entry.getKey(), entry.getValue());
448  }
449 
450  clientSession.setTimestamp(Time.currentTime());
451 
452  // Remove authentication session now
453  new AuthenticationSessionManager(session).removeAuthenticationSession(userSession.getRealm(), authSession, true);
454 
455  return DefaultClientSessionContext.fromClientSessionAndClientScopeIds(clientSession, clientScopeIds);
456  }

◆ checkTokenValidForIntrospection()

boolean org.keycloak.protocol.oidc.TokenManager.checkTokenValidForIntrospection ( KeycloakSession  session,
RealmModel  realm,
AccessToken  token 
) throws OAuthErrorException
inline

Checks if the token is valid. Intended usage is for token introspection endpoints as the session last refresh is updated if the token was valid. This is used to keep the session alive when long lived tokens are used.

引数
session
realm
token
戻り値
例外
OAuthErrorException
215  {
216  if (!token.isActive()) {
217  return false;
218  }
219 
220  if (token.getIssuedAt() < realm.getNotBefore()) {
221  return false;
222  }
223 
224  ClientModel client = realm.getClientByClientId(token.getIssuedFor());
225  if (client == null || !client.isEnabled() || token.getIssuedAt() < client.getNotBefore()) {
226  return false;
227  }
228 
229  boolean valid = false;
230 
231  UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), false, client.getId());
232 
233  if (AuthenticationManager.isSessionValid(realm, userSession)) {
234  valid = isUserValid(session, realm, token, userSession);
235  } else {
236  userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, token.getSessionState(), true, client.getId());
237  if (AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
238  valid = isUserValid(session, realm, token, userSession);
239  }
240  }
241 
242  if (valid) {
243  userSession.setLastSessionRefresh(Time.currentTime());
244  }
245 
246  return valid;
247  }
boolean isUserValid(KeycloakSession session, RealmModel realm, AccessToken token, UserSessionModel userSession)
Definition: TokenManager.java:249

◆ createClientAccessToken()

AccessToken org.keycloak.protocol.oidc.TokenManager.createClientAccessToken ( KeycloakSession  session,
RealmModel  realm,
ClientModel  client,
UserModel  user,
UserSessionModel  userSession,
ClientSessionContext  clientSessionCtx 
)
inline
416  {
417  Set<RoleModel> requestedRoles = clientSessionCtx.getRoles();
418  AccessToken token = initToken(realm, client, user, userSession, clientSessionCtx, session.getContext().getUri());
419  for (RoleModel role : requestedRoles) {
420  addComposites(token, role);
421  }
422  token = transformAccessToken(session, token, userSession, clientSessionCtx);
423  return token;
424  }
AccessToken transformAccessToken(KeycloakSession session, AccessToken token, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
Definition: TokenManager.java:598
void addComposites(AccessToken token, RoleModel role)
Definition: TokenManager.java:712
AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionContext clientSessionCtx, UriInfo uriInfo)
Definition: TokenManager.java:641

◆ dettachClientSession()

static void org.keycloak.protocol.oidc.TokenManager.dettachClientSession ( UserSessionProvider  sessions,
RealmModel  realm,
AuthenticatedClientSessionModel  clientSession 
)
inlinestatic
459  {
460  UserSessionModel userSession = clientSession.getUserSession();
461  if (userSession == null) {
462  return;
463  }
464 
465  clientSession.detachFromUserSession();
466 
467  // TODO: Might need optimization to prevent loading client sessions from cache in getAuthenticatedClientSessions()
468  if (userSession.getAuthenticatedClientSessions().isEmpty()) {
469  sessions.removeUserSession(realm, userSession);
470  }
471  }

◆ getAccess()

static Set<RoleModel> org.keycloak.protocol.oidc.TokenManager.getAccess ( UserModel  user,
ClientModel  client,
Set< ClientScopeModel >  clientScopes 
)
inlinestatic
481  {
482  Set<RoleModel> requestedRoles = new HashSet<RoleModel>();
483 
484  Set<RoleModel> mappings = user.getRoleMappings();
485  Set<RoleModel> roleMappings = new HashSet<>();
486  roleMappings.addAll(mappings);
487  for (GroupModel group : user.getGroups()) {
488  addGroupRoles(group, roleMappings);
489  }
490 
491  if (client.isFullScopeAllowed()) {
492  if (logger.isTraceEnabled()) {
493  logger.tracef("Using full scope for client %s", client.getClientId());
494  }
495  requestedRoles = roleMappings;
496  } else {
497  Set<RoleModel> scopeMappings = new HashSet<>();
498 
499  // 1 - Client roles of this client itself
500  scopeMappings.addAll(client.getRoles());
501 
502  // 2 - Role mappings of client itself + default client scopes + optional client scopes requested by scope parameter (if applyScopeParam is true)
503  for (ClientScopeModel clientScope : clientScopes) {
504  if (logger.isTraceEnabled()) {
505  logger.tracef("Adding client scope role mappings of client scope '%s' to client '%s'", clientScope.getName(), client.getClientId());
506  }
507  scopeMappings.addAll(clientScope.getScopeMappings());
508  }
509 
510  for (RoleModel role : roleMappings) {
511  for (RoleModel desiredRole : scopeMappings) {
512  Set<RoleModel> visited = new HashSet<RoleModel>();
513  applyScope(role, desiredRole, visited, requestedRoles);
514  }
515  }
516  }
517 
518  return requestedRoles;
519  }
static void addGroupRoles(GroupModel group, Set< RoleModel > roleMappings)
Definition: TokenManager.java:474
static final Logger logger
Definition: TokenManager.java:85
static void applyScope(RoleModel role, RoleModel scope, Set< RoleModel > visited, Set< RoleModel > requested)
Definition: TokenManager.java:88

◆ getRequestedClientScopes()

static Set<ClientScopeModel> org.keycloak.protocol.oidc.TokenManager.getRequestedClientScopes ( String  scopeParam,
ClientModel  client 
)
inlinestatic

Return client itself + all default client scopes of client + optional client scopes requested by scope parameter

523  {
524  // Add all default client scopes automatically
525  Set<ClientScopeModel> clientScopes = new HashSet<>(client.getClientScopes(true, true).values());
526 
527  // Add client itself
528  clientScopes.add(client);
529 
530  if (scopeParam == null) {
531  return clientScopes;
532  }
533 
534  // Add optional client scopes requested by scope parameter
535  String[] scopes = scopeParam.split(" ");
536  Collection<String> scopeParamParts = Arrays.asList(scopes);
537  Map<String, ClientScopeModel> allOptionalScopes = client.getClientScopes(false, true);
538  for (String scopeParamPart : scopeParamParts) {
539  ClientScopeModel scope = allOptionalScopes.get(scopeParamPart);
540  if (scope != null) {
541  clientScopes.add(scope);
542  }
543  }
544 
545  return clientScopes;
546  }

◆ getTokenExpiration()

int org.keycloak.protocol.oidc.TokenManager.getTokenExpiration ( RealmModel  realm,
ClientModel  client,
UserSessionModel  userSession,
AuthenticatedClientSessionModel  clientSession 
)
inlineprivate
677  {
678  boolean implicitFlow = false;
679  String responseType = clientSession.getNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
680  if (responseType != null) {
681  implicitFlow = OIDCResponseType.parse(responseType).isImplicitFlow();
682  }
683 
684  int tokenLifespan;
685 
686  if (implicitFlow) {
687  tokenLifespan = realm.getAccessTokenLifespanForImplicitFlow();
688  } else {
689  String clientLifespan = client.getAttribute(OIDCConfigAttributes.ACCESS_TOKEN_LIFESPAN);
690  if (clientLifespan != null && !clientLifespan.trim().isEmpty()) {
691  tokenLifespan = Integer.parseInt(clientLifespan);
692  } else {
693  tokenLifespan = realm.getAccessTokenLifespan();
694  }
695  }
696 
697  int expiration;
698  if (tokenLifespan == -1) {
699  expiration = userSession.getStarted() + realm.getSsoSessionMaxLifespan();
700  } else {
701  expiration = Time.currentTime() + tokenLifespan;
702  }
703 
704  if (!userSession.isOffline()) {
705  int sessionExpires = userSession.getStarted() + realm.getSsoSessionMaxLifespan();
706  expiration = expiration <= sessionExpires ? expiration : sessionExpires;
707  }
708 
709  return expiration;
710  }

◆ initToken()

AccessToken org.keycloak.protocol.oidc.TokenManager.initToken ( RealmModel  realm,
ClientModel  client,
UserModel  user,
UserSessionModel  session,
ClientSessionContext  clientSessionCtx,
UriInfo  uriInfo 
)
inlineprotected
642  {
643  AccessToken token = new AccessToken();
644  token.id(KeycloakModelUtils.generateId());
645  token.type(TokenUtil.TOKEN_TYPE_BEARER);
646  token.subject(user.getId());
647  token.audience(client.getClientId());
648  token.issuedNow();
649  token.issuedFor(client.getClientId());
650 
651  AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
652  token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
653  token.setNonce(clientSession.getNote(OIDCLoginProtocol.NONCE_PARAM));
654  token.setScope(clientSessionCtx.getScopeString());
655 
656  // Best effort for "acr" value. Use 0 if clientSession was authenticated through cookie ( SSO )
657  // TODO: Add better acr support. See KEYCLOAK-3314
658  String acr = (AuthenticationManager.isSSOAuthentication(clientSession)) ? "0" : "1";
659  token.setAcr(acr);
660 
661  String authTime = session.getNote(AuthenticationManager.AUTH_TIME);
662  if (authTime != null) {
663  token.setAuthTime(Integer.parseInt(authTime));
664  }
665 
666 
667  token.setSessionState(session.getId());
668  token.expiration(getTokenExpiration(realm, client, session, clientSession));
669 
670  Set<String> allowedOrigins = client.getWebOrigins();
671  if (allowedOrigins != null) {
672  token.setAllowedOrigins(WebOriginsUtils.resolveValidWebOrigins(uriInfo, client));
673  }
674  return token;
675  }
int getTokenExpiration(RealmModel realm, ClientModel client, UserSessionModel userSession, AuthenticatedClientSessionModel clientSession)
Definition: TokenManager.java:677

◆ isUserValid()

boolean org.keycloak.protocol.oidc.TokenManager.isUserValid ( KeycloakSession  session,
RealmModel  realm,
AccessToken  token,
UserSessionModel  userSession 
)
inlineprivate
249  {
250  UserModel user = userSession.getUser();
251  if (user == null) {
252  return false;
253  }
254  if (!user.isEnabled()) {
255  return false;
256  }
257  if (token.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
258  return false;
259  }
260  return true;
261  }

◆ refreshAccessToken()

RefreshResult org.keycloak.protocol.oidc.TokenManager.refreshAccessToken ( KeycloakSession  session,
UriInfo  uriInfo,
ClientConnection  connection,
RealmModel  realm,
ClientModel  authorizedClient,
String  encodedRefreshToken,
EventBuilder  event,
HttpHeaders  headers,
HttpRequest  request 
) throws OAuthErrorException
inline
265  {
266  RefreshToken refreshToken = verifyRefreshToken(session, realm, authorizedClient, request, encodedRefreshToken, true);
267 
268  event.user(refreshToken.getSubject()).session(refreshToken.getSessionState())
269  .detail(Details.REFRESH_TOKEN_ID, refreshToken.getId())
270  .detail(Details.REFRESH_TOKEN_TYPE, refreshToken.getType());
271 
272  TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
273  AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
274 
275  // validate authorizedClient is same as validated client
276  if (!clientSession.getClient().getId().equals(authorizedClient.getId())) {
277  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
278  }
279 
280  validateTokenReuse(session, realm, refreshToken, validation);
281 
282  int currentTime = Time.currentTime();
283  clientSession.setTimestamp(currentTime);
284  validation.userSession.setLastSessionRefresh(currentTime);
285 
286  if (refreshToken.getAuthorization() != null) {
287  validation.newToken.setAuthorization(refreshToken.getAuthorization());
288  }
289 
290  AccessTokenResponseBuilder responseBuilder = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSessionCtx)
291  .accessToken(validation.newToken)
292  .generateRefreshToken();
293 
294  if (validation.newToken.getAuthorization() != null) {
295  responseBuilder.getRefreshToken().setAuthorization(validation.newToken.getAuthorization());
296  }
297 
298  // KEYCLOAK-6771 Certificate Bound Token
299  // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
300  // bind refreshed access and refresh token with Client Certificate
301  AccessToken.CertConf certConf = refreshToken.getCertConf();
302  if (certConf != null) {
303  responseBuilder.getAccessToken().setCertConf(certConf);
304  responseBuilder.getRefreshToken().setCertConf(certConf);
305  }
306 
307  String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
308  if (TokenUtil.isOIDCRequest(scopeParam)) {
309  responseBuilder.generateIDToken();
310  }
311 
312  AccessTokenResponse res = responseBuilder.build();
313 
314  return new RefreshResult(res, TokenUtil.TOKEN_TYPE_OFFLINE.equals(refreshToken.getType()));
315  }
AccessToken accessToken
Definition: TokenManager.java:753
void validateTokenReuse(KeycloakSession session, RealmModel realm, RefreshToken refreshToken, TokenValidation validation)
Definition: TokenManager.java:317
RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, String encodedRefreshToken)
Definition: TokenManager.java:346
TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, RefreshToken oldToken, HttpHeaders headers)
Definition: TokenManager.java:116
AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
Definition: TokenManager.java:740

◆ responseBuilder()

AccessTokenResponseBuilder org.keycloak.protocol.oidc.TokenManager.responseBuilder ( RealmModel  realm,
ClientModel  client,
EventBuilder  event,
KeycloakSession  session,
UserSessionModel  userSession,
ClientSessionContext  clientSessionCtx 
)
inline
741  {
742  return new AccessTokenResponseBuilder(realm, client, event, session, userSession, clientSessionCtx);
743  }

◆ toRefreshToken()

RefreshToken org.keycloak.protocol.oidc.TokenManager.toRefreshToken ( KeycloakSession  session,
String  encodedRefreshToken 
) throws JWSInputException, OAuthErrorException
inline
385  {
386  RefreshToken refreshToken = session.tokens().decode(encodedRefreshToken, RefreshToken.class);
387  if (refreshToken == null) {
388  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
389  }
390  return refreshToken;
391  }

◆ transformAccessToken()

AccessToken org.keycloak.protocol.oidc.TokenManager.transformAccessToken ( KeycloakSession  session,
AccessToken  token,
UserSessionModel  userSession,
ClientSessionContext  clientSessionCtx 
)
inline
599  {
600  Set<ProtocolMapperModel> mappings = clientSessionCtx.getProtocolMappers();
601  KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
602  for (ProtocolMapperModel mapping : mappings) {
603 
604  ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
605  if (mapper instanceof OIDCAccessTokenMapper) {
606  token = ((OIDCAccessTokenMapper) mapper).transformAccessToken(token, mapping, session, userSession, clientSessionCtx.getClientSession());
607  }
608  }
609 
610  return token;
611  }

◆ transformIDToken()

void org.keycloak.protocol.oidc.TokenManager.transformIDToken ( KeycloakSession  session,
IDToken  token,
UserSessionModel  userSession,
ClientSessionContext  clientSessionCtx 
)
inline
629  {
630  Set<ProtocolMapperModel> mappings = clientSessionCtx.getProtocolMappers();
631  KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
632  for (ProtocolMapperModel mapping : mappings) {
633 
634  ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
635  if (mapper instanceof OIDCIDTokenMapper) {
636  token = ((OIDCIDTokenMapper) mapper).transformIDToken(token, mapping, session, userSession, clientSessionCtx.getClientSession());
637  }
638  }
639  }

◆ transformUserInfoAccessToken()

AccessToken org.keycloak.protocol.oidc.TokenManager.transformUserInfoAccessToken ( KeycloakSession  session,
AccessToken  token,
UserSessionModel  userSession,
ClientSessionContext  clientSessionCtx 
)
inline
614  {
615  Set<ProtocolMapperModel> mappings = clientSessionCtx.getProtocolMappers();
616  KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
617  for (ProtocolMapperModel mapping : mappings) {
618 
619  ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
620  if (mapper instanceof UserInfoTokenMapper) {
621  token = ((UserInfoTokenMapper) mapper).transformUserInfoToken(token, mapping, session, userSession, clientSessionCtx.getClientSession());
622  }
623  }
624 
625  return token;
626  }

◆ validateToken()

TokenValidation org.keycloak.protocol.oidc.TokenManager.validateToken ( KeycloakSession  session,
UriInfo  uriInfo,
ClientConnection  connection,
RealmModel  realm,
RefreshToken  oldToken,
HttpHeaders  headers 
) throws OAuthErrorException
inline
117  {
118  UserSessionModel userSession = null;
119  boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());
120 
121  if (offline) {
122 
123  UserSessionManager sessionManager = new UserSessionManager(session);
124  userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
125  if (userSession != null) {
126 
127  // Revoke timeouted offline userSession
128  if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
129  sessionManager.revokeOfflineUserSession(userSession);
130  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
131  }
132 
133  } else {
134  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
135  }
136  } else {
137  // Find userSession regularly for online tokens
138  userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
139  if (!AuthenticationManager.isSessionValid(realm, userSession)) {
140  AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
141  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
142  }
143  }
144 
145  UserModel user = userSession.getUser();
146  if (user == null) {
147  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
148  }
149 
150  if (!user.isEnabled()) {
151  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
152  }
153 
154  ClientModel client = session.getContext().getClient();
155  AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
156 
157  // Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
158  if (clientSession == null) {
159  userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
160  if (userSession != null) {
161  clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
162  } else {
163  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
164  }
165  }
166 
167  if (!client.getClientId().equals(oldToken.getIssuedFor())) {
168  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
169  }
170 
171  if (oldToken.getIssuedAt() < client.getNotBefore()) {
172  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
173  }
174  if (oldToken.getIssuedAt() < realm.getNotBefore()) {
175  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
176  }
177  if (oldToken.getIssuedAt() < session.users().getNotBeforeOfUser(realm, user)) {
178  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
179  }
180 
181 
182  // Setup clientScopes from refresh token to the context
183  String oldTokenScope = oldToken.getScope();
184 
185  // Case when offline token is migrated from previous version
186  if (oldTokenScope == null && userSession.isOffline()) {
187  logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
188  MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
189  }
190 
191  ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope);
192 
193  // Check user didn't revoke granted consent
194  if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopes())) {
195  throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
196  }
197 
198  // recreate token.
199  AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);
200  verifyAccess(oldToken, newToken);
201 
202  return new TokenValidation(user, userSession, clientSessionCtx, newToken);
203  }
static boolean verifyConsentStillAvailable(KeycloakSession session, UserModel user, ClientModel client, Set< ClientScopeModel > requestedClientScopes)
Definition: TokenManager.java:549
static final Logger logger
Definition: TokenManager.java:85
void verifyAccess(AccessToken token, AccessToken newToken)
Definition: TokenManager.java:572
AccessToken createClientAccessToken(KeycloakSession session, RealmModel realm, ClientModel client, UserModel user, UserSessionModel userSession, ClientSessionContext clientSessionCtx)
Definition: TokenManager.java:415

◆ validateTokenReuse()

void org.keycloak.protocol.oidc.TokenManager.validateTokenReuse ( KeycloakSession  session,
RealmModel  realm,
RefreshToken  refreshToken,
TokenValidation  validation 
) throws OAuthErrorException
inlineprivate
318  {
319  if (realm.isRevokeRefreshToken()) {
320  AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
321 
322  int clusterStartupTime = session.getProvider(ClusterProvider.class).getClusterStartupTime();
323 
324  if (clientSession.getCurrentRefreshToken() != null &&
325  !refreshToken.getId().equals(clientSession.getCurrentRefreshToken()) &&
326  refreshToken.getIssuedAt() < clientSession.getTimestamp() &&
327  clusterStartupTime != clientSession.getTimestamp()) {
328  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
329  }
330 
331 
332  if (!refreshToken.getId().equals(clientSession.getCurrentRefreshToken())) {
333  clientSession.setCurrentRefreshToken(refreshToken.getId());
334  clientSession.setCurrentRefreshTokenUseCount(0);
335  }
336 
337  int currentCount = clientSession.getCurrentRefreshTokenUseCount();
338  if (currentCount > realm.getRefreshTokenMaxReuse()) {
339  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Maximum allowed refresh token reuse exceeded",
340  "Maximum allowed refresh token reuse exceeded");
341  }
342  clientSession.setCurrentRefreshTokenUseCount(currentCount + 1);
343  }
344  }

◆ verifyAccess()

void org.keycloak.protocol.oidc.TokenManager.verifyAccess ( AccessToken  token,
AccessToken  newToken 
) throws OAuthErrorException
inlineprivate
572  {
573  if (token.getRealmAccess() != null) {
574  if (newToken.getRealmAccess() == null) throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm roles");
575 
576  for (String roleName : token.getRealmAccess().getRoles()) {
577  if (!newToken.getRealmAccess().getRoles().contains(roleName)) {
578  throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for realm role: " + roleName);
579  }
580  }
581  }
582  if (token.getResourceAccess() != null) {
583  for (Map.Entry<String, AccessToken.Access> entry : token.getResourceAccess().entrySet()) {
584  AccessToken.Access appAccess = newToken.getResourceAccess(entry.getKey());
585  if (appAccess == null && !entry.getValue().getRoles().isEmpty()) {
586  throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User or client no longer has role permissions for client key: " + entry.getKey());
587 
588  }
589  for (String roleName : entry.getValue().getRoles()) {
590  if (!appAccess.getRoles().contains(roleName)) {
591  throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "User no long has permission for client role " + roleName);
592  }
593  }
594  }
595  }
596  }

◆ verifyConsentStillAvailable()

static boolean org.keycloak.protocol.oidc.TokenManager.verifyConsentStillAvailable ( KeycloakSession  session,
UserModel  user,
ClientModel  client,
Set< ClientScopeModel >  requestedClientScopes 
)
inlinestatic
549  {
550  if (!client.isConsentRequired()) {
551  return true;
552  }
553 
554  UserConsentModel grantedConsent = session.users().getConsentByClient(client.getRealm(), user.getId(), client.getId());
555 
556  for (ClientScopeModel requestedScope : requestedClientScopes) {
557  if (!requestedScope.isDisplayOnConsentScreen()) {
558  continue;
559  }
560 
561  if (!grantedConsent.getGrantedClientScopes().contains(requestedScope)) {
562  logger.debugf("Client '%s' no longer has requested consent from user '%s' for client scope '%s'",
563  client.getClientId(), user.getUsername(), requestedScope.getName());
564  return false;
565  }
566  }
567 
568  return true;
569  }
static final Logger logger
Definition: TokenManager.java:85

◆ verifyIDToken()

IDToken org.keycloak.protocol.oidc.TokenManager.verifyIDToken ( KeycloakSession  session,
RealmModel  realm,
String  encodedIDToken 
) throws OAuthErrorException
inline
393  {
394  IDToken idToken = session.tokens().decode(encodedIDToken, IDToken.class);
395  if (idToken == null) {
396  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid IDToken");
397  }
398  if (idToken.isExpired()) {
399  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "IDToken expired");
400  }
401  if (idToken.getIssuedAt() < realm.getNotBefore()) {
402  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale IDToken");
403  }
404  return idToken;
405  }

◆ verifyIDTokenSignature()

IDToken org.keycloak.protocol.oidc.TokenManager.verifyIDTokenSignature ( KeycloakSession  session,
String  encodedIDToken 
) throws OAuthErrorException
inline
407  {
408  IDToken idToken = session.tokens().decode(encodedIDToken, IDToken.class);
409  if (idToken == null) {
410  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid IDToken");
411  }
412  return idToken;
413  }

◆ verifyRefreshToken() [1/3]

RefreshToken org.keycloak.protocol.oidc.TokenManager.verifyRefreshToken ( KeycloakSession  session,
RealmModel  realm,
String  encodedRefreshToken 
) throws OAuthErrorException
inline
346  {
347  return verifyRefreshToken(session, realm, encodedRefreshToken, true);
348  }
RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, String encodedRefreshToken)
Definition: TokenManager.java:346

◆ verifyRefreshToken() [2/3]

RefreshToken org.keycloak.protocol.oidc.TokenManager.verifyRefreshToken ( KeycloakSession  session,
RealmModel  realm,
String  encodedRefreshToken,
boolean  checkExpiration 
) throws OAuthErrorException
inline
350  {
351  return verifyRefreshToken(session, realm, null, null, encodedRefreshToken, true);
352  }
RefreshToken verifyRefreshToken(KeycloakSession session, RealmModel realm, String encodedRefreshToken)
Definition: TokenManager.java:346

◆ verifyRefreshToken() [3/3]

RefreshToken org.keycloak.protocol.oidc.TokenManager.verifyRefreshToken ( KeycloakSession  session,
RealmModel  realm,
ClientModel  client,
HttpRequest  request,
String  encodedRefreshToken,
boolean  checkExpiration 
) throws OAuthErrorException
inline
354  {
355  try {
356  RefreshToken refreshToken = toRefreshToken(session, encodedRefreshToken);
357 
358  if (!(TokenUtil.TOKEN_TYPE_REFRESH.equals(refreshToken.getType()) || TokenUtil.TOKEN_TYPE_OFFLINE.equals(refreshToken.getType()))) {
359  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token");
360  }
361 
362  if (checkExpiration) {
363  if (refreshToken.getExpiration() != 0 && refreshToken.isExpired()) {
364  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh token expired");
365  }
366 
367  if (refreshToken.getIssuedAt() < realm.getNotBefore()) {
368  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale refresh token");
369  }
370  }
371 
372  // KEYCLOAK-6771 Certificate Bound Token
373  if (client != null && OIDCAdvancedConfigWrapper.fromClientModel(client).isUseMtlsHokToken()) {
374  if (!MtlsHoKTokenUtil.verifyTokenBindingWithClientCertificate(refreshToken, request, session)) {
375  throw new OAuthErrorException(OAuthErrorException.UNAUTHORIZED_CLIENT, MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC);
376  }
377  }
378 
379  return refreshToken;
380  } catch (JWSInputException e) {
381  throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", e);
382  }
383  }
RefreshToken toRefreshToken(KeycloakSession session, String encodedRefreshToken)
Definition: TokenManager.java:385

メンバ詳解

◆ JWT

final String org.keycloak.protocol.oidc.TokenManager.JWT = "JWT"
staticprivate

◆ logger

final Logger org.keycloak.protocol.oidc.TokenManager.logger = Logger.getLogger(TokenManager.class)
staticprivate

このクラス詳解は次のファイルから抽出されました: