8000 Rewrite AssertEvents expectLoginEvent to EventAssertion. by lhanusov · Pull Request #48467 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.keycloak.testframework.events;

import java.util.Set;

import org.keycloak.events.Details;
import org.keycloak.events.EventType;
import org.keycloak.representations.idm.EventRepresentation;
Expand Down Expand Up @@ -49,6 +51,34 @@ public static EventAssertion assertError(EventRepresentation event) {
return new EventAssertion(event);
}

/**
* Assert an expected LOGIN event
*
* @param event the event to assert
* @return
*/
public static EventAssertion expectLoginSuccess(EventRepresentation event) {
return assertSuccess(event)
.type(EventType.LOGIN)
.isCodeId()
.hasSessionId()
.hasIpAddress()
.loginSuccessEventHasAllRequiredDetails();
}

/**
* Assert an expected LOGIN_ERROR event
*
* @param event the event to assert
* @return
*/
public static EventAssertion expectLoginError(EventRepresentation event) {
return assertError(event)
.type(EventType.LOGIN_ERROR)
.isCodeId()
.hasIpAddress();
}

/**
* Assert the error message
*
Expand Down Expand Up @@ -81,6 +111,16 @@ public EventAssertion hasSessionId() {
return this;
}

/**
* Assert the event has a userId set
*
* @return
*/
public EventAssertion hasUserId() {
MatcherAssert.assertThat(event.getUserId(), EventMatchers.isUUID());
return this;
}

/**
* Assert the event has the <code>code_id</code> details set
* @return
Expand Down Expand Up @@ -163,6 +203,19 @@ public EventAssertion withoutDetails(String... keys) {
return this;
}

/**
* Assert the LOGIN event details with required key set
*
* @return
*/
private EventAssertion loginSuccessEventHasAllRequiredDetails() {
Set<String> keyDetails = Set.of("auth_method", "response_type", "redirect_uri", "consent", "code_id", "response_mode");
for (String key : keyDetails) {
MatcherAssert.assertThat(event.getDetails(), Matchers.hasKey(key));
}
return this;
}

/**
* Return the event associated to the assertion.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ public void clientConsentRequiredAfterLogin() {
.isCodeId()
.details(Details.USERNAME, userFromUserRealm.getUsername())
.details(Details.CONSENT, Details.CONSENT_VALUE_NO_CONSENT_REQUIRED)
.details(Details.REDIRECT_URI, "http://127.0.0.1:8500/callback/oauth");
.details(Details.REDIRECT_URI, userRealmOAuth.getRedirectUri());

userRealm.updateWithCleanup(r -> r.enabledEventTypes("REFRESH_TOKEN_ERROR"));
String sessionId = loginEvent.getSessionId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void eventAttributesTest() {
.details(Details.AUTH_METHOD, "openid-connect")
.details(Details.AUTH_TYPE, "code")
.details(Details.USERNAME, "bad")
.details(Details.REDIRECT_URI, "http://127.0.0.1:8500/callback/oauth");
.details(Details.REDIRECT_URI, oAuthClient.getRedirectUri());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.keycloak.models.Constants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultAuthenticationFlows;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
Expand All @@ -41,6 +42,7 @@
import org.keycloak.testframework.annotations.TestSetup;
import org.keycloak.testframework.events.EventAssertion;
import org.keycloak.testframework.events.Events;
import org.keycloak.testframework.injection.LifeCycle;
import org.keycloak.testframework.mail.MailServer;
import org.keycloak.testframework.mail.annotations.InjectMailServer;
import org.keycloak.testframework.oauth.OAuthClient;
Expand Down Expand Up @@ -87,7 +89,7 @@ public class UserSessionLimitsTest {
@InjectWebDriver
ManagedWebDriver driver;

@InjectOAuthClient
@InjectOAuthClient(lifecycle = LifeCycle.METHOD)
OAuthClient oauth;

@InjectEvents
Expand All @@ -113,7 +115,6 @@ public class UserSessionLimitsTest {
private static final String password = "password";
private static final String directGrant1 = "direct-grant-1";
private static final String directGrant2 = "direct-grant-2";
private static String defaultRedirectUri = null;

@BeforeEach
public void setup() {
Expand All @@ -126,15 +127,10 @@ public void setup() {
session.sessions().removeUserSessions(realm);

// Reset password
org.keycloak.models.UserModel user = session.users().getUserByUsername(realm, username);
UserModel user = session.users().getUserByUsername(realm, username);
user.credentialManager().updateCredential(UserCredentialModel.password(password));
});

if (defaultRedirectUri == null) {
defaultRedirectUri = oauth.getRedirectUri();
}
oauth.redirectUri(defaultRedirectUri);

events.clear();
}

Expand Down Expand Up @@ -402,6 +398,7 @@ public void testRealmSessionCountAndClientSessionCountExceededAndOldestClientSes
}
}

@Test
public void testRealmSessionCountAndClientSessionCountExceededAndDecreaseLimitsAfterActiveSessionsAreCreated() throws Exception {
try {
setAuthenticatorConfigItem(DefaultAuthenticationFlows.DIRECT_GRANT_FLOW, UserSessionLimitsAuthenticatorFactory.BEHAVIOR, UserSessionLimitsAuthenticatorFactory.TERMINATE_OLDEST_SESSION);
Expand Down
A311
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package org.keycloak.testframework.events;

import java.util.Set;

import org.keycloak.events.Details;
import org.keycloak.events.EventType;
import org.keycloak.representations.idm.EventRepresentation;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;

import static org.hamcrest.Matchers.is;

/**
* Helper to assert login events
*/
public class EventAssertion {

private final EventRepresentation event;

private static final String DEFAULT_IP_ADDRESS = "127.0.0.1";
private static final String DEFAULT_IP_ADDRESS_V6 = "0:0:0:0:0:0:0:1";
private static final String DEFAULT_IP_ADDRESS_V6_SHORT = "::1";

protected EventAssertion(EventRepresentation event) {
Assertions.assertNotNull(event, "Event was null");
Assertions.assertNotNull(event.getId(), "Event id was null");
this.event = event;
}

/**
* Assert an expected successfull event
*
* @param event the event to assert
* @return
*/
public static EventAssertion assertSuccess(EventRepresentation event) {
Assertions.assertFalse(event.getType().endsWith("_ERROR"), "Expected successful event");
return new EventAssertion(event);
}

/**
* Assert an expected error event
*
* @param event the event to assert
* @return
*/
public static EventAssertion assertError(EventRepresentation event) {
Assertions.assertTrue(event.getType().endsWith("_ERROR"), "Expected error event");
return new EventAssertion(event);
}

/**
* Assert an expected LOGIN event
*
* @param event the event to assert
* @return
*/
public static EventAssertion expectLoginSuccess(EventRepresentation event) {
return assertSuccess(event)
.type(EventType.LOGIN)
.isCodeId()
.hasSessionId()
.hasIpAddress()
.loginSuccessEventHasAllRequiredDetails();
}

/**
* Assert an expected LOGIN_ERROR event
*
* @param event the event to assert
* @return
*/
public static EventAssertion expectLoginError(EventRepresentation event) {
return assertError(event)
.type(EventType.LOGIN_ERROR)
.isCodeId()
.hasIpAddress();
}

/**
* Assert the error message
*
* @param error the expected error message
* @return
*/
public EventAssertion error(String error) {
Assertions.assertEquals(error, event.getError());
return this;
}

/**
* Assert the type of the event
*
* @param type the expected type of the event
* @return
*/
public EventAssertion type(EventType type) {
Assertions.assertEquals(type, EventType.valueOf(event.getType()));
return this;
}

/**
* Assert the event has a sessionId set
*
* @return
*/
public EventAssertion hasSessionId() {
MatcherAssert.assertThat(event.getSessionId(), EventMatchers.isSessionId());
return this;
}

/**
* Assert the event has a userId set
*
* @return
*/
public EventAssertion hasUserId() {
MatcherAssert.assertThat(event.getUserId(), EventMatchers.isUUID());
return this;
}

/**
* Assert the event has the <code>code_id</code> details set
* @return
*/
public EventAssertion isCodeId() {
MatcherAssert.assertThat(event.getDetails().get(Details.CODE_ID), EventMatchers.isCodeId());
return this;
}

/**
* Assert the event has an ipAddress set
* @return
*/
public EventAssertion hasIpAddress() {
Assertions.assertNotNull(event.getIpAddress());
Assertions.assertFalse(event.getIpAddress().isEmpty());
MatcherAssert.assertThat(event.getIpAddress(), Matchers.anyOf(is(DEFAULT_IP_ADDRESS), is(DEFAULT_IP_ADDRESS_V6), is(DEFAULT_IP_ADDRESS_V6_SHORT)));
return this;
}

/**
* Assert the clientId for the event
*
* @param clientId the expected clientId
* @return
*/
public EventAssertion clientId(String clientId) {
Assertions.assertEquals(clientId, event.getClientId());
return this;
}

/**
* Assert the sessionId for the event
*
* @param sessionId the expected sessionId
* @return
*/
public EventAssertion sessionId(String sessionId) {
Assertions.assertEquals(sessionId, event.getSessionId());
return this;
}

/**
* Assert the userId (sub) of the event
*
* @param userId the expected userId
* @return
*/
public EventAssertion userId(String userId) {
Assertions.assertEquals(userId, event.getUserId());
return this;
}

/**
* Assert the event has an entry in the details map with the specified key and value
*
* @param key the expected details key
* @param value the expected details value
* @return
*/
public EventAssertion details(String key, String value) {
if (value != null) {
MatcherAssert.assertThat(event.getDetails(), Matchers.hasEntry(key, value));
} else {
withoutDetails(key);
}
return this;
}

/**
* Assert the event details map does not contain the specified keys
*
* @param keys the list of keys that are not expected in the details map
* @return
*/
public EventAssertion withoutDetails(String... keys) {
for (String key : keys) {
MatcherAssert.assertThat(event.getDetails(), Matchers.not(Matchers.hasKey(key)));
}
return this;
}

/**
* Assert the LOGIN event details with required key set
*
* @return
*/
private EventAssertion loginSuccessEventHasAllRequiredDetails() {
Set<String> keyDetails = Set.of("auth_method", "response_type", "redirect_uri", "consent", "code_id", "response_mode");
for (String key : keyDetails) {
MatcherAssert.assertThat(event.getDetails(), Matchers.hasKey(key));
}
return this;
}

/**
* Return the event associated to the assertion.
*
* @return the asserted {@link EventRepresentation}
*/
public EventRepresentation getEvent() {
return event;
}
}
Loading
Loading
0