use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.
the class AuthenticationProcessor method generateCode.
public String generateCode() {
ClientSessionCode accessCode = new ClientSessionCode(session, getRealm(), getAuthenticationSession());
authenticationSession.getParentSession().setTimestamp(Time.currentTime());
return accessCode.getOrGenerateCode();
}
use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.
the class LoginActionsService method redirectToAfterBrokerLoginEndpoint.
public static Response redirectToAfterBrokerLoginEndpoint(KeycloakSession session, RealmModel realm, UriInfo uriInfo, AuthenticationSessionModel authSession, boolean firstBrokerLogin) {
ClientSessionCode<AuthenticationSessionModel> accessCode = new ClientSessionCode<>(session, realm, authSession);
authSession.getParentSession().setTimestamp(Time.currentTime());
String clientId = authSession.getClient().getClientId();
String tabId = authSession.getTabId();
URI redirect = firstBrokerLogin ? Urls.identityProviderAfterFirstBrokerLogin(uriInfo.getBaseUri(), realm.getName(), accessCode.getOrGenerateCode(), clientId, tabId) : Urls.identityProviderAfterPostBrokerLogin(uriInfo.getBaseUri(), realm.getName(), accessCode.getOrGenerateCode(), clientId, tabId);
logger.debugf("Redirecting to '%s' ", redirect);
return Response.status(302).location(redirect).build();
}
use of org.keycloak.services.managers.ClientSessionCode 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.services.managers.ClientSessionCode in project keycloak by keycloak.
the class IdentityBrokerService method performLogin.
@GET
@NoCache
@Path("/{provider_id}/login")
public Response performLogin(@PathParam("provider_id") String providerId, @QueryParam(LoginActionsService.SESSION_CODE) String code, @QueryParam("client_id") String clientId, @QueryParam(Constants.TAB_ID) String tabId, @QueryParam(OIDCLoginProtocol.LOGIN_HINT_PARAM) String loginHint) {
this.event.detail(Details.IDENTITY_PROVIDER, providerId);
if (isDebugEnabled()) {
logger.debugf("Sending authentication request to identity provider [%s].", providerId);
}
try {
AuthenticationSessionModel authSession = parseSessionCode(code, clientId, tabId);
ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
if (identityProviderModel == null) {
throw new IdentityBrokerException("Identity Provider [" + providerId + "] not found.");
}
if (identityProviderModel.isLinkOnly()) {
throw new IdentityBrokerException("Identity Provider [" + providerId + "] is not allowed to perform a login.");
}
if (clientSessionCode != null && clientSessionCode.getClientSession() != null && loginHint != null) {
clientSessionCode.getClientSession().setClientNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, loginHint);
}
IdentityProviderFactory providerFactory = getIdentityProviderFactory(session, identityProviderModel);
IdentityProvider identityProvider = providerFactory.create(session, identityProviderModel);
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(Response.Status.BAD_GATEWAY, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
} catch (Exception e) {
return redirectToErrorPage(Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
}
return redirectToErrorPage(Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
}
use of org.keycloak.services.managers.ClientSessionCode in project keycloak by keycloak.
the class LoginTimeoutValidationTest method testIsLoginTimeoutValid.
@Test
@ModelTest
public void testIsLoginTimeoutValid(KeycloakSession keycloakSession) {
RealmModel realm = keycloakSession.realms().getRealmByName("test");
UserSessionModel userSession = keycloakSession.sessions().createUserSession(realm, keycloakSession.users().getUserByUsername(realm, "user1"), "user1", "127.0.0.1", "form", true, null, null);
ClientModel client = realm.getClientByClientId("account");
AuthenticationSessionModel authSession = keycloakSession.authenticationSessions().createRootAuthenticationSession(realm).createAuthenticationSession(client);
ClientSessionCode clientSessionCode = new ClientSessionCode(keycloakSession, realm, authSession);
/*
* KEYCLOAK-10636 Large Login timeout causes login failure
* realm > Realm setting > Tokens > Login timeout
*/
// Login timeout
int accessCodeLifespanLoginOrig = realm.getAccessCodeLifespanLogin();
realm.setAccessCodeLifespanLogin(Integer.MAX_VALUE);
Assert.assertTrue("Login validataion with large Login Timeout failed", clientSessionCode.isActionActive(ClientSessionCode.ActionType.LOGIN));
realm.setAccessCodeLifespanLogin(accessCodeLifespanLoginOrig);
/*
* KEYCLOAK-10637 Large Login Action timeout causes login failure
* realm > Realm setting > Tokens > Login Action timeout
*/
// Login Action timeout
int accessCodeLifespanUserActionOrig = realm.getAccessCodeLifespanUserAction();
realm.setAccessCodeLifespanUserAction(Integer.MAX_VALUE);
Assert.assertTrue("Login validataion with large Login Action Timeout failed", clientSessionCode.isActionActive(ClientSessionCode.ActionType.USER));
realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserActionOrig);
}
Aggregations