use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.
the class SessionCodeChecks method initialVerify.
public boolean initialVerify() {
// Basic realm checks and authenticationSession retrieve
authSession = initialVerifyAuthSession();
if (authSession == null) {
return false;
}
// Check cached response from previous action request
response = BrowserHistoryHelper.getInstance().loadSavedResponse(session, authSession);
if (response != null) {
return false;
}
// Client checks
event.detail(Details.CODE_ID, authSession.getParentSession().getId());
ClientModel client = authSession.getClient();
if (client == null) {
event.error(Errors.CLIENT_NOT_FOUND);
response = ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.UNKNOWN_LOGIN_REQUESTER);
clientCode.removeExpiredClientSession();
return false;
}
event.client(client);
session.getContext().setClient(client);
if (!client.isEnabled()) {
event.error(Errors.CLIENT_DISABLED);
response = ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.LOGIN_REQUESTER_NOT_ENABLED);
clientCode.removeExpiredClientSession();
return false;
}
// Check if it's action or not
if (code == null) {
String lastExecFromSession = authSession.getAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
String lastFlow = authSession.getAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH);
// Check if we transitted between flows (eg. clicking "register" on login screen)
if (execution == null && !flowPath.equals(lastFlow)) {
logger.debugf("Transition between flows! Current flow: %s, Previous flow: %s", flowPath, lastFlow);
// Don't allow moving to different flow if I am on requiredActions already
if (AuthenticationSessionModel.Action.AUTHENTICATE.name().equals(authSession.getAction())) {
authSession.setAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH, flowPath);
authSession.removeAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION);
lastExecFromSession = null;
}
}
if (execution == null || execution.equals(lastExecFromSession)) {
// Allow refresh of previous page
clientCode = new ClientSessionCode<>(session, realm, authSession);
actionRequest = false;
// Allow refresh, but rewrite browser history
if (execution == null && lastExecFromSession != null) {
logger.debugf("Parameter 'execution' is not in the request, but flow wasn't changed. Will update browser history");
request.setAttribute(BrowserHistoryHelper.SHOULD_UPDATE_BROWSER_HISTORY, true);
}
return true;
} else {
response = showPageExpired(authSession);
return false;
}
} else {
ClientSessionCode.ParseResult<AuthenticationSessionModel> result = ClientSessionCode.parseResult(code, tabId, session, realm, client, event, authSession);
clientCode = result.getCode();
if (clientCode == null) {
// In case that is replayed action, but sent to the same FORM like actual FORM, we just re-render the page
if (ObjectUtil.isEqualOrBothNull(execution, authSession.getAuthNote(AuthenticationProcessor.CURRENT_AUTHENTICATION_EXECUTION))) {
String latestFlowPath = authSession.getAuthNote(AuthenticationProcessor.CURRENT_FLOW_PATH);
URI redirectUri = getLastExecutionUrl(latestFlowPath, execution, tabId);
logger.debugf("Invalid action code, but execution matches. So just redirecting to %s", redirectUri);
authSession.setAuthNote(LoginActionsService.FORWARDED_ERROR_MESSAGE_NOTE, Messages.EXPIRED_ACTION);
response = Response.status(Response.Status.FOUND).location(redirectUri).build();
} else {
response = showPageExpired(authSession);
}
return false;
}
actionRequest = true;
if (execution != null) {
authSession.setAuthNote(AuthenticationProcessor.LAST_PROCESSED_EXECUTION, execution);
}
return true;
}
}
use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.
the class ClientScopeEvaluateResource method sessionAware.
private <R> R sessionAware(UserModel user, String scopeParam, BiFunction<UserSessionModel, ClientSessionContext, R> function) {
AuthenticationSessionModel authSession = null;
AuthenticationSessionManager authSessionManager = new AuthenticationSessionManager(session);
try {
RootAuthenticationSessionModel rootAuthSession = authSessionManager.createAuthenticationSession(realm, false);
authSession = rootAuthSession.createAuthenticationSession(client);
authSession.setAuthenticatedUser(user);
authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName()));
authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scopeParam);
UserSessionModel userSession = session.sessions().createUserSession(authSession.getParentSession().getId(), realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "example-auth", false, null, null, UserSessionModel.SessionPersistenceState.TRANSIENT);
AuthenticationManager.setClientScopesInSession(authSession);
ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(session, userSession, authSession);
return function.apply(userSession, clientSessionCtx);
} finally {
if (authSession != null) {
authSessionManager.removeAuthenticationSession(realm, authSession, false);
}
}
}
use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.
the class AuthenticationSessionTest method testLimitAuthSessions.
@Test
public void testLimitAuthSessions() {
RootAuthenticationSessionModel ras = withRealm(realmId, (session, realm) -> session.authenticationSessions().createRootAuthenticationSession(realm));
List<String> tabIds = withRealm(realmId, (session, realm) -> {
ClientModel client = realm.getClientByClientId("test-app");
return IntStream.range(0, 300).mapToObj(i -> {
Time.setOffset(i);
return ras.createAuthenticationSession(client);
}).map(AuthenticationSessionModel::getTabId).collect(Collectors.toList());
});
withRealm(realmId, (session, realm) -> {
ClientModel client = realm.getClientByClientId("test-app");
// create 301st auth session
AuthenticationSessionModel as = ras.createAuthenticationSession(client);
Assert.assertEquals(as, ras.getAuthenticationSession(client, as.getTabId()));
// assert the first authentication session was deleted
Assert.assertNull(ras.getAuthenticationSession(client, tabIds.get(0)));
return null;
});
}
use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.
the class AuthenticatorUtilTest method variousFactoryProviders.
@Test
public void variousFactoryProviders() {
testingClient.server().run(session -> {
RealmModel realm = session.realms().getRealm(TEST_REALM_NAME);
assertThat(realm, notNullValue());
ClientModel client = realm.getClientByClientId("test-app");
assertThat(client, notNullValue());
AuthenticationSessionModel authSession = session.authenticationSessions().createRootAuthenticationSession(realm).createAuthenticationSession(client);
assertThat(authSession, notNullValue());
Set<String> callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories, Matchers.empty());
AuthenticatorUtil.setAuthCallbacksFactoryIds(authSession, "factory1");
callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories.size(), is(1));
String note = authSession.getAuthNote(AuthenticatorUtil.CALLBACKS_FACTORY_IDS_NOTE);
assertThat(note, notNullValue());
assertThat(note, is("factory1"));
AuthenticatorUtil.setAuthCallbacksFactoryIds(authSession, "factory2");
callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories.size(), is(2));
note = authSession.getAuthNote(AuthenticatorUtil.CALLBACKS_FACTORY_IDS_NOTE);
assertThat(note, notNullValue());
assertThat(note, is("factory1" + Constants.CFG_DELIMITER + "factory2"));
AuthenticatorUtil.setAuthCallbacksFactoryIds(authSession, "factory1");
callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories.size(), is(2));
note = authSession.getAuthNote(AuthenticatorUtil.CALLBACKS_FACTORY_IDS_NOTE);
assertThat(note, notNullValue());
assertThat(note, is("factory1" + Constants.CFG_DELIMITER + "factory2"));
AuthenticatorUtil.setAuthCallbacksFactoryIds(authSession, "");
callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories.size(), is(2));
note = authSession.getAuthNote(AuthenticatorUtil.CALLBACKS_FACTORY_IDS_NOTE);
assertThat(note, notNullValue());
assertThat(note, is("factory1" + Constants.CFG_DELIMITER + "factory2"));
AuthenticatorUtil.setAuthCallbacksFactoryIds(authSession, null);
callbacksFactories = AuthenticatorUtil.getAuthCallbacksFactoryIds(authSession);
assertThat(callbacksFactories, notNullValue());
assertThat(callbacksFactories.size(), is(2));
note = authSession.getAuthNote(AuthenticatorUtil.CALLBACKS_FACTORY_IDS_NOTE);
assertThat(note, notNullValue());
assertThat(note, is("factory1" + Constants.CFG_DELIMITER + "factory2"));
});
}
use of org.keycloak.sessions.AuthenticationSessionModel in project keycloak by keycloak.
the class MSADUserAccountControlStorageMapper method processAuthErrorCode.
protected boolean processAuthErrorCode(String errorCode, UserModel user) {
logger.debugf("MSAD Error code is '%s' after failed LDAP login of user '%s'. Realm is '%s'", errorCode, user.getUsername(), getRealmName());
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
if (errorCode.equals("532") || errorCode.equals("773")) {
// User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action to authenticationSession
if (user.getRequiredActionsStream().noneMatch(action -> Objects.equals(action, UserModel.RequiredAction.UPDATE_PASSWORD.name()))) {
// This usually happens when 532 was returned, which means that "pwdLastSet" is set to some positive value, which is older than MSAD password expiration policy.
AuthenticationSessionModel authSession = session.getContext().getAuthenticationSession();
if (authSession != null) {
if (authSession.getRequiredActions().stream().noneMatch(action -> Objects.equals(action, UserModel.RequiredAction.UPDATE_PASSWORD.name()))) {
logger.debugf("Adding requiredAction UPDATE_PASSWORD to the authenticationSession of user %s", user.getUsername());
authSession.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
} else {
// Just a fallback. It should not happen during normal authentication process
logger.debugf("Adding requiredAction UPDATE_PASSWORD to the user %s", user.getUsername());
user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
}
} else {
// This usually happens when "773" error code is returned by MSAD. This typically happens when "pwdLastSet" is set to 0 and password was manually set
// by administrator (or user) to expire
logger.tracef("Skip adding required action UPDATE_PASSWORD. It was already set on user '%s' in realm '%s'", user.getUsername(), getRealmName());
}
return true;
} else if (errorCode.equals("533")) {
// User is disabled in MSAD. Set him to disabled in KC as well
if (user.isEnabled()) {
user.setEnabled(false);
}
return true;
} else if (errorCode.equals("775")) {
logger.warnf("Locked user '%s' attempt to login. Realm is '%s'", user.getUsername(), getRealmName());
}
}
return false;
}
Aggregations