Search in sources :

Example 16 with RootAuthenticationSessionModel

use of org.keycloak.sessions.RootAuthenticationSessionModel in project keycloak by keycloak.

the class LoginActionsService method createAuthenticationSessionForClient.

AuthenticationSessionModel createAuthenticationSessionForClient(String clientID) throws UriBuilderException, IllegalArgumentException {
    AuthenticationSessionModel authSession;
    ClientModel client = session.clients().getClientByClientId(realm, clientID);
    String redirectUri;
    if (client == null) {
        client = SystemClientUtil.getSystemClient(realm);
        redirectUri = Urls.accountBase(session.getContext().getUri().getBaseUri()).path("/").build(realm.getName()).toString();
    } else {
        redirectUri = RedirectUtils.getFirstValidRedirectUri(session, client.getRootUrl(), client.getRedirectUris());
    }
    RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, true);
    authSession = rootAuthSession.createAuthenticationSession(client);
    authSession.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
    // authSession.setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true");
    authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
    authSession.setRedirectUri(redirectUri);
    authSession.setClientNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, OAuth2Constants.CODE);
    authSession.setClientNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri);
    authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
    return authSession;
}
Also used : AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel)

Example 17 with RootAuthenticationSessionModel

use of org.keycloak.sessions.RootAuthenticationSessionModel in project keycloak by keycloak.

the class RequiredActionEmailVerificationTest method verifyEmailViaAuthSessionWhileLoggedIn.

@Test
public void verifyEmailViaAuthSessionWhileLoggedIn() throws IOException, MessagingException {
    Assume.assumeTrue("Works only on auth-server-undertow", AuthServerTestEnricher.AUTH_SERVER_CONTAINER.equals(AuthServerTestEnricher.AUTH_SERVER_CONTAINER_DEFAULT));
    UserAttributeUpdater userAttributeUpdater = new UserAttributeUpdater(testRealm().users().get(testUserId));
    userAttributeUpdater.setEmailVerified(false).update();
    final String testRealmName = testRealm().toRepresentation().getRealm();
    accountPage.setAuthRealm(testRealmName);
    oauth.realm(testRealmName).clientId("account").redirectUri(getAuthServerRoot() + "realms/" + testRealmName + "/account");
    loginPage.open();
    String authSessionId = AuthenticationSessionFailoverClusterTest.getAuthSessionCookieValue(driver);
    String realmId = testRealm().toRepresentation().getId();
    testingClient.server().run(session -> {
        RealmModel realm = session.realms().getRealm(realmId);
        RootAuthenticationSessionModel ras = session.authenticationSessions().getRootAuthenticationSession(realm, authSessionId);
        assertThat("Expecting single auth session", ras.getAuthenticationSessions().keySet(), Matchers.hasSize(1));
        ras.getAuthenticationSessions().forEach((id, as) -> as.addRequiredAction(RequiredAction.VERIFY_EMAIL));
    });
    loginPage.login("test-user@localhost", "password");
    verifyEmailPage.assertCurrent();
    Assert.assertEquals(1, greenMail.getReceivedMessages().length);
    MimeMessage message = greenMail.getLastReceivedMessage();
    String verificationUrl = getPasswordResetEmailLink(message);
    // confirm
    driver.navigate().to(verificationUrl);
    // back to account, already logged in
    accountPage.assertCurrent();
    // email should be verified and required actions empty
    UserRepresentation user = testRealm().users().get(testUserId).toRepresentation();
    Assert.assertTrue(user.isEmailVerified());
    Assert.assertThat(user.getRequiredActions(), Matchers.empty());
}
Also used : RealmModel(org.keycloak.models.RealmModel) UserAttributeUpdater(org.keycloak.testsuite.updaters.UserAttributeUpdater) MimeMessage(javax.mail.internet.MimeMessage) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) UserRepresentation(org.keycloak.representations.idm.UserRepresentation) Test(org.junit.Test) AbstractTestRealmKeycloakTest(org.keycloak.testsuite.AbstractTestRealmKeycloakTest) AuthenticationSessionFailoverClusterTest(org.keycloak.testsuite.cluster.AuthenticationSessionFailoverClusterTest)

Example 18 with RootAuthenticationSessionModel

use of org.keycloak.sessions.RootAuthenticationSessionModel in project keycloak by keycloak.

the class IdentityBrokerService method clientInitiatedAccountLinking.

@GET
@NoCache
@Path("/{provider_id}/link")
public Response clientInitiatedAccountLinking(@PathParam("provider_id") String providerId, @QueryParam("redirect_uri") String redirectUri, @QueryParam("client_id") String clientId, @QueryParam("nonce") String nonce, @QueryParam("hash") String hash) {
    this.event.event(EventType.CLIENT_INITIATED_ACCOUNT_LINKING);
    checkRealm();
    ClientModel client = checkClient(clientId);
    redirectUri = RedirectUtils.verifyRedirectUri(session, redirectUri, client);
    if (redirectUri == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.REDIRECT_URI, redirectUri);
    if (nonce == null || hash == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    AuthenticationManager.AuthResult cookieResult = AuthenticationManager.authenticateIdentityCookie(session, realmModel, true);
    String errorParam = "link_error";
    if (cookieResult == null) {
        event.error(Errors.NOT_LOGGED_IN);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_LOGGED_IN).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    cookieResult.getSession();
    event.session(cookieResult.getSession());
    event.user(cookieResult.getUser());
    event.detail(Details.USERNAME, cookieResult.getUser().getUsername());
    AuthenticatedClientSessionModel clientSession = null;
    for (AuthenticatedClientSessionModel cs : cookieResult.getSession().getAuthenticatedClientSessions().values()) {
        if (cs.getClient().getClientId().equals(clientId)) {
            byte[] decoded = Base64Url.decode(hash);
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("SHA-256");
            } catch (NoSuchAlgorithmException e) {
                throw new ErrorPageException(session, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
            }
            String input = nonce + cookieResult.getSession().getId() + clientId + providerId;
            byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
            if (MessageDigest.isEqual(decoded, check)) {
                clientSession = cs;
                break;
            }
        }
    }
    if (clientSession == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.IDENTITY_PROVIDER, providerId);
    ClientModel accountService = this.realmModel.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
    if (!accountService.getId().equals(client.getId())) {
        RoleModel manageAccountRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT);
        // Ensure user has role and client has "role scope" for this role
        ClientSessionContext ctx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
        Set<RoleModel> userAccountRoles = ctx.getRolesStream().collect(Collectors.toSet());
        if (!userAccountRoles.contains(manageAccountRole)) {
            RoleModel linkRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT_LINKS);
            if (!userAccountRoles.contains(linkRole)) {
                event.error(Errors.NOT_ALLOWED);
                UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_ALLOWED).queryParam("nonce", nonce);
                return Response.status(302).location(builder.build()).build();
            }
        }
    }
    IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
    if (identityProviderModel == null) {
        event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.UNKNOWN_IDENTITY_PROVIDER).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    // Create AuthenticationSessionModel with same ID like userSession and refresh cookie
    UserSessionModel userSession = cookieResult.getSession();
    // Auth session with ID corresponding to our userSession may already exists in some rare cases (EG. if some client tried to login in another browser tab with "prompt=login")
    RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().getRootAuthenticationSession(realmModel, userSession.getId());
    if (rootAuthSession == null) {
        rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(realmModel, userSession.getId());
    }
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    // Refresh the cookie
    new AuthenticationSessionManager(session).setAuthSessionCookie(userSession.getId(), realmModel);
    ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
    clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
    clientSessionCode.getOrGenerateCode();
    authSession.setProtocol(client.getProtocol());
    authSession.setRedirectUri(redirectUri);
    authSession.setClientNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
    authSession.setAuthNote(LINKING_IDENTITY_PROVIDER, cookieResult.getSession().getId() + clientId + providerId);
    event.detail(Details.CODE_ID, userSession.getId());
    event.success();
    try {
        IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
        Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
        if (response != null) {
            if (isDebugEnabled()) {
                logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
            }
            return response;
        }
    } catch (IdentityBrokerException e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
    }
    return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) RoleModel(org.keycloak.models.RoleModel) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) ErrorPageException(org.keycloak.services.ErrorPageException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) WebApplicationException(javax.ws.rs.WebApplicationException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) OAuthErrorException(org.keycloak.OAuthErrorException) NotFoundException(javax.ws.rs.NotFoundException) ErrorPageException(org.keycloak.services.ErrorPageException) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Response(javax.ws.rs.core.Response) ErrorResponse(org.keycloak.services.ErrorResponse) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) UriBuilder(javax.ws.rs.core.UriBuilder) MessageDigest(java.security.MessageDigest) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 19 with RootAuthenticationSessionModel

use of org.keycloak.sessions.RootAuthenticationSessionModel in project keycloak by keycloak.

the class AuthenticationManager method createOrJoinLogoutSession.

private static AuthenticationSessionModel createOrJoinLogoutSession(KeycloakSession session, RealmModel realm, final AuthenticationSessionManager asm, UserSessionModel userSession, boolean browserCookie) {
    // Account management client is used as a placeholder
    ClientModel client = SystemClientUtil.getSystemClient(realm);
    String authSessionId;
    RootAuthenticationSessionModel rootLogoutSession = null;
    boolean browserCookiePresent = false;
    // Try to lookup current authSessionId from browser cookie. If doesn't exist, use the same as current userSession
    if (browserCookie) {
        rootLogoutSession = asm.getCurrentRootAuthenticationSession(realm);
    }
    if (rootLogoutSession != null) {
        authSessionId = rootLogoutSession.getId();
        browserCookiePresent = true;
    } else {
        authSessionId = userSession.getId();
        rootLogoutSession = session.authenticationSessions().getRootAuthenticationSession(realm, authSessionId);
    }
    if (rootLogoutSession == null) {
        rootLogoutSession = session.authenticationSessions().createRootAuthenticationSession(realm, authSessionId);
    }
    if (browserCookie && !browserCookiePresent) {
        // Update cookie if needed
        asm.setAuthSessionCookie(authSessionId, realm);
    }
    // See if we have logoutAuthSession inside current rootSession. Create new if not
    Optional<AuthenticationSessionModel> found = rootLogoutSession.getAuthenticationSessions().values().stream().filter((AuthenticationSessionModel authSession) -> {
        return client.equals(authSession.getClient()) && Objects.equals(AuthenticationSessionModel.Action.LOGGING_OUT.name(), authSession.getAction());
    }).findFirst();
    AuthenticationSessionModel logoutAuthSession = found.isPresent() ? found.get() : rootLogoutSession.createAuthenticationSession(client);
    session.getContext().setAuthenticationSession(logoutAuthSession);
    logoutAuthSession.setAction(AuthenticationSessionModel.Action.LOGGING_OUT.name());
    return logoutAuthSession;
}
Also used : ClientModel(org.keycloak.models.ClientModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel)

Example 20 with RootAuthenticationSessionModel

use of org.keycloak.sessions.RootAuthenticationSessionModel in project keycloak by keycloak.

the class AuthenticationSessionManager method removeAuthenticationSession.

public void removeAuthenticationSession(RealmModel realm, AuthenticationSessionModel authSession, boolean expireRestartCookie) {
    RootAuthenticationSessionModel rootAuthSession = authSession.getParentSession();
    log.debugf("Removing authSession '%s'. Expire restart cookie: %b", rootAuthSession.getId(), expireRestartCookie);
    session.authenticationSessions().removeRootAuthenticationSession(realm, rootAuthSession);
    // expire restart cookie
    if (expireRestartCookie) {
        ClientConnection clientConnection = session.getContext().getConnection();
        UriInfo uriInfo = session.getContext().getUri();
        RestartLoginCookie.expireRestartCookie(realm, clientConnection, uriInfo);
    }
}
Also used : RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) ClientConnection(org.keycloak.common.ClientConnection) UriInfo(javax.ws.rs.core.UriInfo)

Aggregations

RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)24 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)21 AuthenticationSessionManager (org.keycloak.services.managers.AuthenticationSessionManager)11 UserSessionModel (org.keycloak.models.UserSessionModel)10 ClientModel (org.keycloak.models.ClientModel)9 UserModel (org.keycloak.models.UserModel)9 ClientSessionContext (org.keycloak.models.ClientSessionContext)7 Test (org.junit.Test)6 RealmModel (org.keycloak.models.RealmModel)6 KeycloakSession (org.keycloak.models.KeycloakSession)5 DefaultClientSessionContext (org.keycloak.services.util.DefaultClientSessionContext)5 AbstractTestRealmKeycloakTest (org.keycloak.testsuite.AbstractTestRealmKeycloakTest)5 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 TokenManager (org.keycloak.protocol.oidc.TokenManager)3 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)3 ModelTest (org.keycloak.testsuite.arquillian.annotation.ModelTest)3 Response (javax.ws.rs.core.Response)2 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)2 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)2 ClientManager (org.keycloak.services.managers.ClientManager)2