Search in sources :

Example 46 with AuthenticatedClientSessionModel

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();
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) TokenRefreshContext(org.keycloak.services.clientpolicy.context.TokenRefreshContext) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) TokenManager(org.keycloak.protocol.oidc.TokenManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 47 with AuthenticatedClientSessionModel

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();
}
Also used : AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) OIDCRedirectUriBuilder(org.keycloak.protocol.oidc.utils.OIDCRedirectUriBuilder) OAuth2Code(org.keycloak.protocol.oidc.utils.OAuth2Code) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 48 with AuthenticatedClientSessionModel

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;
}
Also used : AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) ClientScopeModel(org.keycloak.models.ClientScopeModel) Map(java.util.Map) HashMap(java.util.HashMap)

Example 49 with AuthenticatedClientSessionModel

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;
}
Also used : AccessToken(org.keycloak.representations.AccessToken) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) ClientScopeModel(org.keycloak.models.ClientScopeModel)

Example 50 with AuthenticatedClientSessionModel

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()));
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) AccessToken(org.keycloak.representations.AccessToken) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)59 UserSessionModel (org.keycloak.models.UserSessionModel)35 RealmModel (org.keycloak.models.RealmModel)25 ClientModel (org.keycloak.models.ClientModel)23 Test (org.junit.Test)16 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)13 UserModel (org.keycloak.models.UserModel)12 KeycloakSession (org.keycloak.models.KeycloakSession)11 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)11 HashMap (java.util.HashMap)10 Map (java.util.Map)9 ClientSessionContext (org.keycloak.models.ClientSessionContext)9 LinkedList (java.util.LinkedList)8 DefaultClientSessionContext (org.keycloak.services.util.DefaultClientSessionContext)8 OAuthErrorException (org.keycloak.OAuthErrorException)6 VerificationException (org.keycloak.common.VerificationException)6 AccessToken (org.keycloak.representations.AccessToken)6 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)6 HashSet (java.util.HashSet)5 List (java.util.List)5