Java Code Examples for org.keycloak.models.UserSessionModel#setNote()

The following examples show how to use org.keycloak.models.UserSessionModel#setNote() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: LogoutEndpoint.java    From keycloak-protocol-cas with Apache License 2.0 6 votes vote down vote up
@GET
@NoCache
public Response logout(@QueryParam(CASLoginProtocol.SERVICE_PARAM) String service) {
    checkClient(service);

    AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(session, realm, false);
    if (authResult != null) {
        UserSessionModel userSession = authResult.getSession();
        userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, CASLoginProtocol.LOGIN_PROTOCOL);
        if (redirectUri != null) userSession.setNote(CASLoginProtocol.LOGOUT_REDIRECT_URI, redirectUri);

        logger.debug("Initiating CAS browser logout");
        Response response =  AuthenticationManager.browserLogout(session, realm, authResult.getSession(), session.getContext().getUri(), clientConnection, headers, null);
        logger.debug("finishing CAS browser logout");
        return response;
    }
    return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_LOGOUT);
}
 
Example 2
Source File: DeviceActivityManager.java    From keycloak with Apache License 2.0 5 votes vote down vote up
/**
 * Attaches a device to the given {@code userSession} where the device information is obtained from the {@link HttpHeaders#USER_AGENT} in the current
 * request, if available.
 * 
 * @param userSession the user session
 * @param session the keycloak session
 */
public static void attachDevice(UserSessionModel userSession, KeycloakSession session) {
    DeviceRepresentation current = getDeviceFromUserAgent(session);

    if (current != null) {
        try {
            userSession.setNote(DEVICE_NOTE, Base64.encodeBytes(JsonSerialization.writeValueAsBytes(current)));
        } catch (IOException cause) {
            throw new RuntimeException(cause);
        }
    }
}
 
Example 3
Source File: LogoutEndpoint.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private Response initiateBrowserLogout(UserSessionModel userSession, String redirect, String state, String initiatingIdp ) {
    if (redirect != null) userSession.setNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI, redirect);
    if (state != null) userSession.setNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM, state);
    userSession.setNote(AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, OIDCLoginProtocol.LOGIN_PROTOCOL);
    logger.debug("Initiating OIDC browser logout");
    Response response =  AuthenticationManager.browserLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, initiatingIdp);
    logger.debug("finishing OIDC browser logout");
    return response;
}
 
Example 4
Source File: AbstractOAuth2IdentityProvider.java    From keycloak with Apache License 2.0 5 votes vote down vote up
@Override
public void exchangeExternalComplete(UserSessionModel userSession, BrokeredIdentityContext context, MultivaluedMap<String, String> params) {
    if (context.getContextData().containsKey(OIDCIdentityProvider.VALIDATED_ID_TOKEN))
        userSession.setNote(FEDERATED_ACCESS_TOKEN, params.getFirst(OAuth2Constants.SUBJECT_TOKEN));
    if (context.getContextData().containsKey(OIDCIdentityProvider.VALIDATED_ID_TOKEN))
        userSession.setNote(OIDCIdentityProvider.FEDERATED_ID_TOKEN, params.getFirst(OAuth2Constants.SUBJECT_TOKEN));
    userSession.setNote(OIDCIdentityProvider.EXCHANGE_PROVIDER, getConfig().getAlias());

}
 
Example 5
Source File: CrossRealmClientAuthMapper.java    From keycloak-extension-playground with Apache License 2.0 4 votes vote down vote up
private Object fetchCrossRealmData(KeycloakSession session) {


        RealmModel targetRealm = session.realms().getRealmByName("services-demo");
        ClientModel serviceClient = targetRealm.getClientByClientId("simple-service");
        if (!serviceClient.isServiceAccountsEnabled()) {
            return null;
        }
        String loopback = "127.0.0.1";
        EventBuilder event = new EventBuilder(targetRealm, session, new ClientConnection() {
            public String getRemoteAddr() {
                return loopback;
            }

            public String getRemoteHost() {
                return loopback;
            }

            public int getRemotePort() {
                return 8080;
            }

            public String getLocalAddr() {
                return loopback;
            }

            public int getLocalPort() {
                return 8080;
            }
        });

        UserModel serviceAccountUser = session.users().getServiceAccount(serviceClient);
        if (!serviceAccountUser.isEnabled()) {
            return null;
        }

        RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(targetRealm, false);
        AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(serviceClient);
        authSession.setAuthenticatedUser(serviceAccountUser);
        authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
        authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), targetRealm.getName()));
        authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, "openid profile roles");
        UserSessionModel serviceAccountUserSession = session.sessions().createUserSession(authSession.getParentSession().getId(), targetRealm, serviceAccountUser, serviceAccountUser.getUsername(),
                loopback, ServiceAccountConstants.CLIENT_AUTH, false, null, null);
        AuthenticationManager.setClientScopesInSession(authSession);
        ClientSessionContext clientSessionContext = TokenManager.attachAuthenticationSession(session, serviceAccountUserSession, authSession);

        // Notes about serviceClient details
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_ID, serviceClient.getClientId());
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_HOST, loopback);
        serviceAccountUserSession.setNote(ServiceAccountConstants.CLIENT_ADDRESS, loopback);

        TokenManager tokenManager = new TokenManager();
        TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(targetRealm, serviceClient, event, session, serviceAccountUserSession, clientSessionContext)
                .generateAccessToken();

        AccessTokenResponse accessTokenResponse = responseBuilder.build();

        String accessToken = accessTokenResponse.getToken();

        LOGGER.infof("AccessToken: %s", accessToken);

        return null;
    }
 
Example 6
Source File: TokenEndpoint.java    From keycloak with Apache License 2.0 4 votes vote down vote up
private void updateUserSessionFromClientAuth(UserSessionModel userSession) {
    for (Map.Entry<String, String> attr : clientAuthAttributes.entrySet()) {
        userSession.setNote(attr.getKey(), attr.getValue());
    }
}
 
Example 7
Source File: TokenEndpoint.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public Response clientCredentialsGrant() {
    if (client.isBearerOnly()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Bearer-only client not allowed to retrieve service account", Response.Status.UNAUTHORIZED);
    }
    if (client.isPublicClient()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Public client not allowed to retrieve service account", Response.Status.UNAUTHORIZED);
    }
    if (!client.isServiceAccountsEnabled()) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Client not enabled to retrieve service account", Response.Status.UNAUTHORIZED);
    }

    UserModel clientUser = session.users().getServiceAccount(client);

    if (clientUser == null || client.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, ServiceAccountConstants.CLIENT_ID_PROTOCOL_MAPPER) == null) {
        // May need to handle bootstrap here as well
        logger.debugf("Service account user for client '%s' not found or default protocol mapper for service account not found. Creating now", client.getClientId());
        new ClientManager(new RealmManager(session)).enableServiceAccount(client);
        clientUser = session.users().getServiceAccount(client);
    }

    String clientUsername = clientUser.getUsername();
    event.detail(Details.USERNAME, clientUsername);
    event.user(clientUser);

    if (!clientUser.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "User '" + clientUsername + "' disabled", Response.Status.UNAUTHORIZED);
    }

    String scope = getRequestedScopes();

    RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, false);
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);

    authSession.setAuthenticatedUser(clientUser);
    authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
    authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
    authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);

    UserSessionModel userSession = session.sessions().createUserSession(authSession.getParentSession().getId(), realm, clientUser, clientUsername,
            clientConnection.getRemoteAddr(), ServiceAccountConstants.CLIENT_AUTH, false, null, null);
    event.session(userSession);

    AuthenticationManager.setClientScopesInSession(authSession);
    ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);

    // Notes about client details
    userSession.setNote(ServiceAccountConstants.CLIENT_ID, client.getClientId());
    userSession.setNote(ServiceAccountConstants.CLIENT_HOST, clientConnection.getRemoteHost());
    userSession.setNote(ServiceAccountConstants.CLIENT_ADDRESS, clientConnection.getRemoteAddr());

    updateUserSessionFromClientAuth(userSession);

    TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSessionCtx)
            .generateAccessToken()
            .generateRefreshToken();

    String scopeParam = clientSessionCtx.getClientSession().getNote(OAuth2Constants.SCOPE);
    if (TokenUtil.isOIDCRequest(scopeParam)) {
        responseBuilder.generateIDToken().generateAccessTokenHash();
    }

    // TODO : do the same as codeToToken()
    AccessTokenResponse res = responseBuilder.build();

    event.success();

    return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
 
Example 8
Source File: TokenEndpoint.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public Response exchangeExternalToken(String issuer, String subjectToken) {
    ExchangeExternalToken externalIdp = null;
    IdentityProviderModel externalIdpModel = null;

    for (IdentityProviderModel idpModel : realm.getIdentityProviders()) {
        IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel);
        IdentityProvider idp = factory.create(session, idpModel);
        if (idp instanceof ExchangeExternalToken) {
            ExchangeExternalToken external = (ExchangeExternalToken) idp;
            if (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) {
                externalIdp = external;
                externalIdpModel = idpModel;
                break;
            }
        }
    }


    if (externalIdp == null) {
        event.error(Errors.INVALID_ISSUER);
        throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
    }
    if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel)) {
        event.detail(Details.REASON, "client not allowed to exchange subject_issuer");
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
    }
    BrokeredIdentityContext context = externalIdp.exchangeExternal(event, formParams);
    if (context == null) {
        event.error(Errors.INVALID_ISSUER);
        throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
    }

    UserModel user = importUserFromExternalIdentity(context);

    UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "external-exchange", false, null, null);
    externalIdp.exchangeExternalComplete(userSession, context, formParams);

    // this must exist so that we can obtain access token from user session if idp's store tokens is off
    userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.getAlias());
    userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken);

    return exchangeClientToClient(user, userSession);
}
 
Example 9
Source File: IdentityBrokerService.java    From keycloak with Apache License 2.0 4 votes vote down vote up
private Response performAccountLinking(AuthenticationSessionModel authSession, UserSessionModel userSession, BrokeredIdentityContext context, FederatedIdentityModel newModel, UserModel federatedUser) {
    logger.debugf("Will try to link identity provider [%s] to user [%s]", context.getIdpConfig().getAlias(), userSession.getUser().getUsername());

    this.event.event(EventType.FEDERATED_IDENTITY_LINK);



    UserModel authenticatedUser = userSession.getUser();
    authSession.setAuthenticatedUser(authenticatedUser);

    if (federatedUser != null && !authenticatedUser.getId().equals(federatedUser.getId())) {
        return redirectToErrorWhenLinkingFailed(authSession, Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
    }

    if (!authenticatedUser.hasRole(this.realmModel.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID).getRole(AccountRoles.MANAGE_ACCOUNT))) {
        return redirectToErrorPage(authSession, Response.Status.FORBIDDEN, Messages.INSUFFICIENT_PERMISSION);
    }

    if (!authenticatedUser.isEnabled()) {
        return redirectToErrorWhenLinkingFailed(authSession, Messages.ACCOUNT_DISABLED);
    }



    if (federatedUser != null) {
        if (context.getIdpConfig().isStoreToken()) {
            FederatedIdentityModel oldModel = this.session.users().getFederatedIdentity(federatedUser, context.getIdpConfig().getAlias(), this.realmModel);
            if (!ObjectUtil.isEqualOrBothNull(context.getToken(), oldModel.getToken())) {
                this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, newModel);
                if (isDebugEnabled()) {
                    logger.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, context.getIdpConfig().getAlias());
                }
            }
        }
    } else {
        this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, newModel);
    }
    context.getIdp().authenticationFinished(authSession, context);

    AuthenticationManager.setClientScopesInSession(authSession);
    TokenManager.attachAuthenticationSession(session, userSession, authSession);

    if (isDebugEnabled()) {
        logger.debugf("Linking account [%s] from identity provider [%s] to user [%s].", newModel, context.getIdpConfig().getAlias(), authenticatedUser);
    }

    this.event.user(authenticatedUser)
            .detail(Details.USERNAME, authenticatedUser.getUsername())
            .detail(Details.IDENTITY_PROVIDER, newModel.getIdentityProvider())
            .detail(Details.IDENTITY_PROVIDER_USERNAME, newModel.getUserName())
            .success();

    // we do this to make sure that the parent IDP is logged out when this user session is complete.
    // But for the case when userSession was previously authenticated with broker1 and now is linked to another broker2, we shouldn't override broker1 notes with the broker2 for sure.
    // Maybe broker logout should be rather always skiped in case of broker-linking
    if (userSession.getNote(Details.IDENTITY_PROVIDER) == null) {
        userSession.setNote(Details.IDENTITY_PROVIDER, context.getIdpConfig().getAlias());
        userSession.setNote(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
    }

    return Response.status(302).location(UriBuilder.fromUri(authSession.getRedirectUri()).build()).build();
}
 
Example 10
Source File: AuthenticationManager.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public static Response redirectAfterSuccessfulFlow(KeycloakSession session, RealmModel realm, UserSessionModel userSession,
                                                   ClientSessionContext clientSessionCtx,
                                                   HttpRequest request, UriInfo uriInfo, ClientConnection clientConnection,
                                                   EventBuilder event, AuthenticationSessionModel authSession, LoginProtocol protocol) {
    Cookie sessionCookie = getCookie(request.getHttpHeaders().getCookies(), AuthenticationManager.KEYCLOAK_SESSION_COOKIE);
    if (sessionCookie != null) {

        String[] split = sessionCookie.getValue().split("/");
        if (split.length >= 3) {
            String oldSessionId = split[2];
            if (!oldSessionId.equals(userSession.getId())) {
                UserSessionModel oldSession = session.sessions().getUserSession(realm, oldSessionId);
                if (oldSession != null) {
                    logger.debugv("Removing old user session: session: {0}", oldSessionId);
                    session.sessions().removeUserSession(realm, oldSession);
                }
            }
        }
    }

    // Updates users locale if required
    session.getContext().resolveLocale(userSession.getUser());

    // refresh the cookies!
    createLoginCookie(session, realm, userSession.getUser(), userSession, uriInfo, clientConnection);
    if (userSession.getState() != UserSessionModel.State.LOGGED_IN) userSession.setState(UserSessionModel.State.LOGGED_IN);
    if (userSession.isRememberMe()) {
        createRememberMeCookie(realm, userSession.getLoginUsername(), uriInfo, clientConnection);
    } else {
        expireRememberMeCookie(realm, uriInfo, clientConnection);
    }

    AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();

    // Update userSession note with authTime. But just if flag SSO_AUTH is not set
    boolean isSSOAuthentication = "true".equals(session.getAttribute(SSO_AUTH));
    if (isSSOAuthentication) {
        clientSession.setNote(SSO_AUTH, "true");
    } else {
        int authTime = Time.currentTime();
        userSession.setNote(AUTH_TIME, String.valueOf(authTime));
        clientSession.removeNote(SSO_AUTH);
    }

    // The user has successfully logged in and we can clear his/her previous login failure attempts.
    logSuccess(session, authSession);

    return protocol.authenticated(authSession, userSession, clientSessionCtx);

}
 
Example 11
Source File: OIDCIdentityProvider.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
protected Response exchangeSessionToken(UriInfo uriInfo, EventBuilder event, ClientModel authorizedClient, UserSessionModel tokenUserSession, UserModel tokenSubject) {
    String refreshToken = tokenUserSession.getNote(FEDERATED_REFRESH_TOKEN);
    String accessToken = tokenUserSession.getNote(FEDERATED_ACCESS_TOKEN);
    String idToken = tokenUserSession.getNote(FEDERATED_ID_TOKEN);

    if (accessToken == null) {
        event.detail(Details.REASON, "requested_issuer is not linked");
        event.error(Errors.INVALID_TOKEN);
        return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
    }
    try (VaultStringSecret vaultStringSecret = session.vault().getStringSecret(getConfig().getClientSecret())) {
        long expiration = Long.parseLong(tokenUserSession.getNote(FEDERATED_TOKEN_EXPIRATION));
        if (expiration == 0 || expiration > Time.currentTime()) {
            AccessTokenResponse tokenResponse = new AccessTokenResponse();
            tokenResponse.setExpiresIn(expiration);
            tokenResponse.setToken(accessToken);
            tokenResponse.setIdToken(null);
            tokenResponse.setRefreshToken(null);
            tokenResponse.setRefreshExpiresIn(0);
            tokenResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
            tokenResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
            event.success();
            return Response.ok(tokenResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
        }
        String response = getRefreshTokenRequest(session, refreshToken, getConfig().getClientId(), vaultStringSecret.get().orElse(getConfig().getClientSecret())).asString();
        if (response.contains("error")) {
            logger.debugv("Error refreshing token, refresh token expiration?: {0}", response);
            event.detail(Details.REASON, "requested_issuer token expired");
            event.error(Errors.INVALID_TOKEN);
            return exchangeTokenExpired(uriInfo, authorizedClient, tokenUserSession, tokenSubject);
        }
        AccessTokenResponse newResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
        long accessTokenExpiration = newResponse.getExpiresIn() > 0 ? Time.currentTime() + newResponse.getExpiresIn() : 0;
        tokenUserSession.setNote(FEDERATED_TOKEN_EXPIRATION, Long.toString(accessTokenExpiration));
        tokenUserSession.setNote(FEDERATED_REFRESH_TOKEN, newResponse.getRefreshToken());
        tokenUserSession.setNote(FEDERATED_ACCESS_TOKEN, newResponse.getToken());
        tokenUserSession.setNote(FEDERATED_ID_TOKEN, newResponse.getIdToken());
        newResponse.setIdToken(null);
        newResponse.setRefreshToken(null);
        newResponse.setRefreshExpiresIn(0);
        newResponse.getOtherClaims().clear();
        newResponse.getOtherClaims().put(OAuth2Constants.ISSUED_TOKEN_TYPE, OAuth2Constants.ACCESS_TOKEN_TYPE);
        newResponse.getOtherClaims().put(ACCOUNT_LINK_URL, getLinkingUrl(uriInfo, authorizedClient, tokenUserSession));
        event.success();
        return Response.ok(newResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}