/** * Update the TOTP for this account. * * <p>form parameters: * * <p>totp - otp generated by authenticator totpSecret - totp secret to register * * @param formData * @return */ @Path("totp") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processTotpUpdate(final MultivaluedMap<String, String> formData) { if (auth == null) { return login("totp"); } require(AccountRoles.MANAGE_ACCOUNT); String action = formData.getFirst("submitAction"); if (action != null && action.equals("Cancel")) { setReferrerOnPage(); return account.createResponse(AccountPages.TOTP); } csrfCheck(formData); UserModel user = auth.getUser(); String totp = formData.getFirst("totp"); String totpSecret = formData.getFirst("totpSecret"); if (Validation.isBlank(totp)) { setReferrerOnPage(); return account.setError(Messages.MISSING_TOTP).createResponse(AccountPages.TOTP); } else if (!CredentialValidation.validOTP(realm, totp, totpSecret)) { setReferrerOnPage(); return account.setError(Messages.INVALID_TOTP).createResponse(AccountPages.TOTP); } UserCredentialModel credentials = new UserCredentialModel(); credentials.setType(realm.getOTPPolicy().getType()); credentials.setValue(totpSecret); session.users().updateCredential(realm, user, credentials); user.setOtpEnabled(true); // to update counter UserCredentialModel cred = new UserCredentialModel(); cred.setType(realm.getOTPPolicy().getType()); cred.setValue(totp); session.users().validCredentials(realm, user, cred); event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success(); setReferrerOnPage(); return account.setSuccess(Messages.SUCCESS_TOTP).createResponse(AccountPages.TOTP); }
@Path("log") @GET public Response logPage() { if (auth != null) { List<Event> events = eventStore .createQuery() .type(LOG_EVENTS) .user(auth.getUser().getId()) .maxResults(30) .getResultList(); for (Event e : events) { if (e.getDetails() != null) { Iterator<Map.Entry<String, String>> itr = e.getDetails().entrySet().iterator(); while (itr.hasNext()) { if (!LOG_DETAILS.contains(itr.next().getKey())) { itr.remove(); } } } } account.setEvents(events); } return forwardToPage("log", AccountPages.LOG); }
@Path("sessions") @GET public Response sessionsPage() { if (auth != null) { account.setSessions(session.sessions().getUserSessions(realm, auth.getUser())); } return forwardToPage("sessions", AccountPages.SESSIONS); }
@Path("password") @GET public Response passwordPage() { if (auth != null) { account.setPasswordSet(isPasswordSet(auth.getUser())); } return forwardToPage("password", AccountPages.PASSWORD); }
@Path("revoke-grant") @POST public Response processRevokeGrant(final MultivaluedMap<String, String> formData) { if (auth == null) { return login("applications"); } require(AccountRoles.MANAGE_ACCOUNT); csrfCheck(formData); String clientId = formData.getFirst("clientId"); if (clientId == null) { return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS); } ClientModel client = realm.getClientById(clientId); if (client == null) { return account.setError(Messages.CLIENT_NOT_FOUND).createResponse(AccountPages.APPLICATIONS); } // Revoke grant in UserModel UserModel user = auth.getUser(); user.revokeConsentForClient(client.getId()); OfflineTokenUtils.revokeOfflineToken(session, realm, user, client); // Logout clientSessions for this user and client AuthenticationManager.backchannelUserFromClient(session, realm, user, client, uriInfo, headers); event .event(EventType.REVOKE_GRANT) .client(auth.getClient()) .user(auth.getUser()) .detail(Details.REVOKED_CLIENT, client.getClientId()) .success(); setReferrerOnPage(); UriBuilder builder = Urls.accountBase(uriInfo.getBaseUri()).path(AccountService.class, "applicationsPage"); String referrer = uriInfo.getQueryParameters().getFirst("referrer"); if (referrer != null) { builder.queryParam("referrer", referrer); } URI location = builder.build(realm.getName()); return Response.seeOther(location).build(); }
private Response forwardToPage(String path, AccountPages page) { if (auth != null) { try { require(AccountRoles.MANAGE_ACCOUNT); } catch (ForbiddenException e) { return session .getProvider(LoginFormsProvider.class) .setError(Messages.NO_ACCESS) .createErrorPage(); } setReferrerOnPage(); return account.createResponse(page); } else { return login(path); } }
@Path("totp-remove") @GET public Response processTotpRemove(@QueryParam("stateChecker") String stateChecker) { if (auth == null) { return login("totp"); } require(AccountRoles.MANAGE_ACCOUNT); csrfCheck(stateChecker); UserModel user = auth.getUser(); user.setOtpEnabled(false); event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success(); setReferrerOnPage(); return account.setSuccess(Messages.SUCCESS_TOTP_REMOVED).createResponse(AccountPages.TOTP); }
@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(); } }
/** * Update account password * * <p>Form params: * * <p>password - old password password-new pasword-confirm * * @param formData * @return */ @Path("password") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) { if (auth == null) { return login("password"); } require(AccountRoles.MANAGE_ACCOUNT); String action = formData.getFirst("submitAction"); if (action != null && action.equals("Cancel")) { setReferrerOnPage(); return account.createResponse(AccountPages.PASSWORD); } csrfCheck(formData); UserModel user = auth.getUser(); boolean requireCurrent = isPasswordSet(user); account.setPasswordSet(requireCurrent); String password = formData.getFirst("password"); String passwordNew = formData.getFirst("password-new"); String passwordConfirm = formData.getFirst("password-confirm"); if (requireCurrent) { if (Validation.isBlank(password)) { setReferrerOnPage(); return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD); } UserCredentialModel cred = UserCredentialModel.password(password); if (!session.users().validCredentials(realm, user, cred)) { setReferrerOnPage(); return account .setError(Messages.INVALID_PASSWORD_EXISTING) .createResponse(AccountPages.PASSWORD); } } if (Validation.isEmpty(passwordNew)) { setReferrerOnPage(); return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD); } if (!passwordNew.equals(passwordConfirm)) { setReferrerOnPage(); return account .setError(Messages.INVALID_PASSWORD_CONFIRM) .createResponse(AccountPages.PASSWORD); } try { session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew)); } catch (ModelReadOnlyException mre) { setReferrerOnPage(); return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD); } catch (ModelException me) { logger.error("Failed to update password", me); setReferrerOnPage(); return account .setError(me.getMessage(), me.getParameters()) .createResponse(AccountPages.PASSWORD); } catch (Exception ape) { logger.error("Failed to update password", ape); setReferrerOnPage(); return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD); } List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user); for (UserSessionModel s : sessions) { if (!s.getId().equals(auth.getSession().getId())) { AuthenticationManager.backchannelLogout( session, realm, s, uriInfo, clientConnection, headers, true); } } event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success(); setReferrerOnPage(); return account .setPasswordSet(true) .setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED) .createResponse(AccountPages.PASSWORD); }
/** * Update account information. * * <p>Form params: * * <p>firstName lastName email * * @param formData * @return */ @Path("/") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processAccountUpdate(final MultivaluedMap<String, String> formData) { if (auth == null) { return login(null); } require(AccountRoles.MANAGE_ACCOUNT); String action = formData.getFirst("submitAction"); if (action != null && action.equals("Cancel")) { setReferrerOnPage(); return account.createResponse(AccountPages.ACCOUNT); } csrfCheck(formData); UserModel user = auth.getUser(); List<FormMessage> errors = Validation.validateUpdateProfileForm(realm, formData); if (errors != null && !errors.isEmpty()) { setReferrerOnPage(); return account .setErrors(errors) .setProfileFormData(formData) .createResponse(AccountPages.ACCOUNT); } try { if (realm.isEditUsernameAllowed()) { String username = formData.getFirst("username"); UserModel existing = session.users().getUserByUsername(username, realm); if (existing != null && !existing.getId().equals(user.getId())) { throw new ModelDuplicateException(Messages.USERNAME_EXISTS); } user.setUsername(username); } user.setFirstName(formData.getFirst("firstName")); user.setLastName(formData.getFirst("lastName")); String email = formData.getFirst("email"); String oldEmail = user.getEmail(); boolean emailChanged = oldEmail != null ? !oldEmail.equals(email) : email != null; if (emailChanged) { UserModel existing = session.users().getUserByEmail(email, realm); if (existing != null && !existing.getId().equals(user.getId())) { throw new ModelDuplicateException(Messages.EMAIL_EXISTS); } } user.setEmail(email); AttributeFormDataProcessor.process(formData, realm, user); event.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()).success(); if (emailChanged) { user.setEmailVerified(false); event .clone() .event(EventType.UPDATE_EMAIL) .detail(Details.PREVIOUS_EMAIL, oldEmail) .detail(Details.UPDATED_EMAIL, email) .success(); } setReferrerOnPage(); return account.setSuccess(Messages.ACCOUNT_UPDATED).createResponse(AccountPages.ACCOUNT); } catch (ModelReadOnlyException roe) { setReferrerOnPage(); return account .setError(Messages.READ_ONLY_USER) .setProfileFormData(formData) .createResponse(AccountPages.ACCOUNT); } catch (ModelDuplicateException mde) { setReferrerOnPage(); return account .setError(mde.getMessage()) .setProfileFormData(formData) .createResponse(AccountPages.ACCOUNT); } }
protected void setReferrerOnPage() { String[] referrer = getReferrer(); if (referrer != null) { account.setReferrer(referrer); } }
public void init() { eventStore = session.getProvider(EventStoreProvider.class); account = session .getProvider(AccountProvider.class) .setRealm(realm) .setUriInfo(uriInfo) .setHttpHeaders(headers); AuthenticationManager.AuthResult authResult = authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers); if (authResult != null) { auth = new Auth( realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), false); } else { authResult = authManager.authenticateIdentityCookie(session, realm); if (authResult != null) { auth = new Auth( realm, authResult.getToken(), authResult.getUser(), client, authResult.getSession(), true); updateCsrfChecks(); account.setStateChecker(stateChecker); } } String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri()); // don't allow cors requests unless they were authenticated by an access token // This is to prevent CSRF attacks. if (auth != null && auth.isCookieAuthenticated()) { String origin = headers.getRequestHeaders().getFirst("Origin"); if (origin != null && !requestOrigin.equals(origin)) { throw new ForbiddenException(); } if (!request.getHttpMethod().equals("GET")) { String referrer = headers.getRequestHeaders().getFirst("Referer"); if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) { throw new ForbiddenException(); } } } if (authResult != null) { UserSessionModel userSession = authResult.getSession(); if (userSession != null) { boolean associated = false; for (ClientSessionModel c : userSession.getClientSessions()) { if (c.getClient().equals(client)) { auth.setClientSession(c); associated = true; break; } } if (!associated) { ClientSessionModel clientSession = session.sessions().createClientSession(realm, client); clientSession.setUserSession(userSession); auth.setClientSession(clientSession); } } account.setUser(auth.getUser()); } boolean eventsEnabled = eventStore != null && realm.isEventsEnabled(); // todo find out from federation if password is updatable account.setFeatures(realm.isIdentityFederationEnabled(), eventsEnabled, true); }