use of org.keycloak.models.UserSessionModel in project keycloak by keycloak.
the class IdentityBrokerService method checkAccountManagementFailedLinking.
private Response checkAccountManagementFailedLinking(AuthenticationSessionModel authSession, String error, Object... parameters) {
UserSessionModel userSession = new AuthenticationSessionManager(session).getUserSession(authSession);
if (userSession != null && authSession.getClient() != null && authSession.getClient().getClientId().equals(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID)) {
this.event.event(EventType.FEDERATED_IDENTITY_LINK);
UserModel user = userSession.getUser();
this.event.user(user);
this.event.detail(Details.USERNAME, user.getUsername());
return redirectToAccountErrorPage(authSession, error, parameters);
} else {
return null;
}
}
use of org.keycloak.models.UserSessionModel 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);
}
use of org.keycloak.models.UserSessionModel in project keycloak by keycloak.
the class AuthenticationManager method finishBrowserLogout.
public static Response finishBrowserLogout(KeycloakSession session, RealmModel realm, UserSessionModel userSession, UriInfo uriInfo, ClientConnection connection, HttpHeaders headers) {
final AuthenticationSessionManager asm = new AuthenticationSessionManager(session);
AuthenticationSessionModel logoutAuthSession = createOrJoinLogoutSession(session, realm, asm, userSession, true);
checkUserSessionOnlyHasLoggedOutClients(realm, userSession, logoutAuthSession);
// For resolving artifact we don't need any cookie, all details are stored in session storage so we can remove
expireIdentityCookie(realm, uriInfo, connection);
expireRememberMeCookie(realm, uriInfo, connection);
String method = userSession.getNote(KEYCLOAK_LOGOUT_PROTOCOL);
EventBuilder event = new EventBuilder(realm, session, connection);
LoginProtocol protocol = session.getProvider(LoginProtocol.class, method);
protocol.setRealm(realm).setHttpHeaders(headers).setUriInfo(uriInfo).setEventBuilder(event);
Response response = protocol.finishLogout(userSession);
// It may be possible that there are some client sessions that are still in LOGGING_OUT state
long numberOfUnconfirmedSessions = userSession.getAuthenticatedClientSessions().values().stream().filter(clientSessionModel -> CommonClientSessionModel.Action.LOGGING_OUT.name().equals(clientSessionModel.getAction())).count();
// If logout flow end up correctly there should be at maximum 1 client session in LOGGING_OUT action, if there are more, something went wrong
if (numberOfUnconfirmedSessions > 1) {
logger.warnf("There are more than one clientSession in logging_out state. Perhaps some client did not finish logout flow correctly.");
}
// LOGGED_OUT action can remove UserSession
if (numberOfUnconfirmedSessions >= 1) {
userSession.setState(UserSessionModel.State.LOGGED_OUT_UNCONFIRMED);
} else {
userSession.setState(UserSessionModel.State.LOGGED_OUT);
}
// Do not remove user session, it will be removed when last clientSession will be logged out
if (numberOfUnconfirmedSessions < 1) {
session.sessions().removeUserSession(realm, userSession);
}
session.authenticationSessions().removeRootAuthenticationSession(realm, logoutAuthSession.getParentSession());
return response;
}
use of org.keycloak.models.UserSessionModel in project keycloak by keycloak.
the class AuthenticationManager method redirectAfterSuccessfulFlow.
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 = AuthenticatorUtil.isSSOAuthentication(authSession);
if (isSSOAuthentication) {
clientSession.setNote(SSO_AUTH, "true");
authSession.removeAuthNote(SSO_AUTH);
} 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);
}
use of org.keycloak.models.UserSessionModel in project keycloak by keycloak.
the class AuthenticationManager method verifyIdentityToken.
public static AuthResult verifyIdentityToken(KeycloakSession session, RealmModel realm, UriInfo uriInfo, ClientConnection connection, boolean checkActive, boolean checkTokenType, String checkAudience, boolean isCookie, String tokenString, HttpHeaders headers, Predicate<? super AccessToken>... additionalChecks) {
try {
TokenVerifier<AccessToken> verifier = TokenVerifier.create(tokenString, AccessToken.class).withDefaultChecks().realmUrl(Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName())).checkActive(checkActive).checkTokenType(checkTokenType).withChecks(additionalChecks);
if (checkAudience != null) {
verifier.audience(checkAudience);
}
// Check token revocation in case of access token
if (checkTokenType) {
verifier.withChecks(new TokenManager.TokenRevocationCheck(session));
}
String kid = verifier.getHeader().getKeyId();
String algorithm = verifier.getHeader().getAlgorithm().name();
SignatureVerifierContext signatureVerifier = session.getProvider(SignatureProvider.class, algorithm).verifier(kid);
verifier.verifierContext(signatureVerifier);
AccessToken token = verifier.verify().getToken();
if (checkActive) {
if (!token.isActive() || token.getIssuedAt() < realm.getNotBefore()) {
logger.debug("Identity cookie expired");
return null;
}
}
UserSessionModel userSession = null;
UserModel user = null;
if (token.getSessionState() == null) {
user = TokenManager.lookupUserFromStatelessToken(session, realm, token);
if (!isUserValid(session, realm, user, token)) {
return null;
}
} else {
userSession = session.sessions().getUserSession(realm, token.getSessionState());
if (userSession != null) {
user = userSession.getUser();
if (!isUserValid(session, realm, user, token)) {
return null;
}
}
}
if (token.getSessionState() != null && !isSessionValid(realm, userSession)) {
// Check if accessToken was for the offline session.
if (!isCookie) {
UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
if (isOfflineSessionValid(realm, offlineUserSession)) {
user = offlineUserSession.getUser();
ClientModel client = realm.getClientByClientId(token.getIssuedFor());
if (!isClientValid(offlineUserSession, client, token)) {
return null;
}
return new AuthResult(user, offlineUserSession, token, client);
}
}
if (userSession != null)
backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
logger.debug("User session not active");
return null;
}
session.setAttribute("state_checker", token.getOtherClaims().get("state_checker"));
ClientModel client;
if (isCookie) {
client = null;
} else {
client = realm.getClientByClientId(token.getIssuedFor());
if (!isClientValid(userSession, client, token)) {
return null;
}
}
return new AuthResult(user, userSession, token, client);
} catch (VerificationException e) {
logger.debugf("Failed to verify identity token: %s", e.getMessage());
}
return null;
}
Aggregations