use of org.keycloak.models.AuthenticatedClientSessionModel in project keycloak by keycloak.
the class TokenEndpoint method refreshTokenGrant.
public Response refreshTokenGrant() {
String refreshToken = formParams.getFirst(OAuth2Constants.REFRESH_TOKEN);
if (refreshToken == null) {
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
}
try {
session.clientPolicy().triggerOnEvent(new TokenRefreshContext(formParams));
} catch (ClientPolicyException cpe) {
event.error(cpe.getError());
throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
}
AccessTokenResponse res;
try {
// KEYCLOAK-6771 Certificate Bound Token
TokenManager.RefreshResult result = tokenManager.refreshAccessToken(session, session.getContext().getUri(), clientConnection, realm, client, refreshToken, event, headers, request);
res = result.getResponse();
if (!result.isOfflineToken()) {
UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
updateClientSession(clientSession);
updateUserSessionFromClientAuth(userSession);
}
} catch (OAuthErrorException e) {
logger.trace(e.getMessage(), e);
// KEYCLOAK-6771 Certificate Bound Token
if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
event.error(Errors.NOT_ALLOWED);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
} else {
event.error(Errors.INVALID_TOKEN);
throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
}
}
event.success();
return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
use of org.keycloak.models.AuthenticatedClientSessionModel in project keycloak by keycloak.
the class OIDCLoginProtocol method authenticated.
@Override
public Response authenticated(AuthenticationSessionModel authSession, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
if (isOAuth2DeviceVerificationFlow(authSession)) {
return approveOAuth2DeviceAuthorization(authSession, clientSession, session);
}
String responseTypeParam = authSession.getClientNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM);
String responseModeParam = authSession.getClientNote(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
setupResponseTypeAndMode(responseTypeParam, responseModeParam);
String redirect = authSession.getRedirectUri();
OIDCRedirectUriBuilder redirectUri = OIDCRedirectUriBuilder.fromUri(redirect, responseMode, session, clientSession);
String state = authSession.getClientNote(OIDCLoginProtocol.STATE_PARAM);
logger.debugv("redirectAccessCode: state: {0}", state);
if (state != null)
redirectUri.addParam(OAuth2Constants.STATE, state);
OIDCAdvancedConfigWrapper clientConfig = OIDCAdvancedConfigWrapper.fromClientModel(clientSession.getClient());
if (!clientConfig.isExcludeSessionStateFromAuthResponse()) {
redirectUri.addParam(OAuth2Constants.SESSION_STATE, userSession.getId());
}
String nonce = authSession.getClientNote(OIDCLoginProtocol.NONCE_PARAM);
clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, nonce);
String kcActionStatus = authSession.getClientNote(Constants.KC_ACTION_STATUS);
if (kcActionStatus != null) {
redirectUri.addParam(Constants.KC_ACTION_STATUS, kcActionStatus);
}
// Standard or hybrid flow
String code = null;
if (responseType.hasResponseType(OIDCResponseType.CODE)) {
OAuth2Code codeData = new OAuth2Code(UUID.randomUUID(), Time.currentTime() + userSession.getRealm().getAccessCodeLifespan(), nonce, authSession.getClientNote(OAuth2Constants.SCOPE), authSession.getClientNote(OIDCLoginProtocol.REDIRECT_URI_PARAM), authSession.getClientNote(OIDCLoginProtocol.CODE_CHALLENGE_PARAM), authSession.getClientNote(OIDCLoginProtocol.CODE_CHALLENGE_METHOD_PARAM));
code = OAuth2CodeParser.persistCode(session, clientSession, codeData);
redirectUri.addParam(OAuth2Constants.CODE, code);
}
// Implicit or hybrid flow
if (responseType.isImplicitOrHybridFlow()) {
org.keycloak.protocol.oidc.TokenManager tokenManager = new org.keycloak.protocol.oidc.TokenManager();
org.keycloak.protocol.oidc.TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, clientSession.getClient(), event, session, userSession, clientSessionCtx).generateAccessToken();
if (responseType.hasResponseType(OIDCResponseType.ID_TOKEN)) {
responseBuilder.generateIDToken(isIdTokenAsDetachedSignature(clientSession.getClient()));
if (responseType.hasResponseType(OIDCResponseType.TOKEN)) {
responseBuilder.generateAccessTokenHash();
}
if (responseType.hasResponseType(OIDCResponseType.CODE)) {
responseBuilder.generateCodeHash(code);
}
// http://openid.net/specs/openid-financial-api-part-2.html#authorization-server
if (state != null && !state.isEmpty())
responseBuilder.generateStateHash(state);
}
AccessTokenResponse res = responseBuilder.build();
if (responseType.hasResponseType(OIDCResponseType.ID_TOKEN)) {
redirectUri.addParam(OAuth2Constants.ID_TOKEN, res.getIdToken());
}
if (responseType.hasResponseType(OIDCResponseType.TOKEN)) {
redirectUri.addParam(OAuth2Constants.ACCESS_TOKEN, res.getToken());
redirectUri.addParam(OAuth2Constants.TOKEN_TYPE, res.getTokenType());
redirectUri.addParam(OAuth2Constants.EXPIRES_IN, String.valueOf(res.getExpiresIn()));
}
}
return redirectUri.build();
}
use of org.keycloak.models.AuthenticatedClientSessionModel in project keycloak by keycloak.
the class TokenManager method attachAuthenticationSession.
public static ClientSessionContext attachAuthenticationSession(KeycloakSession session, UserSessionModel userSession, AuthenticationSessionModel authSession) {
ClientModel client = authSession.getClient();
AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
if (clientSession == null) {
clientSession = session.sessions().createClientSession(userSession.getRealm(), client, userSession);
}
clientSession.setRedirectUri(authSession.getRedirectUri());
clientSession.setProtocol(authSession.getProtocol());
Set<String> clientScopeIds;
if (Profile.isFeatureEnabled(Profile.Feature.DYNAMIC_SCOPES)) {
clientScopeIds = AuthorizationContextUtil.getClientScopesStreamFromAuthorizationRequestContextWithClient(session, authSession.getClientNote(OAuth2Constants.SCOPE)).map(ClientScopeModel::getId).collect(Collectors.toSet());
} else {
clientScopeIds = authSession.getClientScopes();
}
Map<String, String> transferredNotes = authSession.getClientNotes();
for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
clientSession.setNote(entry.getKey(), entry.getValue());
}
Map<String, String> transferredUserSessionNotes = authSession.getUserSessionNotes();
for (Map.Entry<String, String> entry : transferredUserSessionNotes.entrySet()) {
userSession.setNote(entry.getKey(), entry.getValue());
}
clientSession.setNote(Constants.LEVEL_OF_AUTHENTICATION, String.valueOf(AuthenticatorUtil.getCurrentLevelOfAuthentication(authSession)));
clientSession.setTimestamp(Time.currentTime());
// Remove authentication session now
new AuthenticationSessionManager(session).removeAuthenticationSession(userSession.getRealm(), authSession, true);
ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndClientScopeIds(clientSession, clientScopeIds, session);
return clientSessionCtx;
}
use of org.keycloak.models.AuthenticatedClientSessionModel in project keycloak by keycloak.
the class TokenManager method initToken.
protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionContext clientSessionCtx, UriInfo uriInfo) {
AccessToken token = new AccessToken();
token.id(KeycloakModelUtils.generateId());
token.type(TokenUtil.TOKEN_TYPE_BEARER);
token.subject(user.getId());
token.issuedNow();
token.issuedFor(client.getClientId());
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
token.setNonce(clientSessionCtx.getAttribute(OIDCLoginProtocol.NONCE_PARAM, String.class));
token.setScope(clientSessionCtx.getScopeString());
token.setAcr(getAcr(clientSession));
String authTime = session.getNote(AuthenticationManager.AUTH_TIME);
if (authTime != null) {
token.setAuthTime(Integer.parseInt(authTime));
}
token.setSessionState(session.getId());
ClientScopeModel offlineAccessScope = KeycloakModelUtils.getClientScopeByName(realm, OAuth2Constants.OFFLINE_ACCESS);
boolean offlineTokenRequested = offlineAccessScope == null ? false : clientSessionCtx.getClientScopeIds().contains(offlineAccessScope.getId());
token.expiration(getTokenExpiration(realm, client, session, clientSession, offlineTokenRequested));
return token;
}
use of org.keycloak.models.AuthenticatedClientSessionModel in project keycloak by keycloak.
the class TokenManager method refreshAccessToken.
public RefreshResult refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers, HttpRequest request) throws OAuthErrorException {
RefreshToken refreshToken = verifyRefreshToken(session, realm, authorizedClient, request, encodedRefreshToken, true);
event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.REFRESH_TOKEN_TYPE, refreshToken.getType());
TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
// validate authorizedClient is same as validated client
if (!clientSession.getClient().getId().equals(authorizedClient.getId())) {
throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
}
validateTokenReuseForRefresh(session, realm, refreshToken, validation);
int currentTime = Time.currentTime();
clientSession.setTimestamp(currentTime);
validation.userSession.setLastSessionRefresh(currentTime);
if (refreshToken.getAuthorization() != null) {
validation.newToken.setAuthorization(refreshToken.getAuthorization());
}
AccessTokenResponseBuilder responseBuilder = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSessionCtx).accessToken(validation.newToken);
if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
responseBuilder.generateRefreshToken();
}
if (validation.newToken.getAuthorization() != null && OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
responseBuilder.getRefreshToken().setAuthorization(validation.newToken.getAuthorization());
}
// KEYCLOAK-6771 Certificate Bound Token
// https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
// bind refreshed access and refresh token with Client Certificate
AccessToken.CertConf certConf = refreshToken.getCertConf();
if (certConf != null) {
responseBuilder.getAccessToken().setCertConf(certConf);
if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
responseBuilder.getRefreshToken().setCertConf(certConf);
}
}
String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
if (TokenUtil.isOIDCRequest(scopeParam)) {
responseBuilder.generateIDToken().generateAccessTokenHash();
}
AccessTokenResponse res = responseBuilder.build();
return new RefreshResult(res, TokenUtil.TOKEN_TYPE_OFFLINE.equals(refreshToken.getType()));
}
Aggregations