Rename audit to events
This commit is contained in:
1 parent
b50ab14a0a
commit
3bfe3d256e
143 files changed
+1132
-1142
No files matched your search
+1
-1
@@ -39,7 +39,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-audit-api</artifactId>
|
||||
<artifactId>keycloak-events-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package org.keycloak.services.managers;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class AuditManager {
|
||||
|
||||
private Logger log = Logger.getLogger(AuditManager.class);
|
||||
|
||||
private RealmModel realm;
|
||||
private KeycloakSession session;
|
||||
private ClientConnection clientConnection;
|
||||
|
||||
public AuditManager(RealmModel realm, KeycloakSession session, ClientConnection clientConnection) {
|
||||
this.realm = realm;
|
||||
this.session = session;
|
||||
this.clientConnection = clientConnection;
|
||||
}
|
||||
|
||||
public Audit createAudit() {
|
||||
List<AuditListener> listeners = new LinkedList<AuditListener>();
|
||||
|
||||
if (realm.isAuditEnabled()) {
|
||||
AuditProvider auditProvider = session.getProvider(AuditProvider.class);
|
||||
if (auditProvider != null) {
|
||||
listeners.add(auditProvider);
|
||||
} else {
|
||||
log.error("Audit enabled, but no audit provider configured");
|
||||
}
|
||||
}
|
||||
|
||||
if (realm.getAuditListeners() != null) {
|
||||
for (String id : realm.getAuditListeners()) {
|
||||
AuditListener listener = session.getProvider(AuditListener.class, id);
|
||||
if (listener != null) {
|
||||
listeners.add(listener);
|
||||
} else {
|
||||
log.error("Audit listener '" + id + "' registered, but not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Audit(listeners, realm, clientConnection.getRemoteAddr());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class BruteForceProtector implements Runnable {
|
||||
session.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed processing event", e);
|
||||
logger.error("Failed processing type", e);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
@@ -228,7 +228,7 @@ public class BruteForceProtector implements Runnable {
|
||||
try {
|
||||
FailedLogin event = new FailedLogin(realm.getId(), username, clientConnection.getRemoteAddr());
|
||||
queue.offer(event);
|
||||
// wait a minimum of seconds for event to process so that a hacker
|
||||
// wait a minimum of seconds for type to process so that a hacker
|
||||
// cannot flood with failed logins and overwhelm the queue and not have notBefore updated to block next requests
|
||||
// todo failure HTTP responses should be queued via async HTTP
|
||||
event.latch.await(5, TimeUnit.SECONDS);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.keycloak.services.managers;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class EventsManager {
|
||||
|
||||
private Logger log = Logger.getLogger(EventsManager.class);
|
||||
|
||||
private RealmModel realm;
|
||||
private KeycloakSession session;
|
||||
private ClientConnection clientConnection;
|
||||
|
||||
public EventsManager(RealmModel realm, KeycloakSession session, ClientConnection clientConnection) {
|
||||
this.realm = realm;
|
||||
this.session = session;
|
||||
this.clientConnection = clientConnection;
|
||||
}
|
||||
|
||||
public EventBuilder createEventBuilder() {
|
||||
List<EventListenerProvider> listeners = new LinkedList<EventListenerProvider>();
|
||||
|
||||
if (realm.isEventsEnabled()) {
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
if (eventStore != null) {
|
||||
listeners.add(eventStore);
|
||||
} else {
|
||||
log.error("Events enabled, but no event store provider configured");
|
||||
}
|
||||
}
|
||||
|
||||
if (realm.getEventsListeners() != null) {
|
||||
for (String id : realm.getEventsListeners()) {
|
||||
EventListenerProvider listener = session.getProvider(EventListenerProvider.class, id);
|
||||
if (listener != null) {
|
||||
listeners.add(listener);
|
||||
} else {
|
||||
log.error("Event listener '" + id + "' registered, but provider not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new EventBuilder(listeners, realm, clientConnection.getRemoteAddr());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import org.keycloak.models.UserSessionProvider;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||
import org.keycloak.representations.idm.RealmAuditRepresentation;
|
||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.timer.TimerProvider;
|
||||
|
||||
@@ -155,11 +155,11 @@ public class RealmManager {
|
||||
return removed;
|
||||
}
|
||||
|
||||
public void updateRealmAudit(RealmAuditRepresentation rep, RealmModel realm) {
|
||||
realm.setAuditEnabled(rep.isAuditEnabled());
|
||||
realm.setAuditExpiration(rep.getAuditExpiration() != null ? rep.getAuditExpiration() : 0);
|
||||
if (rep.getAuditListeners() != null) {
|
||||
realm.setAuditListeners(new HashSet<String>(rep.getAuditListeners()));
|
||||
public void updateRealmEventsConfig(RealmEventsConfigRepresentation rep, RealmModel realm) {
|
||||
realm.setEventsEnabled(rep.isEventsEnabled());
|
||||
realm.setEventsExpiration(rep.getEventsExpiration() != null ? rep.getEventsExpiration() : 0);
|
||||
if (rep.getEventsListeners() != null) {
|
||||
realm.setEventsListeners(new HashSet<String>(rep.getEventsListeners()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ package org.keycloak.services.managers;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.jose.jws.JWSBuilder;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||
@@ -63,10 +63,10 @@ public class TokenManager {
|
||||
return new AccessCode(realm, clientSession);
|
||||
}
|
||||
|
||||
public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel client, String encodedRefreshToken, Audit audit) throws OAuthErrorException {
|
||||
public AccessToken refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel client, String encodedRefreshToken, EventBuilder event) throws OAuthErrorException {
|
||||
RefreshToken refreshToken = verifyRefreshToken(realm, encodedRefreshToken);
|
||||
|
||||
audit.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
|
||||
UserModel user = session.users().getUserById(refreshToken.getSubject(), realm);
|
||||
if (user == null) {
|
||||
@@ -290,8 +290,8 @@ public class TokenManager {
|
||||
return encodedToken;
|
||||
}
|
||||
|
||||
public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, Audit audit) {
|
||||
return new AccessTokenResponseBuilder(realm, client, audit);
|
||||
public AccessTokenResponseBuilder responseBuilder(RealmModel realm, ClientModel client, EventBuilder event) {
|
||||
return new AccessTokenResponseBuilder(realm, client, event);
|
||||
}
|
||||
|
||||
public class AccessTokenResponseBuilder {
|
||||
@@ -300,12 +300,12 @@ public class TokenManager {
|
||||
AccessToken accessToken;
|
||||
RefreshToken refreshToken;
|
||||
IDToken idToken;
|
||||
Audit audit;
|
||||
EventBuilder event;
|
||||
|
||||
public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, Audit audit) {
|
||||
public AccessTokenResponseBuilder(RealmModel realm, ClientModel client, EventBuilder event) {
|
||||
this.realm = realm;
|
||||
this.client = client;
|
||||
this.audit = audit;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public AccessTokenResponseBuilder accessToken(AccessToken accessToken) {
|
||||
@@ -379,14 +379,14 @@ public class TokenManager {
|
||||
|
||||
public AccessTokenResponse build() {
|
||||
if (accessToken != null) {
|
||||
audit.detail(Details.TOKEN_ID, accessToken.getId());
|
||||
event.detail(Details.TOKEN_ID, accessToken.getId());
|
||||
}
|
||||
|
||||
if (refreshToken != null) {
|
||||
if (audit.getEvent().getDetails().containsKey(Details.REFRESH_TOKEN_ID)) {
|
||||
audit.detail(Details.UPDATED_REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
if (event.getEvent().getDetails().containsKey(Details.REFRESH_TOKEN_ID)) {
|
||||
event.detail(Details.UPDATED_REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
} else {
|
||||
audit.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
event.detail(Details.REFRESH_TOKEN_ID, refreshToken.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@ import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.account.AccountPages;
|
||||
import org.keycloak.account.AccountProvider;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.Event;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Event;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
@@ -92,18 +92,18 @@ public class AccountService {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(AccountService.class);
|
||||
|
||||
private static final EventType[] AUDIT_EVENTS = {EventType.LOGIN, EventType.LOGOUT, EventType.REGISTER, EventType.REMOVE_SOCIAL_LINK, EventType.REMOVE_TOTP, EventType.SEND_RESET_PASSWORD,
|
||||
private static final EventType[] LOG_EVENTS = {EventType.LOGIN, EventType.LOGOUT, EventType.REGISTER, EventType.REMOVE_SOCIAL_LINK, EventType.REMOVE_TOTP, EventType.SEND_RESET_PASSWORD,
|
||||
EventType.SEND_VERIFY_EMAIL, EventType.SOCIAL_LINK, EventType.UPDATE_EMAIL, EventType.UPDATE_PASSWORD, EventType.UPDATE_PROFILE, EventType.UPDATE_TOTP, EventType.VERIFY_EMAIL};
|
||||
|
||||
private static final Set<String> AUDIT_DETAILS = new HashSet<String>();
|
||||
private static final Set<String> LOG_DETAILS = new HashSet<String>();
|
||||
static {
|
||||
AUDIT_DETAILS.add(Details.UPDATED_EMAIL);
|
||||
AUDIT_DETAILS.add(Details.EMAIL);
|
||||
AUDIT_DETAILS.add(Details.PREVIOUS_EMAIL);
|
||||
AUDIT_DETAILS.add(Details.USERNAME);
|
||||
AUDIT_DETAILS.add(Details.REMEMBER_ME);
|
||||
AUDIT_DETAILS.add(Details.REGISTER_METHOD);
|
||||
AUDIT_DETAILS.add(Details.AUTH_METHOD);
|
||||
LOG_DETAILS.add(Details.UPDATED_EMAIL);
|
||||
LOG_DETAILS.add(Details.EMAIL);
|
||||
LOG_DETAILS.add(Details.PREVIOUS_EMAIL);
|
||||
LOG_DETAILS.add(Details.USERNAME);
|
||||
LOG_DETAILS.add(Details.REMEMBER_ME);
|
||||
LOG_DETAILS.add(Details.REGISTER_METHOD);
|
||||
LOG_DETAILS.add(Details.AUTH_METHOD);
|
||||
}
|
||||
|
||||
private RealmModel realm;
|
||||
@@ -125,20 +125,20 @@ public class AccountService {
|
||||
|
||||
private final AppAuthManager authManager;
|
||||
private final ApplicationModel application;
|
||||
private Audit audit;
|
||||
private EventBuilder event;
|
||||
private AccountProvider account;
|
||||
private Auth auth;
|
||||
private AuditProvider auditProvider;
|
||||
private EventStoreProvider eventStore;
|
||||
|
||||
public AccountService(RealmModel realm, ApplicationModel application, Audit audit) {
|
||||
public AccountService(RealmModel realm, ApplicationModel application, EventBuilder event) {
|
||||
this.realm = realm;
|
||||
this.application = application;
|
||||
this.audit = audit;
|
||||
this.event = event;
|
||||
this.authManager = new AppAuthManager();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
auditProvider = session.getProvider(AuditProvider.class);
|
||||
eventStore = session.getProvider(EventStoreProvider.class);
|
||||
|
||||
account = session.getProvider(AccountProvider.class).setRealm(realm).setUriInfo(uriInfo);
|
||||
|
||||
@@ -170,10 +170,10 @@ public class AccountService {
|
||||
|
||||
}
|
||||
|
||||
boolean auditEnabled = auditProvider != null && realm.isAuditEnabled();
|
||||
boolean eventsEnabled = eventStore != null && realm.isEventsEnabled();
|
||||
|
||||
// todo find out from federation if password is updatable
|
||||
account.setFeatures(realm.isSocial(), auditEnabled, true);
|
||||
account.setFeatures(realm.isSocial(), eventsEnabled, true);
|
||||
}
|
||||
|
||||
public static UriBuilder accountServiceBaseUrl(UriInfo uriInfo) {
|
||||
@@ -282,12 +282,12 @@ public class AccountService {
|
||||
@GET
|
||||
public Response logPage() {
|
||||
if (auth != null) {
|
||||
List<Event> events = auditProvider.createQuery().event(AUDIT_EVENTS).user(auth.getUser().getId()).maxResults(30).getResultList();
|
||||
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 (!AUDIT_DETAILS.contains(itr.next().getKey())) {
|
||||
if (!LOG_DETAILS.contains(itr.next().getKey())) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
@@ -353,11 +353,11 @@ public class AccountService {
|
||||
|
||||
user.setEmail(formData.getFirst("email"));
|
||||
|
||||
audit.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()).success();
|
||||
event.event(EventType.UPDATE_PROFILE).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
if (emailChanged) {
|
||||
user.setEmailVerified(false);
|
||||
audit.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||
}
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("accountUpdated").createResponse(AccountPages.ACCOUNT);
|
||||
@@ -379,7 +379,7 @@ public class AccountService {
|
||||
UserModel user = auth.getUser();
|
||||
user.setTotp(false);
|
||||
|
||||
audit.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
event.event(EventType.REMOVE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("successTotpRemoved").createResponse(AccountPages.TOTP);
|
||||
@@ -455,7 +455,7 @@ public class AccountService {
|
||||
|
||||
user.setTotp(true);
|
||||
|
||||
audit.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("successTotp").createResponse(AccountPages.TOTP);
|
||||
@@ -525,7 +525,7 @@ public class AccountService {
|
||||
return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
|
||||
}
|
||||
|
||||
audit.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
|
||||
event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();
|
||||
|
||||
setReferrerOnPage();
|
||||
return account.setSuccess("accountPasswordUpdated").createResponse(AccountPages.PASSWORD);
|
||||
@@ -588,7 +588,7 @@ public class AccountService {
|
||||
|
||||
logger.debugv("Social provider {0} removed successfully from user {1}", providerId, user.getUsername());
|
||||
|
||||
audit.event(EventType.REMOVE_SOCIAL_LINK).client(auth.getClient()).user(auth.getUser())
|
||||
event.event(EventType.REMOVE_SOCIAL_LINK).client(auth.getClient()).user(auth.getUser())
|
||||
.detail(Details.USERNAME, link.getSocialUserId() + "@" + link.getSocialProvider())
|
||||
.success();
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.keycloak.services.managers.UsersSyncManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
import org.keycloak.services.scheduled.ClearExpiredAuditEvents;
|
||||
import org.keycloak.services.scheduled.ClearExpiredEvents;
|
||||
import org.keycloak.services.scheduled.ClearExpiredUserSessions;
|
||||
import org.keycloak.services.scheduled.ScheduledTaskRunner;
|
||||
import org.keycloak.services.util.JsonConfigProvider;
|
||||
@@ -147,7 +147,7 @@ public class KeycloakApplication extends Application {
|
||||
long interval = Config.scope("scheduled").getLong("interval", 60L) * 1000;
|
||||
|
||||
TimerProvider timer = sessionFactory.create().getProvider(TimerProvider.class);
|
||||
timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredAuditEvents()), interval, "ClearExpiredAuditEvents");
|
||||
timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredEvents()), interval, "ClearExpiredEvents");
|
||||
timer.schedule(new ScheduledTaskRunner(sessionFactory, new ClearExpiredUserSessions()), interval, "ClearExpiredUserSessions");
|
||||
new UsersSyncManager().bootstrapPeriodic(sessionFactory, timer);
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ import org.jboss.resteasy.spi.BadRequestException;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.managers.AuditManager;
|
||||
import org.keycloak.services.managers.EventsManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.BruteForceProtector;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
@@ -140,9 +140,9 @@ public class RealmsResource {
|
||||
public TokenService getTokenService(final @PathParam("realm") String name) {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = locateRealm(name, realmManager);
|
||||
Audit audit = new AuditManager(realm, session, clientConnection).createAudit();
|
||||
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
|
||||
AuthenticationManager authManager = new AuthenticationManager(protector);
|
||||
TokenService tokenService = new TokenService(realm, tokenManager, audit, authManager);
|
||||
TokenService tokenService = new TokenService(realm, tokenManager, event, authManager);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(tokenService);
|
||||
//resourceContext.initResource(tokenService);
|
||||
return tokenService;
|
||||
@@ -167,8 +167,8 @@ public class RealmsResource {
|
||||
throw new NotFoundException("account management not enabled");
|
||||
}
|
||||
|
||||
Audit audit = new AuditManager(realm, session, clientConnection).createAudit();
|
||||
AccountService accountService = new AccountService(realm, application, audit);
|
||||
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder();
|
||||
AccountService accountService = new AccountService(realm, application, event);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(accountService);
|
||||
//resourceContext.initResource(accountService);
|
||||
accountService.init();
|
||||
|
||||
+28
-28
@@ -25,10 +25,10 @@ import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.Errors;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.email.EmailException;
|
||||
import org.keycloak.email.EmailProvider;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
@@ -94,12 +94,12 @@ public class RequiredActionsService {
|
||||
|
||||
private TokenManager tokenManager;
|
||||
|
||||
private Audit audit;
|
||||
private EventBuilder event;
|
||||
|
||||
public RequiredActionsService(RealmModel realm, TokenManager tokenManager, Audit audit) {
|
||||
public RequiredActionsService(RealmModel realm, TokenManager tokenManager, EventBuilder event) {
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
this.audit = audit;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Path("profile")
|
||||
@@ -113,7 +113,7 @@ public class RequiredActionsService {
|
||||
|
||||
UserModel user = getUser(accessCode);
|
||||
|
||||
initAudit(accessCode);
|
||||
initEvent(accessCode);
|
||||
|
||||
String error = Validation.validateUpdateProfileForm(formData);
|
||||
if (error != null) {
|
||||
@@ -131,10 +131,10 @@ public class RequiredActionsService {
|
||||
|
||||
user.removeRequiredAction(RequiredAction.UPDATE_PROFILE);
|
||||
|
||||
audit.clone().event(EventType.UPDATE_PROFILE).success();
|
||||
event.clone().event(EventType.UPDATE_PROFILE).success();
|
||||
if (emailChanged) {
|
||||
user.setEmailVerified(false);
|
||||
audit.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, email).success();
|
||||
}
|
||||
|
||||
return redirectOauth(user, accessCode);
|
||||
@@ -151,7 +151,7 @@ public class RequiredActionsService {
|
||||
|
||||
UserModel user = getUser(accessCode);
|
||||
|
||||
initAudit(accessCode);
|
||||
initEvent(accessCode);
|
||||
|
||||
String totp = formData.getFirst("totp");
|
||||
String totpSecret = formData.getFirst("totpSecret");
|
||||
@@ -172,7 +172,7 @@ public class RequiredActionsService {
|
||||
|
||||
user.removeRequiredAction(RequiredAction.CONFIGURE_TOTP);
|
||||
|
||||
audit.clone().event(EventType.UPDATE_TOTP).success();
|
||||
event.clone().event(EventType.UPDATE_TOTP).success();
|
||||
|
||||
return redirectOauth(user, accessCode);
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class RequiredActionsService {
|
||||
|
||||
UserModel user = getUser(accessCode);
|
||||
|
||||
initAudit(accessCode);
|
||||
initEvent(accessCode);
|
||||
|
||||
String passwordNew = formData.getFirst("password-new");
|
||||
String passwordConfirm = formData.getFirst("password-confirm");
|
||||
@@ -208,7 +208,7 @@ public class RequiredActionsService {
|
||||
|
||||
user.removeRequiredAction(RequiredAction.UPDATE_PASSWORD);
|
||||
|
||||
audit.clone().event(EventType.UPDATE_PASSWORD).success();
|
||||
event.clone().event(EventType.UPDATE_PASSWORD).success();
|
||||
|
||||
// Redirect to account management to login if password reset was initiated by admin
|
||||
if (accessCode.getSessionState() == null) {
|
||||
@@ -230,13 +230,13 @@ public class RequiredActionsService {
|
||||
|
||||
UserModel user = getUser(accessCode);
|
||||
|
||||
initAudit(accessCode);
|
||||
initEvent(accessCode);
|
||||
|
||||
user.setEmailVerified(true);
|
||||
|
||||
user.removeRequiredAction(RequiredAction.VERIFY_EMAIL);
|
||||
|
||||
audit.clone().event(EventType.VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
|
||||
event.clone().event(EventType.VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
|
||||
|
||||
return redirectOauth(user, accessCode);
|
||||
} else {
|
||||
@@ -245,7 +245,7 @@ public class RequiredActionsService {
|
||||
return unauthorized();
|
||||
}
|
||||
|
||||
initAudit(accessCode);
|
||||
initEvent(accessCode);
|
||||
|
||||
return Flows.forms(session, realm, null, uriInfo).setAccessCode(accessCode.getCode()).setUser(accessCode.getUser())
|
||||
.createResponse(RequiredAction.VERIFY_EMAIL);
|
||||
@@ -290,7 +290,7 @@ public class RequiredActionsService {
|
||||
"Login requester not enabled.");
|
||||
}
|
||||
|
||||
audit.event(EventType.SEND_RESET_PASSWORD).client(clientId)
|
||||
event.event(EventType.SEND_RESET_PASSWORD).client(clientId)
|
||||
.detail(Details.REDIRECT_URI, redirect)
|
||||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
.detail(Details.AUTH_METHOD, "form")
|
||||
@@ -302,10 +302,10 @@ public class RequiredActionsService {
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
audit.error(Errors.USER_NOT_FOUND);
|
||||
event.error(Errors.USER_NOT_FOUND);
|
||||
} else {
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", false);
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
AccessCode accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, session, realm, client, user, userSession);
|
||||
accessCode.setRequiredAction(RequiredAction.UPDATE_PASSWORD);
|
||||
@@ -319,7 +319,7 @@ public class RequiredActionsService {
|
||||
|
||||
this.session.getProvider(EmailProvider.class).setRealm(realm).setUser(user).sendPasswordReset(link, expiration);
|
||||
|
||||
audit.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
|
||||
event.user(user).detail(Details.EMAIL, user.getEmail()).detail(Details.CODE_ID, accessCode.getCodeId()).success();
|
||||
} catch (EmailException e) {
|
||||
logger.error("Failed to send password reset email", e);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError("emailSendError").createErrorPage();
|
||||
@@ -375,17 +375,17 @@ public class RequiredActionsService {
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection);
|
||||
return Flows.oauth(this.session, realm, request, uriInfo, clientConnection, authManager, tokenManager).redirectError(accessCode.getClient(), "access_denied", accessCode.getState(), accessCode.getRedirectUri());
|
||||
}
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
return Flows.oauth(this.session, realm, request, uriInfo, clientConnection, authManager, tokenManager).redirectAccessCode(accessCode,
|
||||
userSession, accessCode.getState(), accessCode.getRedirectUri());
|
||||
}
|
||||
}
|
||||
|
||||
private void initAudit(AccessCode accessCode) {
|
||||
audit.event(EventType.LOGIN).client(accessCode.getClient())
|
||||
private void initEvent(AccessCode accessCode) {
|
||||
event.event(EventType.LOGIN).client(accessCode.getClient())
|
||||
.user(accessCode.getUser())
|
||||
.session(accessCode.getSessionState())
|
||||
.detail(Details.CODE_ID, accessCode.getCodeId())
|
||||
@@ -395,10 +395,10 @@ public class RequiredActionsService {
|
||||
UserSessionModel userSession = accessCode.getSessionState() != null ? session.sessions().getUserSession(realm, accessCode.getSessionState()) : null;
|
||||
|
||||
if (userSession != null) {
|
||||
audit.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
|
||||
audit.detail(Details.USERNAME, userSession.getLoginUsername());
|
||||
event.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
|
||||
event.detail(Details.USERNAME, userSession.getLoginUsername());
|
||||
if (userSession.isRememberMe()) {
|
||||
audit.detail(Details.REMEMBER_ME, "true");
|
||||
event.detail(Details.REMEMBER_ME, "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,11 @@ import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.Errors;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.AccountRoles;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.Constants;
|
||||
@@ -42,13 +41,12 @@ import org.keycloak.models.SocialLinkModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.services.managers.AuditManager;
|
||||
import org.keycloak.services.managers.EventsManager;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
import org.keycloak.services.resources.flows.OAuthFlows;
|
||||
import org.keycloak.services.resources.flows.OAuthRedirect;
|
||||
import org.keycloak.services.resources.flows.Urls;
|
||||
import org.keycloak.social.AuthCallback;
|
||||
import org.keycloak.social.SocialAccessDeniedException;
|
||||
@@ -124,7 +122,7 @@ public class SocialResource {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||
|
||||
Audit audit = new AuditManager(realm, session, clientConnection).createAudit()
|
||||
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder()
|
||||
.event(EventType.LOGIN)
|
||||
.detail(Details.RESPONSE_TYPE, initialRequest.get(OAuth2Constants.RESPONSE_TYPE))
|
||||
.detail(Details.AUTH_METHOD, authMethod);
|
||||
@@ -133,7 +131,7 @@ public class SocialResource {
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
||||
}
|
||||
|
||||
@@ -143,15 +141,15 @@ public class SocialResource {
|
||||
String state = initialRequest.get(OAuth2Constants.STATE);
|
||||
String responseType = initialRequest.get(OAuth2Constants.RESPONSE_TYPE);
|
||||
|
||||
audit.client(clientId).detail(Details.REDIRECT_URI, redirectUri);
|
||||
event.client(clientId).detail(Details.REDIRECT_URI, redirectUri);
|
||||
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||
}
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||
}
|
||||
|
||||
@@ -176,14 +174,14 @@ public class SocialResource {
|
||||
queryParms.putSingle(OAuth2Constants.REDIRECT_URI, redirectUri);
|
||||
queryParms.putSingle(OAuth2Constants.RESPONSE_TYPE, responseType);
|
||||
|
||||
audit.error(Errors.REJECTED_BY_USER);
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
return Flows.forms(session, realm, client, uriInfo).setQueryParams(queryParms).setWarning("Access denied").createLogin();
|
||||
} catch (SocialProviderException e) {
|
||||
logger.error("Failed to process social callback", e);
|
||||
return oauth.forwardToSecurityFailure("Failed to process social callback");
|
||||
}
|
||||
|
||||
audit.detail(Details.USERNAME, socialUser.getId() + "@" + provider.getId());
|
||||
event.detail(Details.USERNAME, socialUser.getId() + "@" + provider.getId());
|
||||
|
||||
try {
|
||||
SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getId(), socialUser.getUsername());
|
||||
@@ -194,32 +192,32 @@ public class SocialResource {
|
||||
if (userId != null) {
|
||||
UserModel authenticatedUser = session.users().getUserById(userId, realm);
|
||||
|
||||
audit.event(EventType.SOCIAL_LINK).user(userId);
|
||||
event.event(EventType.SOCIAL_LINK).user(userId);
|
||||
|
||||
if (user != null) {
|
||||
audit.error(Errors.SOCIAL_ID_IN_USE);
|
||||
event.error(Errors.SOCIAL_ID_IN_USE);
|
||||
return oauth.forwardToSecurityFailure("This social account is already linked to other user");
|
||||
}
|
||||
|
||||
if (!authenticatedUser.isEnabled()) {
|
||||
audit.error(Errors.USER_DISABLED);
|
||||
event.error(Errors.USER_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("User is disabled");
|
||||
}
|
||||
|
||||
if (!authenticatedUser.hasRole(realm.getApplicationByName(Constants.ACCOUNT_MANAGEMENT_APP).getRole(AccountRoles.MANAGE_ACCOUNT))) {
|
||||
audit.error(Errors.NOT_ALLOWED);
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
return oauth.forwardToSecurityFailure("Insufficient permissions to link social account");
|
||||
}
|
||||
|
||||
if (redirectUri == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return oauth.forwardToSecurityFailure("Unknown redirectUri");
|
||||
}
|
||||
|
||||
session.users().addSocialLink(realm, authenticatedUser, socialLink);
|
||||
logger.debugv("Social provider {0} linked with user {1}", provider.getId(), authenticatedUser.getUsername());
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
||||
}
|
||||
|
||||
@@ -236,26 +234,26 @@ public class SocialResource {
|
||||
|
||||
session.users().addSocialLink(realm, user, socialLink);
|
||||
|
||||
audit.clone().user(user).event(EventType.REGISTER)
|
||||
event.clone().user(user).event(EventType.REGISTER)
|
||||
.detail(Details.REGISTER_METHOD, "social@" + provider.getId())
|
||||
.detail(Details.EMAIL, socialUser.getEmail())
|
||||
.removeDetail("auth_method")
|
||||
.success();
|
||||
}
|
||||
|
||||
audit.user(user);
|
||||
event.user(user);
|
||||
|
||||
if (!user.isEnabled()) {
|
||||
audit.error(Errors.USER_DISABLED);
|
||||
event.error(Errors.USER_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Your account is not enabled.");
|
||||
}
|
||||
|
||||
String username = socialLink.getSocialUserId() + "@" + socialLink.getSocialProvider();
|
||||
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), authMethod, false);
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
Response response = oauth.processAccessCode(scope, state, redirectUri, client, user, userSession, audit);
|
||||
Response response = oauth.processAccessCode(scope, state, redirectUri, client, user, userSession, event);
|
||||
if (session.getTransaction().isActive()) {
|
||||
session.getTransaction().commit();
|
||||
}
|
||||
@@ -275,7 +273,7 @@ public class SocialResource {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.getRealmByName(realmName);
|
||||
|
||||
Audit audit = new AuditManager(realm, session, clientConnection).createAudit()
|
||||
EventBuilder event = new EventsManager(realm, session, clientConnection).createEventBuilder()
|
||||
.event(EventType.LOGIN).client(clientId)
|
||||
.detail(Details.REDIRECT_URI, redirectUri)
|
||||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
@@ -283,23 +281,23 @@ public class SocialResource {
|
||||
|
||||
SocialProvider provider = SocialLoader.load(providerId);
|
||||
if (provider == null) {
|
||||
audit.error(Errors.SOCIAL_PROVIDER_NOT_FOUND);
|
||||
event.error(Errors.SOCIAL_PROVIDER_NOT_FOUND);
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Social provider not found").createErrorPage();
|
||||
}
|
||||
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Unknown login requester.").createErrorPage();
|
||||
}
|
||||
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Login requester not enabled.").createErrorPage();
|
||||
}
|
||||
redirectUri = TokenService.verifyRedirectUri(uriInfo, redirectUri, realm, client);
|
||||
if (redirectUri == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return Flows.forms(session, realm, null, uriInfo).setError("Invalid redirect_uri.").createErrorPage();
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.Errors;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.login.LoginFormsProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
@@ -85,7 +85,7 @@ public class TokenService {
|
||||
|
||||
protected RealmModel realm;
|
||||
protected TokenManager tokenManager;
|
||||
private Audit audit;
|
||||
private EventBuilder event;
|
||||
protected AuthenticationManager authManager;
|
||||
|
||||
@Context
|
||||
@@ -112,10 +112,10 @@ public class TokenService {
|
||||
|
||||
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
|
||||
|
||||
public TokenService(RealmModel realm, TokenManager tokenManager, Audit audit, AuthenticationManager authManager) {
|
||||
public TokenService(RealmModel realm, TokenManager tokenManager, EventBuilder event, AuthenticationManager authManager) {
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
this.audit = audit;
|
||||
this.event = event;
|
||||
this.authManager = authManager;
|
||||
}
|
||||
|
||||
@@ -232,22 +232,22 @@ public class TokenService {
|
||||
return createError("not_enabled", "Direct Grant REST API not enabled", Response.Status.FORBIDDEN);
|
||||
}
|
||||
|
||||
audit.event(EventType.LOGIN).detail(Details.AUTH_METHOD, "oauth_credentials").detail(Details.RESPONSE_TYPE, "token");
|
||||
event.event(EventType.LOGIN).detail(Details.AUTH_METHOD, "oauth_credentials").detail(Details.RESPONSE_TYPE, "token");
|
||||
|
||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||
if (username == null) {
|
||||
audit.error(Errors.USERNAME_MISSING);
|
||||
event.error(Errors.USERNAME_MISSING);
|
||||
throw new UnauthorizedException("No username");
|
||||
}
|
||||
audit.detail(Details.USERNAME, username);
|
||||
event.detail(Details.USERNAME, username);
|
||||
|
||||
UserModel user = session.users().getUserByUsername(username, realm);
|
||||
if (user != null) audit.user(user);
|
||||
if (user != null) event.user(user);
|
||||
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, audit);
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, event);
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return createError("realm_disabled", "Realm is disabled", Response.Status.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@@ -262,21 +262,21 @@ public class TokenService {
|
||||
err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "AccountProvider temporarily disabled");
|
||||
audit.error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
event.error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
case ACCOUNT_DISABLED:
|
||||
err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "AccountProvider disabled");
|
||||
audit.error(Errors.USER_DISABLED);
|
||||
event.error(Errors.USER_DISABLED);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
default:
|
||||
err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Invalid user credentials");
|
||||
audit.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
event.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -284,15 +284,15 @@ public class TokenService {
|
||||
String scope = form.getFirst(OAuth2Constants.SCOPE);
|
||||
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "oauth_credentials", false);
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event)
|
||||
.generateAccessToken(scope, client, user, userSession)
|
||||
.generateRefreshToken()
|
||||
.generateIDToken()
|
||||
.build();
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
||||
}
|
||||
@@ -311,7 +311,7 @@ public class TokenService {
|
||||
if (!checkSsl()) {
|
||||
return createError("https_required", "HTTPS required", Response.Status.FORBIDDEN);
|
||||
}
|
||||
audit.event(EventType.VALIDATE_ACCESS_TOKEN);
|
||||
event.event(EventType.VALIDATE_ACCESS_TOKEN);
|
||||
AccessToken token = null;
|
||||
try {
|
||||
token = RSATokenVerifier.verifyToken(tokenString, realm.getPublicKey(), realm.getName());
|
||||
@@ -319,11 +319,11 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Token invalid");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
audit.user(token.getSubject()).session(token.getSessionState()).detail(Details.VALIDATE_ACCESS_TOKEN, token.getId());
|
||||
event.user(token.getSubject()).session(token.getSessionState()).detail(Details.VALIDATE_ACCESS_TOKEN, token.getId());
|
||||
|
||||
if (token.isExpired()
|
||||
|| token.getIssuedAt() < realm.getNotBefore()
|
||||
@@ -331,7 +331,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Token expired");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -342,7 +342,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "User does not exist");
|
||||
audit.error(Errors.USER_NOT_FOUND);
|
||||
event.error(Errors.USER_NOT_FOUND);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -351,7 +351,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "User disabled");
|
||||
audit.error(Errors.USER_DISABLED);
|
||||
event.error(Errors.USER_DISABLED);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -361,7 +361,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_GRANT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Expired session");
|
||||
audit.error(Errors.USER_SESSION_NOT_FOUND);
|
||||
event.error(Errors.USER_SESSION_NOT_FOUND);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -371,7 +371,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_CLIENT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Issued for client no longer exists");
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
|
||||
@@ -381,7 +381,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_CLIENT);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Issued for client no longer exists");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
}
|
||||
@@ -392,7 +392,7 @@ public class TokenService {
|
||||
Map<String, String> err = new HashMap<String, String>();
|
||||
err.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_SCOPE);
|
||||
err.put(OAuth2Constants.ERROR_DESCRIPTION, "Role mappings have changed");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(err)
|
||||
.build();
|
||||
|
||||
@@ -424,34 +424,34 @@ public class TokenService {
|
||||
return createError("https_required", "HTTPS required", Response.Status.FORBIDDEN);
|
||||
}
|
||||
|
||||
audit.event(EventType.REFRESH_TOKEN);
|
||||
event.event(EventType.REFRESH_TOKEN);
|
||||
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, audit);
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, event);
|
||||
String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
|
||||
if (refreshToken == null) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_REQUEST);
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "No refresh token");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
AccessToken accessToken;
|
||||
try {
|
||||
accessToken = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, audit);
|
||||
accessToken = tokenManager.refreshAccessToken(session, uriInfo, clientConnection, realm, client, refreshToken, event);
|
||||
} catch (OAuthErrorException e) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, e.getError());
|
||||
if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event)
|
||||
.accessToken(accessToken)
|
||||
.generateIDToken()
|
||||
.generateRefreshToken().build();
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
|
||||
}
|
||||
@@ -477,14 +477,14 @@ public class TokenService {
|
||||
String rememberMe = formData.getFirst("rememberMe");
|
||||
boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
|
||||
|
||||
audit.event(EventType.LOGIN).client(clientId)
|
||||
event.event(EventType.LOGIN).client(clientId)
|
||||
.detail(Details.REDIRECT_URI, redirect)
|
||||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
.detail(Details.AUTH_METHOD, "form")
|
||||
.detail(Details.USERNAME, username);
|
||||
|
||||
if (remember) {
|
||||
audit.detail(Details.REMEMBER_ME, "true");
|
||||
event.detail(Details.REMEMBER_ME, "true");
|
||||
}
|
||||
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
@@ -494,27 +494,27 @@ public class TokenService {
|
||||
}
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
||||
}
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||
}
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||
}
|
||||
|
||||
redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
|
||||
if (redirect == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return oauth.forwardToSecurityFailure("Invalid redirect_uri.");
|
||||
}
|
||||
|
||||
if (formData.containsKey("cancel")) {
|
||||
audit.error(Errors.REJECTED_BY_USER);
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
return oauth.redirectError(client, "access_denied", state, redirect);
|
||||
}
|
||||
|
||||
@@ -528,36 +528,36 @@ public class TokenService {
|
||||
|
||||
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(session, realm, username);
|
||||
if (user != null) {
|
||||
audit.user(user);
|
||||
event.user(user);
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case SUCCESS:
|
||||
case ACTIONS_REQUIRED:
|
||||
UserSessionModel userSession = session.sessions().createUserSession(realm, user, username, clientConnection.getRemoteAddr(), "form", remember);
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user, userSession, audit);
|
||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user, userSession, event);
|
||||
case ACCOUNT_TEMPORARILY_DISABLED:
|
||||
audit.error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
event.error(Errors.USER_TEMPORARILY_DISABLED);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError(Messages.ACCOUNT_TEMPORARILY_DISABLED).setFormData(formData).createLogin();
|
||||
case ACCOUNT_DISABLED:
|
||||
audit.error(Errors.USER_DISABLED);
|
||||
event.error(Errors.USER_DISABLED);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError(Messages.ACCOUNT_DISABLED).setFormData(formData).createLogin();
|
||||
case MISSING_TOTP:
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setFormData(formData).createLoginTotp();
|
||||
case INVALID_USER:
|
||||
audit.error(Errors.USER_NOT_FOUND);
|
||||
event.error(Errors.USER_NOT_FOUND);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError(Messages.INVALID_USER).setFormData(formData).createLogin();
|
||||
default:
|
||||
audit.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
event.error(Errors.INVALID_USER_CREDENTIALS);
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setError(Messages.INVALID_USER).setFormData(formData).createLogin();
|
||||
}
|
||||
}
|
||||
|
||||
@Path("auth/request/login-actions")
|
||||
public RequiredActionsService getRequiredActionsService() {
|
||||
RequiredActionsService service = new RequiredActionsService(realm, tokenManager, audit);
|
||||
RequiredActionsService service = new RequiredActionsService(realm, tokenManager, event);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(service);
|
||||
|
||||
//resourceContext.initResource(service);
|
||||
@@ -584,7 +584,7 @@ public class TokenService {
|
||||
String username = formData.getFirst("username");
|
||||
String email = formData.getFirst("email");
|
||||
|
||||
audit.event(EventType.REGISTER).client(clientId)
|
||||
event.event(EventType.REGISTER).client(clientId)
|
||||
.detail(Details.REDIRECT_URI, redirect)
|
||||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
.detail(Details.USERNAME, username)
|
||||
@@ -594,28 +594,28 @@ public class TokenService {
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Realm not enabled");
|
||||
}
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||
}
|
||||
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||
}
|
||||
|
||||
redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
|
||||
if (redirect == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return oauth.forwardToSecurityFailure("Invalid redirect_uri.");
|
||||
}
|
||||
|
||||
if (!realm.isRegistrationAllowed()) {
|
||||
audit.error(Errors.REGISTRATION_DISABLED);
|
||||
event.error(Errors.REGISTRATION_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Registration not allowed");
|
||||
}
|
||||
|
||||
@@ -631,19 +631,19 @@ public class TokenService {
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
audit.error(Errors.INVALID_REGISTRATION);
|
||||
event.error(Errors.INVALID_REGISTRATION);
|
||||
return Flows.forms(session, realm, client, uriInfo).setError(error).setFormData(formData).createRegistration();
|
||||
}
|
||||
|
||||
// Validate that user with this username doesn't exist in realm or any federation provider
|
||||
if (session.users().getUserByUsername(username, realm) != null) {
|
||||
audit.error(Errors.USERNAME_IN_USE);
|
||||
event.error(Errors.USERNAME_IN_USE);
|
||||
return Flows.forms(session, realm, client, uriInfo).setError(Messages.USERNAME_EXISTS).setFormData(formData).createRegistration();
|
||||
}
|
||||
|
||||
// Validate that user with this email doesn't exist in realm or any federation provider
|
||||
if (session.users().getUserByEmail(email, realm) != null) {
|
||||
audit.error(Errors.EMAIL_IN_USE);
|
||||
event.error(Errors.EMAIL_IN_USE);
|
||||
return Flows.forms(session, realm, client, uriInfo).setError(Messages.EMAIL_EXISTS).setFormData(formData).createRegistration();
|
||||
}
|
||||
|
||||
@@ -676,8 +676,8 @@ public class TokenService {
|
||||
}
|
||||
}
|
||||
|
||||
audit.user(user).success();
|
||||
audit.reset();
|
||||
event.user(user).success();
|
||||
event.reset();
|
||||
|
||||
return processLogin(clientId, scopeParam, state, redirect, formData);
|
||||
}
|
||||
@@ -714,10 +714,10 @@ public class TokenService {
|
||||
throw new ForbiddenException("HTTPS required");
|
||||
}
|
||||
|
||||
audit.event(EventType.CODE_TO_TOKEN);
|
||||
event.event(EventType.CODE_TO_TOKEN);
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
throw new UnauthorizedException("Realm not enabled");
|
||||
}
|
||||
|
||||
@@ -726,7 +726,7 @@ public class TokenService {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, "invalid_request");
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "code not specified");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
throw new BadRequestException("Code not specified", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
|
||||
@@ -735,39 +735,39 @@ public class TokenService {
|
||||
String[] parts = code.split("\\.");
|
||||
if (parts.length == 2) {
|
||||
try {
|
||||
audit.detail(Details.CODE_ID, new String(Base64Url.decode(parts[1])));
|
||||
event.detail(Details.CODE_ID, new String(Base64Url.decode(parts[1])));
|
||||
} catch (Throwable t) {
|
||||
}
|
||||
}
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Code not found");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
audit.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
event.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
if (!accessCode.isValid(ClientSessionModel.Action.CODE_TO_TOKEN)) {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Code is expired");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
|
||||
accessCode.setAction(null);
|
||||
|
||||
audit.user(accessCode.getUser());
|
||||
audit.session(accessCode.getSessionState());
|
||||
event.user(accessCode.getUser());
|
||||
event.session(accessCode.getSessionState());
|
||||
|
||||
ClientModel client = authorizeClient(authorizationHeader, formData, audit);
|
||||
ClientModel client = authorizeClient(authorizationHeader, formData, event);
|
||||
|
||||
if (!client.getClientId().equals(accessCode.getClient().getClientId())) {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Auth error");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
@@ -777,7 +777,7 @@ public class TokenService {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "User not found");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
@@ -786,7 +786,7 @@ public class TokenService {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "User disabled");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
@@ -797,7 +797,7 @@ public class TokenService {
|
||||
Map<String, String> res = new HashMap<String, String>();
|
||||
res.put(OAuth2Constants.ERROR, "invalid_grant");
|
||||
res.put(OAuth2Constants.ERROR_DESCRIPTION, "Session not active");
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||
.build();
|
||||
}
|
||||
@@ -810,21 +810,21 @@ public class TokenService {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, e.getError());
|
||||
if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, audit)
|
||||
AccessTokenResponse res = tokenManager.responseBuilder(realm, client, event)
|
||||
.accessToken(token)
|
||||
.generateIDToken()
|
||||
.generateRefreshToken().build();
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
return Cors.add(request, Response.ok(res)).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
|
||||
}
|
||||
|
||||
protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData, Audit audit) {
|
||||
protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData, EventBuilder event) {
|
||||
String client_id;
|
||||
String clientSecret;
|
||||
if (authorizationHeader != null) {
|
||||
@@ -846,14 +846,14 @@ public class TokenService {
|
||||
throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
|
||||
audit.client(client_id);
|
||||
event.client(client_id);
|
||||
|
||||
ClientModel client = realm.findClient(client_id);
|
||||
if (client == null) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, "invalid_client");
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "Could not find client");
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ public class TokenService {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, "invalid_client");
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "Client is not enabled");
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
|
||||
@@ -869,7 +869,7 @@ public class TokenService {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, "invalid_client");
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "Bearer-only not allowed");
|
||||
audit.error(Errors.INVALID_CLIENT);
|
||||
event.error(Errors.INVALID_CLIENT);
|
||||
throw new BadRequestException("Bearer-only not allowed", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
|
||||
@@ -877,7 +877,7 @@ public class TokenService {
|
||||
if (clientSecret == null || !client.validateSecret(clientSecret)) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, "unauthorized_client");
|
||||
audit.error(Errors.INVALID_CLIENT_CREDENTIALS);
|
||||
event.error(Errors.INVALID_CLIENT_CREDENTIALS);
|
||||
throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||
}
|
||||
}
|
||||
@@ -904,7 +904,7 @@ public class TokenService {
|
||||
@QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
||||
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state, final @QueryParam("prompt") String prompt,
|
||||
final @QueryParam("login_hint") String loginHint) {
|
||||
audit.event(EventType.LOGIN).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
|
||||
event.event(EventType.LOGIN).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
|
||||
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
|
||||
@@ -913,30 +913,30 @@ public class TokenService {
|
||||
}
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Realm not enabled");
|
||||
}
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||
}
|
||||
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||
}
|
||||
if ( (client instanceof ApplicationModel) && ((ApplicationModel)client).isBearerOnly()) {
|
||||
audit.error(Errors.NOT_ALLOWED);
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
return oauth.forwardToSecurityFailure("Bearer-only applications are not allowed to initiate browser login");
|
||||
}
|
||||
if (client.isDirectGrantsOnly()) {
|
||||
audit.error(Errors.NOT_ALLOWED);
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
return oauth.forwardToSecurityFailure("direct-grants-only clients are not allowed to initiate browser login");
|
||||
}
|
||||
redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
|
||||
if (redirect == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return oauth.forwardToSecurityFailure("Invalid redirect_uri.");
|
||||
}
|
||||
|
||||
@@ -945,8 +945,8 @@ public class TokenService {
|
||||
UserModel user = authResult.getUser();
|
||||
UserSessionModel session = authResult.getSession();
|
||||
|
||||
audit.user(user).session(session).detail(Details.AUTH_METHOD, "sso");
|
||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user, session, audit);
|
||||
event.user(user).session(session).detail(Details.AUTH_METHOD, "sso");
|
||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user, session, event);
|
||||
}
|
||||
|
||||
if (prompt != null && prompt.equals("none")) {
|
||||
@@ -980,7 +980,7 @@ public class TokenService {
|
||||
public Response registerPage(final @QueryParam("response_type") String responseType,
|
||||
@QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
||||
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
|
||||
audit.event(EventType.REGISTER).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
|
||||
event.event(EventType.REGISTER).client(clientId).detail(Details.REDIRECT_URI, redirect).detail(Details.RESPONSE_TYPE, "code");
|
||||
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
|
||||
@@ -989,28 +989,28 @@ public class TokenService {
|
||||
}
|
||||
|
||||
if (!realm.isEnabled()) {
|
||||
audit.error(Errors.REALM_DISABLED);
|
||||
event.error(Errors.REALM_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Realm not enabled");
|
||||
}
|
||||
ClientModel client = realm.findClient(clientId);
|
||||
if (client == null) {
|
||||
audit.error(Errors.CLIENT_NOT_FOUND);
|
||||
event.error(Errors.CLIENT_NOT_FOUND);
|
||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||
}
|
||||
|
||||
if (!client.isEnabled()) {
|
||||
audit.error(Errors.CLIENT_DISABLED);
|
||||
event.error(Errors.CLIENT_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||
}
|
||||
|
||||
redirect = verifyRedirectUri(uriInfo, redirect, realm, client);
|
||||
if (redirect == null) {
|
||||
audit.error(Errors.INVALID_REDIRECT_URI);
|
||||
event.error(Errors.INVALID_REDIRECT_URI);
|
||||
return oauth.forwardToSecurityFailure("Invalid redirect_uri.");
|
||||
}
|
||||
|
||||
if (!realm.isRegistrationAllowed()) {
|
||||
audit.error(Errors.REGISTRATION_DISABLED);
|
||||
event.error(Errors.REGISTRATION_DISABLED);
|
||||
return oauth.forwardToSecurityFailure("Registration not allowed");
|
||||
}
|
||||
|
||||
@@ -1029,9 +1029,9 @@ public class TokenService {
|
||||
@GET
|
||||
@NoCache
|
||||
public Response logout(final @QueryParam("redirect_uri") String redirectUri) {
|
||||
audit.event(EventType.LOGOUT);
|
||||
event.event(EventType.LOGOUT);
|
||||
if (redirectUri != null) {
|
||||
audit.detail(Details.REDIRECT_URI, redirectUri);
|
||||
event.detail(Details.REDIRECT_URI, redirectUri);
|
||||
}
|
||||
// authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
|
||||
AuthenticationManager.AuthResult authResult = authManager.authenticateIdentityCookie(session, realm, uriInfo, clientConnection, headers, false);
|
||||
@@ -1076,15 +1076,15 @@ public class TokenService {
|
||||
throw new NotAcceptableException("HTTPS required");
|
||||
}
|
||||
|
||||
audit.event(EventType.LOGOUT);
|
||||
event.event(EventType.LOGOUT);
|
||||
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, audit);
|
||||
ClientModel client = authorizeClient(authorizationHeader, form, event);
|
||||
String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
|
||||
if (refreshToken == null) {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, OAuthErrorException.INVALID_REQUEST);
|
||||
error.put(OAuth2Constants.ERROR_DESCRIPTION, "No refresh token");
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
try {
|
||||
@@ -1097,7 +1097,7 @@ public class TokenService {
|
||||
Map<String, String> error = new HashMap<String, String>();
|
||||
error.put(OAuth2Constants.ERROR, e.getError());
|
||||
if (e.getDescription() != null) error.put(OAuth2Constants.ERROR_DESCRIPTION, e.getDescription());
|
||||
audit.error(Errors.INVALID_TOKEN);
|
||||
event.error(Errors.INVALID_TOKEN);
|
||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||
}
|
||||
return Cors.add(request, Response.noContent()).auth().allowedOrigins(client).allowedMethods("POST").exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS).build();
|
||||
@@ -1105,7 +1105,7 @@ public class TokenService {
|
||||
|
||||
private void logout(UserSessionModel userSession) {
|
||||
authManager.logout(session, realm, userSession, uriInfo, clientConnection);
|
||||
audit.user(userSession.getUser()).session(userSession).success();
|
||||
event.user(userSession.getUser()).session(userSession).success();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1118,7 +1118,7 @@ public class TokenService {
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processOAuth(final MultivaluedMap<String, String> formData) {
|
||||
audit.event(EventType.LOGIN).detail(Details.RESPONSE_TYPE, "code");
|
||||
event.event(EventType.LOGIN).detail(Details.RESPONSE_TYPE, "code");
|
||||
|
||||
OAuthFlows oauth = Flows.oauth(session, realm, request, uriInfo, clientConnection, authManager, tokenManager);
|
||||
|
||||
@@ -1130,41 +1130,41 @@ public class TokenService {
|
||||
|
||||
AccessCode accessCode = AccessCode.parse(code, session, realm);
|
||||
if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT)) {
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return oauth.forwardToSecurityFailure("Invalid access code.");
|
||||
}
|
||||
audit.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
event.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
|
||||
String redirect = accessCode.getRedirectUri();
|
||||
String state = accessCode.getState();
|
||||
|
||||
audit.client(accessCode.getClient())
|
||||
event.client(accessCode.getClient())
|
||||
.user(accessCode.getUser())
|
||||
.detail(Details.RESPONSE_TYPE, "code")
|
||||
.detail(Details.REDIRECT_URI, redirect);
|
||||
|
||||
UserSessionModel userSession = session.sessions().getUserSession(realm, accessCode.getSessionState());
|
||||
if (userSession != null) {
|
||||
audit.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
|
||||
audit.detail(Details.USERNAME, userSession.getLoginUsername());
|
||||
event.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
|
||||
event.detail(Details.USERNAME, userSession.getLoginUsername());
|
||||
if (userSession.isRememberMe()) {
|
||||
audit.detail(Details.REMEMBER_ME, "true");
|
||||
event.detail(Details.REMEMBER_ME, "true");
|
||||
}
|
||||
}
|
||||
|
||||
if (!AuthenticationManager.isSessionValid(realm, userSession)) {
|
||||
AuthenticationManager.logout(session, realm, userSession, uriInfo, clientConnection);
|
||||
audit.error(Errors.INVALID_CODE);
|
||||
event.error(Errors.INVALID_CODE);
|
||||
return oauth.forwardToSecurityFailure("Session not active");
|
||||
}
|
||||
audit.session(userSession);
|
||||
event.session(userSession);
|
||||
|
||||
if (formData.containsKey("cancel")) {
|
||||
audit.error(Errors.REJECTED_BY_USER);
|
||||
event.error(Errors.REJECTED_BY_USER);
|
||||
return redirectAccessDenied(redirect, state);
|
||||
}
|
||||
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN);
|
||||
return oauth.redirectAccessCode(accessCode, userSession, state, redirect);
|
||||
|
||||
+32
-32
@@ -4,10 +4,10 @@ import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.audit.Event;
|
||||
import org.keycloak.audit.EventQuery;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.events.Event;
|
||||
import org.keycloak.events.EventQuery;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelDuplicateException;
|
||||
@@ -19,7 +19,7 @@ import org.keycloak.models.cache.CacheUserProvider;
|
||||
import org.keycloak.models.utils.ModelToRepresentation;
|
||||
import org.keycloak.models.utils.RepresentationToModel;
|
||||
import org.keycloak.representations.adapters.action.SessionStats;
|
||||
import org.keycloak.representations.idm.RealmAuditRepresentation;
|
||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.LDAPConnectionTestManager;
|
||||
import org.keycloak.services.managers.UsersSyncManager;
|
||||
@@ -306,62 +306,62 @@ public class RealmAdminResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* View the audit provider and how it is configured.
|
||||
* View the events provider and how it is configured.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@NoCache
|
||||
@Path("audit")
|
||||
@Path("events/config")
|
||||
@Produces("application/json")
|
||||
public RealmAuditRepresentation getRealmAudit() {
|
||||
auth.init(RealmAuth.Resource.AUDIT).requireView();
|
||||
public RealmEventsConfigRepresentation getRealmEventsConfig() {
|
||||
auth.init(RealmAuth.Resource.EVENTS).requireView();
|
||||
|
||||
return ModelToRepresentation.toAuditReprensetation(realm);
|
||||
return ModelToRepresentation.toEventsConfigReprensetation(realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the audit provider and/or it's configuration
|
||||
* Change the events provider and/or it's configuration
|
||||
*
|
||||
* @param rep
|
||||
*/
|
||||
@PUT
|
||||
@Path("audit")
|
||||
@Path("events/config")
|
||||
@Consumes("application/json")
|
||||
public void updateRealmAudit(final RealmAuditRepresentation rep) {
|
||||
auth.init(RealmAuth.Resource.AUDIT).requireManage();
|
||||
public void updateRealmEventsConfig(final RealmEventsConfigRepresentation rep) {
|
||||
auth.init(RealmAuth.Resource.EVENTS).requireManage();
|
||||
|
||||
logger.debug("updating realm audit: " + realm.getName());
|
||||
new RealmManager(session).updateRealmAudit(rep, realm);
|
||||
logger.debug("updating realm events config: " + realm.getName());
|
||||
new RealmManager(session).updateRealmEventsConfig(rep, realm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query audit events. Returns all events, or will query based on URL query parameters listed here
|
||||
* Query events. Returns all events, or will query based on URL query parameters listed here
|
||||
*
|
||||
* @param client app or oauth client name
|
||||
* @param event event type
|
||||
* @param type type type
|
||||
* @param user user id
|
||||
* @param ipAddress
|
||||
* @param firstResult
|
||||
* @param maxResults
|
||||
* @return
|
||||
*/
|
||||
@Path("audit/events")
|
||||
@Path("events")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<Event> getAudit(@QueryParam("client") String client, @QueryParam("event") String event, @QueryParam("user") String user,
|
||||
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
|
||||
auth.init(RealmAuth.Resource.AUDIT).requireView();
|
||||
public List<Event> getEvents(@QueryParam("client") String client, @QueryParam("type") String type, @QueryParam("user") String user,
|
||||
@QueryParam("ipAddress") String ipAddress, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
|
||||
auth.init(RealmAuth.Resource.EVENTS).requireView();
|
||||
|
||||
AuditProvider audit = session.getProvider(AuditProvider.class);
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
|
||||
EventQuery query = audit.createQuery().realm(realm.getId());
|
||||
EventQuery query = eventStore.createQuery().realm(realm.getId());
|
||||
if (client != null) {
|
||||
query.client(client);
|
||||
}
|
||||
if (event != null) {
|
||||
query.event(EventType.valueOf(event));
|
||||
if (type != null) {
|
||||
query.type(EventType.valueOf(type));
|
||||
}
|
||||
if (user != null) {
|
||||
query.user(user);
|
||||
@@ -380,16 +380,16 @@ public class RealmAdminResource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all audit events.
|
||||
* Delete all events.
|
||||
*
|
||||
*/
|
||||
@Path("audit/events")
|
||||
@Path("events")
|
||||
@DELETE
|
||||
public void clearAudit() {
|
||||
auth.init(RealmAuth.Resource.AUDIT).requireManage();
|
||||
public void clearEvents() {
|
||||
auth.init(RealmAuth.Resource.EVENTS).requireManage();
|
||||
|
||||
AuditProvider audit = session.getProvider(AuditProvider.class);
|
||||
audit.clear(realm.getId());
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
eventStore.clear(realm.getId());
|
||||
}
|
||||
|
||||
@Path("testLDAPConnection")
|
||||
|
||||
@@ -13,7 +13,7 @@ public class RealmAuth {
|
||||
private Resource resource;
|
||||
|
||||
public enum Resource {
|
||||
APPLICATION, CLIENT, USER, REALM, AUDIT
|
||||
APPLICATION, CLIENT, USER, REALM, EVENTS
|
||||
}
|
||||
|
||||
private AdminAuth auth;
|
||||
@@ -65,8 +65,8 @@ public class RealmAuth {
|
||||
return AdminRoles.VIEW_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.VIEW_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.VIEW_AUDIT;
|
||||
case EVENTS:
|
||||
return AdminRoles.VIEW_EVENTS;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -82,8 +82,8 @@ public class RealmAuth {
|
||||
return AdminRoles.MANAGE_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.MANAGE_REALM;
|
||||
case AUDIT:
|
||||
return AdminRoles.MANAGE_AUDIT;
|
||||
case EVENTS:
|
||||
return AdminRoles.MANAGE_EVENTS;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,7 +1,7 @@
|
||||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.keycloak.audit.AuditListener;
|
||||
import org.keycloak.events.EventListenerProvider;
|
||||
import org.keycloak.freemarker.Theme;
|
||||
import org.keycloak.freemarker.ThemeProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
@@ -26,7 +26,7 @@ public class ServerInfoAdminResource {
|
||||
private KeycloakSession session;
|
||||
|
||||
/**
|
||||
* Returns a list of themes, social providers, auth providers, and audit listeners available on this server
|
||||
* Returns a list of themes, social providers, auth providers, and event listeners available on this server
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@@ -36,7 +36,7 @@ public class ServerInfoAdminResource {
|
||||
ServerInfoRepresentation info = new ServerInfoRepresentation();
|
||||
setSocialProviders(info);
|
||||
setThemes(info);
|
||||
setAuditListeners(info);
|
||||
setEventListeners(info);
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -60,12 +60,12 @@ public class ServerInfoAdminResource {
|
||||
Collections.sort(info.socialProviders);
|
||||
}
|
||||
|
||||
private void setAuditListeners(ServerInfoRepresentation info) {
|
||||
info.auditListeners = new LinkedList<String>();
|
||||
private void setEventListeners(ServerInfoRepresentation info) {
|
||||
info.eventListeners = new LinkedList<String>();
|
||||
|
||||
Set<String> providers = session.listProviderIds(AuditListener.class);
|
||||
Set<String> providers = session.listProviderIds(EventListenerProvider.class);
|
||||
if (providers != null) {
|
||||
info.auditListeners.addAll(providers);
|
||||
info.eventListeners.addAll(providers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ServerInfoAdminResource {
|
||||
private List<String> socialProviders;
|
||||
|
||||
|
||||
private List<String> auditListeners;
|
||||
private List<String> eventListeners;
|
||||
|
||||
public ServerInfoRepresentation() {
|
||||
}
|
||||
@@ -89,8 +89,8 @@ public class ServerInfoAdminResource {
|
||||
return socialProviders;
|
||||
}
|
||||
|
||||
public List<String> getAuditListeners() {
|
||||
return auditListeners;
|
||||
public List<String> getEventListeners() {
|
||||
return eventListeners;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.BadRequestException;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.email.EmailException;
|
||||
import org.keycloak.email.EmailProvider;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
|
||||
@@ -26,9 +26,9 @@ import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
|
||||
import org.jboss.resteasy.spi.HttpRequest;
|
||||
import org.keycloak.ClientConnection;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.audit.Audit;
|
||||
import org.keycloak.audit.Details;
|
||||
import org.keycloak.audit.EventType;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
@@ -124,7 +124,7 @@ public class OAuthFlows {
|
||||
return Response.status(302).location(redirectUri.build()).build();
|
||||
}
|
||||
|
||||
public Response processAccessCode(String scopeParam, String state, String redirect, ClientModel client, UserModel user, UserSessionModel session, Audit audit) {
|
||||
public Response processAccessCode(String scopeParam, String state, String redirect, ClientModel client, UserModel user, UserSessionModel session, EventBuilder event) {
|
||||
isTotpConfigurationRequired(user);
|
||||
isEmailVerificationRequired(user);
|
||||
|
||||
@@ -135,7 +135,7 @@ public class OAuthFlows {
|
||||
log.debugv("processAccessCode: go to oauth page?: {0}",
|
||||
!isResource);
|
||||
|
||||
audit.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
event.detail(Details.CODE_ID, accessCode.getCodeId());
|
||||
|
||||
Set<RequiredAction> requiredActions = user.getRequiredActions();
|
||||
if (!requiredActions.isEmpty()) {
|
||||
@@ -143,7 +143,7 @@ public class OAuthFlows {
|
||||
accessCode.setRequiredAction(action);
|
||||
|
||||
if (action.equals(RequiredAction.VERIFY_EMAIL)) {
|
||||
audit.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
|
||||
event.clone().event(EventType.SEND_VERIFY_EMAIL).detail(Details.EMAIL, accessCode.getUser().getEmail()).success();
|
||||
}
|
||||
|
||||
return Flows.forms(this.session, realm, client, uriInfo).setAccessCode(accessCode.getCode()).setUser(user)
|
||||
@@ -171,7 +171,7 @@ public class OAuthFlows {
|
||||
}
|
||||
|
||||
if (redirect != null) {
|
||||
audit.success();
|
||||
event.success();
|
||||
|
||||
accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN);
|
||||
return redirectAccessCode(accessCode, session, state, redirect);
|
||||
|
||||
+7
-7
@@ -1,22 +1,22 @@
|
||||
package org.keycloak.services.scheduled;
|
||||
|
||||
import org.keycloak.audit.AuditProvider;
|
||||
import org.keycloak.events.EventStoreProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class ClearExpiredAuditEvents implements ScheduledTask {
|
||||
public class ClearExpiredEvents implements ScheduledTask {
|
||||
|
||||
@Override
|
||||
public void run(KeycloakSession session) {
|
||||
AuditProvider audit = session.getProvider(AuditProvider.class);
|
||||
if (audit != null) {
|
||||
EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
|
||||
if (eventStore != null) {
|
||||
for (RealmModel realm : session.realms().getRealms()) {
|
||||
if (realm.isAuditEnabled() && realm.getAuditExpiration() > 0) {
|
||||
long olderThan = System.currentTimeMillis() - realm.getAuditExpiration() * 1000;
|
||||
audit.clear(realm.getId(), olderThan);
|
||||
if (realm.isEventsEnabled() && realm.getEventsExpiration() > 0) {
|
||||
long olderThan = System.currentTimeMillis() - realm.getEventsExpiration() * 1000;
|
||||
eventStore.clear(realm.getId(), olderThan);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user