/** * Endpoint for executing reset credentials flow. If code is null, a client session is created * with the account service as the client. Successful reset sends you to the account page. Note, * account service must be enabled. * * @param code * @param execution * @return */ @Path(RESET_CREDENTIALS_PATH) @GET public Response resetCredentialsGET( @QueryParam("code") String code, @QueryParam("execution") String execution) { // we allow applications to link to reset credentials without going through OAuth or SAML // handshakes // if (code == null) { if (!realm.isResetPasswordAllowed()) { event.event(EventType.RESET_PASSWORD); event.error(Errors.NOT_ALLOWED); return ErrorPage.error(session, Messages.RESET_CREDENTIAL_NOT_ALLOWED); } // set up the account service as the endpoint to call. ClientModel client = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID); ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name()); clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret()); // clientSession.setNote(AuthenticationManager.END_AFTER_REQUIRED_ACTIONS, "true"); clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL); String redirectUri = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString(); clientSession.setRedirectUri(redirectUri); clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name()); clientSession.setNote(ClientSessionCode.ACTION_KEY, KeycloakModelUtils.generateCodeSecret()); clientSession.setNote(OIDCLoginProtocol.RESPONSE_TYPE_PARAM, OAuth2Constants.CODE); clientSession.setNote(OIDCLoginProtocol.REDIRECT_URI_PARAM, redirectUri); clientSession.setNote( OIDCLoginProtocol.ISSUER, Urls.realmIssuer(uriInfo.getBaseUri(), realm.getName())); return processResetCredentials(null, clientSession, null); } return resetCredentials(code, execution); }
private ClientSessionModel createClientSession( UserModel user, String redirectUri, String clientId) { if (!user.isEnabled()) { throw new WebApplicationException( ErrorResponse.error("User is disabled", Response.Status.BAD_REQUEST)); } if (redirectUri != null && clientId == null) { throw new WebApplicationException( ErrorResponse.error("Client id missing", Response.Status.BAD_REQUEST)); } if (clientId == null) { clientId = Constants.ACCOUNT_MANAGEMENT_CLIENT_ID; } ClientModel client = realm.getClientByClientId(clientId); if (client == null || !client.isEnabled()) { throw new WebApplicationException( ErrorResponse.error(clientId + " not enabled", Response.Status.BAD_REQUEST)); } String redirect; if (redirectUri != null) { redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri, realm, client); if (redirect == null) { throw new WebApplicationException( ErrorResponse.error("Invalid redirect uri.", Response.Status.BAD_REQUEST)); } } else { redirect = Urls.accountBase(uriInfo.getBaseUri()).path("/").build(realm.getName()).toString(); } UserSessionModel userSession = session .sessions() .createUserSession( realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "form", false, null, null); // audit.session(userSession); ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setAuthMethod(OIDCLoginProtocol.LOGIN_PROTOCOL); clientSession.setRedirectUri(redirect); clientSession.setUserSession(userSession); return clientSession; }
@GET @Path("clients/{client}") @Produces(MediaType.TEXT_HTML) public Response idpInitiatedSSO( @PathParam("client") String clientUrlName, @QueryParam("RelayState") String relayState) { event.event(EventType.LOGIN); CacheControlUtil.noBackButtonCacheControlHeader(); ClientModel client = null; for (ClientModel c : realm.getClients()) { String urlName = c.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_URL_NAME); if (urlName == null) continue; if (urlName.equals(clientUrlName)) { client = c; break; } } if (client == null) { event.error(Errors.CLIENT_NOT_FOUND); return ErrorPage.error(session, Messages.CLIENT_NOT_FOUND); } if (client.getManagementUrl() == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) == null) { logger.error("SAML assertion consumer url not set up"); event.error(Errors.INVALID_REDIRECT_URI); return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI); } String bindingType = SamlProtocol.SAML_POST_BINDING; if (client.getManagementUrl() == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE) == null && client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE) != null) { bindingType = SamlProtocol.SAML_REDIRECT_BINDING; } String redirect = null; if (bindingType.equals(SamlProtocol.SAML_REDIRECT_BINDING)) { redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE); } else { redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE); } if (redirect == null) { redirect = client.getManagementUrl(); } ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL); clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name()); clientSession.setNote(SamlProtocol.SAML_BINDING, SamlProtocol.SAML_POST_BINDING); clientSession.setNote(SamlProtocol.SAML_IDP_INITIATED_LOGIN, "true"); clientSession.setRedirectUri(redirect); if (relayState == null) { relayState = client.getAttribute(SamlProtocol.SAML_IDP_INITIATED_SSO_RELAY_STATE); } if (relayState != null && !relayState.trim().equals("")) { clientSession.setNote(GeneralConstants.RELAY_STATE, relayState); } return newBrowserAuthentication(clientSession, false, false); }
protected Response loginRequest( String relayState, AuthnRequestType requestAbstractType, ClientModel client) { SamlClient samlClient = new SamlClient(client); // validate destination if (requestAbstractType.getDestination() != null && !uriInfo.getAbsolutePath().equals(requestAbstractType.getDestination())) { event.detail(Details.REASON, "invalid_destination"); event.error(Errors.INVALID_SAML_AUTHN_REQUEST); return ErrorPage.error(session, Messages.INVALID_REQUEST); } String bindingType = getBindingType(requestAbstractType); if (samlClient.forcePostBinding()) bindingType = SamlProtocol.SAML_POST_BINDING; String redirect = null; URI redirectUri = requestAbstractType.getAssertionConsumerServiceURL(); if (redirectUri != null && !"null".equals(redirectUri)) { // "null" is for testing purposes redirect = RedirectUtils.verifyRedirectUri(uriInfo, redirectUri.toString(), realm, client); } else { if (bindingType.equals(SamlProtocol.SAML_POST_BINDING)) { redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_POST_ATTRIBUTE); } else { redirect = client.getAttribute(SamlProtocol.SAML_ASSERTION_CONSUMER_URL_REDIRECT_ATTRIBUTE); } if (redirect == null) { redirect = client.getManagementUrl(); } } if (redirect == null) { event.error(Errors.INVALID_REDIRECT_URI); return ErrorPage.error(session, Messages.INVALID_REDIRECT_URI); } ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setAuthMethod(SamlProtocol.LOGIN_PROTOCOL); clientSession.setRedirectUri(redirect); clientSession.setAction(ClientSessionModel.Action.AUTHENTICATE.name()); clientSession.setNote(SamlProtocol.SAML_BINDING, bindingType); clientSession.setNote(GeneralConstants.RELAY_STATE, relayState); clientSession.setNote(SamlProtocol.SAML_REQUEST_ID, requestAbstractType.getID()); // Handle NameIDPolicy from SP NameIDPolicyType nameIdPolicy = requestAbstractType.getNameIDPolicy(); if (nameIdPolicy != null && !samlClient.forceNameIDFormat()) { String nameIdFormat = nameIdPolicy.getFormat().toString(); // TODO: Handle AllowCreate too, relevant for persistent NameID. if (isSupportedNameIdFormat(nameIdFormat)) { clientSession.setNote(GeneralConstants.NAMEID_FORMAT, nameIdFormat); } else { event.detail(Details.REASON, "unsupported_nameid_format"); event.error(Errors.INVALID_SAML_AUTHN_REQUEST); return ErrorPage.error(session, Messages.UNSUPPORTED_NAME_ID_FORMAT); } } // Reading subject/nameID in the saml request SubjectType subject = requestAbstractType.getSubject(); if (subject != null) { SubjectType.STSubType subType = subject.getSubType(); if (subType != null) { BaseIDAbstractType baseID = subject.getSubType().getBaseID(); if (baseID != null && baseID instanceof NameIDType) { NameIDType nameID = (NameIDType) baseID; clientSession.setNote(OIDCLoginProtocol.LOGIN_HINT_PARAM, nameID.getValue()); } } } return newBrowserAuthentication( clientSession, requestAbstractType.isIsPassive(), redirectToAuthentication); }
@Path("federated-identity-update") @GET public Response processFederatedIdentityUpdate( @QueryParam("action") String action, @QueryParam("provider_id") String providerId, @QueryParam("stateChecker") String stateChecker) { if (auth == null) { return login("identity"); } require(AccountRoles.MANAGE_ACCOUNT); csrfCheck(stateChecker); UserModel user = auth.getUser(); if (Validation.isEmpty(providerId)) { setReferrerOnPage(); return account .setError(Messages.MISSING_IDENTITY_PROVIDER) .createResponse(AccountPages.FEDERATED_IDENTITY); } AccountSocialAction accountSocialAction = AccountSocialAction.getAction(action); if (accountSocialAction == null) { setReferrerOnPage(); return account .setError(Messages.INVALID_FEDERATED_IDENTITY_ACTION) .createResponse(AccountPages.FEDERATED_IDENTITY); } boolean hasProvider = false; for (IdentityProviderModel model : realm.getIdentityProviders()) { if (model.getAlias().equals(providerId)) { hasProvider = true; } } if (!hasProvider) { setReferrerOnPage(); return account .setError(Messages.IDENTITY_PROVIDER_NOT_FOUND) .createResponse(AccountPages.FEDERATED_IDENTITY); } if (!user.isEnabled()) { setReferrerOnPage(); return account .setError(Messages.ACCOUNT_DISABLED) .createResponse(AccountPages.FEDERATED_IDENTITY); } switch (accountSocialAction) { case ADD: String redirectUri = UriBuilder.fromUri( Urls.accountFederatedIdentityPage(uriInfo.getBaseUri(), realm.getName())) .build() .toString(); try { ClientSessionModel clientSession = auth.getClientSession(); ClientSessionCode clientSessionCode = new ClientSessionCode(realm, clientSession); clientSessionCode.setAction(ClientSessionModel.Action.AUTHENTICATE.name()); clientSession.setRedirectUri(redirectUri); clientSession.setNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString()); return Response.temporaryRedirect( Urls.identityProviderAuthnRequest( this.uriInfo.getBaseUri(), providerId, realm.getName(), clientSessionCode.getCode())) .build(); } catch (Exception spe) { setReferrerOnPage(); return account .setError(Messages.IDENTITY_PROVIDER_REDIRECT_ERROR) .createResponse(AccountPages.FEDERATED_IDENTITY); } case REMOVE: FederatedIdentityModel link = session.users().getFederatedIdentity(user, providerId, realm); if (link != null) { // Removing last social provider is not possible if you don't have other possibility to // authenticate if (session.users().getFederatedIdentities(user, realm).size() > 1 || user.getFederationLink() != null || isPasswordSet(user)) { session.users().removeFederatedIdentity(realm, user, providerId); logger.debugv( "Social provider {0} removed successfully from user {1}", providerId, user.getUsername()); event .event(EventType.REMOVE_FEDERATED_IDENTITY) .client(auth.getClient()) .user(auth.getUser()) .detail(Details.USERNAME, link.getUserId() + "@" + link.getIdentityProvider()) .success(); setReferrerOnPage(); return account .setSuccess(Messages.IDENTITY_PROVIDER_REMOVED) .createResponse(AccountPages.FEDERATED_IDENTITY); } else { setReferrerOnPage(); return account .setError(Messages.FEDERATED_IDENTITY_REMOVING_LAST_PROVIDER) .createResponse(AccountPages.FEDERATED_IDENTITY); } } else { setReferrerOnPage(); return account .setError(Messages.FEDERATED_IDENTITY_NOT_ACTIVE) .createResponse(AccountPages.FEDERATED_IDENTITY); } default: throw new IllegalArgumentException(); } }