From 93213c988dc3b574f18883e0082e0b411f0c6322 Mon Sep 17 00:00:00 2001 From: Akvel Date: Mon, 18 Sep 2023 17:56:10 +0300 Subject: [PATCH 1/2] Added ability to set token's lifespan for server mode Signed-off-by: Akvel --- .../keycloakmock/api/ServerConfig.java | 30 +++++++++++++++++++ .../tngtech/keycloakmock/api/TokenConfig.java | 6 ++++ .../impl/dagger/ServerModule.java | 8 +++++ .../keycloakmock/impl/helper/TokenHelper.java | 15 +++++++--- .../impl/helper/TokenHelperTest.java | 7 +++-- 5 files changed, 59 insertions(+), 7 deletions(-) diff --git a/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java b/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java index 8b6561b..83ab7e6 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java @@ -1,6 +1,8 @@ package com.tngtech.keycloakmock.api; import com.tngtech.keycloakmock.impl.Protocol; + +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -17,6 +19,7 @@ public final class ServerConfig { private static final int DEFAULT_PORT = 8000; private static final String DEFAULT_REALM = "master"; private static final String DEFAULT_SCOPE = "openid"; + private static final Duration DEFAULT_TOKEN_LIFESPAN = Duration.ofHours(10); private final int port; @Nonnull private final Protocol protocol; @@ -25,6 +28,7 @@ public final class ServerConfig { @Nonnull private final String defaultRealm; @Nonnull private final List resourcesToMapRolesTo; @Nonnull private final Set defaultScopes; + @Nonnull private final Duration tokenLifespan; private ServerConfig(@Nonnull final Builder builder) { this.port = builder.port; @@ -34,6 +38,7 @@ private ServerConfig(@Nonnull final Builder builder) { this.defaultRealm = builder.defaultRealm; this.resourcesToMapRolesTo = builder.resourcesToMapRolesTo; this.defaultScopes = builder.defaultScopes; + this.tokenLifespan = builder.tokenLifespan; } /** @@ -148,6 +153,16 @@ public Set getDefaultScopes() { return Collections.unmodifiableSet(defaultScopes); } + /** + * Get access token lifespan + * + * @return token lifespan + */ + @Nonnull + public Duration getTokenLifespan() { + return tokenLifespan; + } + /** * Builder for {@link ServerConfig}. * @@ -162,6 +177,7 @@ public static final class Builder { @Nonnull private String defaultRealm = DEFAULT_REALM; @Nonnull private final List resourcesToMapRolesTo = new ArrayList<>(); @Nonnull private final Set defaultScopes = new HashSet<>(); + @Nonnull private Duration tokenLifespan = DEFAULT_TOKEN_LIFESPAN; private Builder() { defaultScopes.add(DEFAULT_SCOPE); @@ -365,6 +381,20 @@ public Builder withDefaultScope(@Nonnull final String defaultScope) { return this; } + /** + * Set default access token lifespan ("exp" filed will be set as issuedAt + tokenLifespan) + * By default lifespan 10 hours. + * + * @param tokenLifespan as duration + * @return builder + * + */ + @Nonnull + public Builder withTokenLifespan(@Nonnull final Duration tokenLifespan) { + this.tokenLifespan = tokenLifespan; + return this; + } + /** * Build the server configuration. * diff --git a/mock/src/main/java/com/tngtech/keycloakmock/api/TokenConfig.java b/mock/src/main/java/com/tngtech/keycloakmock/api/TokenConfig.java index 1eebbd7..e8d2aef 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/api/TokenConfig.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/api/TokenConfig.java @@ -5,6 +5,7 @@ import io.jsonwebtoken.Jwts; import java.net.URI; import java.net.URISyntaxException; +import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -762,6 +763,11 @@ public Builder withAuthenticationContextClassReference( public TokenConfig build() { return new TokenConfig(this); } + + public Builder witTokenLifespan(Duration tokenLifespan) { + this.expiration = issuedAt.plus(tokenLifespan); + return this; + } } /** diff --git a/mock/src/main/java/com/tngtech/keycloakmock/impl/dagger/ServerModule.java b/mock/src/main/java/com/tngtech/keycloakmock/impl/dagger/ServerModule.java index 70ed932..e3441ff 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/impl/dagger/ServerModule.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/impl/dagger/ServerModule.java @@ -35,6 +35,7 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; +import java.time.Duration; import java.util.List; import java.util.Set; import javax.annotation.Nonnull; @@ -96,6 +97,13 @@ public Set provideScopes(@Nonnull ServerConfig serverConfig) { return serverConfig.getDefaultScopes(); } + @Provides + @Singleton + @Named("tokenLifespan") + public Duration provideTokenLifespan(@Nonnull ServerConfig serverConfig) { + return serverConfig.getTokenLifespan(); + } + @Provides @Singleton Buffer keystoreBuffer(@Nonnull KeyStore keyStore) { diff --git a/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java b/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java index 74a60e7..6ea2a65 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java @@ -7,6 +7,8 @@ import com.tngtech.keycloakmock.impl.UrlConfiguration; import com.tngtech.keycloakmock.impl.session.Session; import com.tngtech.keycloakmock.impl.session.UserData; + +import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Set; @@ -26,14 +28,18 @@ public class TokenHelper { @Nonnull private final List resourcesToMapRolesTo; @Nonnull private final Set defaultScopes; + @Nonnull private final Duration tokenLifespan; + @Inject TokenHelper( - @Nonnull TokenGenerator tokenGenerator, - @Nonnull @Named("resources") List resourcesToMapRolesTo, - @Nonnull @Named("scopes") Set defaultScopes) { + @Nonnull TokenGenerator tokenGenerator, + @Nonnull @Named("resources") List resourcesToMapRolesTo, + @Nonnull @Named("scopes") Set defaultScopes, + @Nonnull @Named("tokenLifespan") Duration tokenLifespan) { this.tokenGenerator = tokenGenerator; this.resourcesToMapRolesTo = resourcesToMapRolesTo; this.defaultScopes = defaultScopes; + this.tokenLifespan = tokenLifespan; } @Nullable @@ -53,7 +59,8 @@ public String getToken(@Nonnull Session session, @Nonnull UrlConfiguration reque .withClaim(SESSION_STATE, session.getSessionId()) // we currently don't do proper authorization anyway, so we can just act as if we were // compliant to ISO/IEC 29115 level 1 (see KEYCLOAK-3223 / KEYCLOAK-3314) - .withAuthenticationContextClassReference("1"); + .withAuthenticationContextClassReference("1") + .witTokenLifespan(tokenLifespan); if (session.getNonce() != null) { builder.withClaim(NONCE, session.getNonce()); } diff --git a/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java b/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java index dd50c36..95da198 100644 --- a/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java +++ b/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java @@ -10,6 +10,7 @@ import com.tngtech.keycloakmock.impl.UrlConfiguration; import com.tngtech.keycloakmock.impl.session.PersistentSession; import com.tngtech.keycloakmock.impl.session.UserData; +import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -55,7 +56,7 @@ void setup() { @Test void token_is_correctly_generated() { - uut = new TokenHelper(tokenGenerator, Collections.emptyList(), Collections.emptySet()); + uut = new TokenHelper(tokenGenerator, Collections.emptyList(), Collections.emptySet(), Duration.ofHours(100)); uut.getToken(session, urlConfiguration); @@ -68,7 +69,7 @@ void token_is_correctly_generated() { assertThat(tokenConfig.getClaims()) .containsEntry("nonce", NONCE) .containsEntry("session_state", SESSION_ID); - assertThat(tokenConfig.getExpiration()).isAfter(Instant.now().plus(9, ChronoUnit.HOURS)); + assertThat(tokenConfig.getExpiration()).isAfter(Instant.now().plus(99, ChronoUnit.HOURS)); assertThat(tokenConfig.getGivenName()).isEqualTo(USER.getGivenName()); assertThat(tokenConfig.getFamilyName()).isEqualTo(USER.getFamilyName()); assertThat(tokenConfig.getName()).isEqualTo(USER.getName()); @@ -82,7 +83,7 @@ void token_is_correctly_generated() { @Test void resource_roles_are_used_if_configured() { - uut = new TokenHelper(tokenGenerator, CONFIGURED_RESOURCES, Collections.emptySet()); + uut = new TokenHelper(tokenGenerator, CONFIGURED_RESOURCES, Collections.emptySet(), Duration.ofHours(10)); uut.getToken(session, urlConfiguration); From 7d3d67348386d8bbee2a79fc5ac68caaa2fc863b Mon Sep 17 00:00:00 2001 From: Akvel Date: Mon, 25 Sep 2023 17:31:55 +0300 Subject: [PATCH 2/2] Fixed pre-commit checks Signed-off-by: Akvel Amended by ostrya --- .../java/com/tngtech/keycloakmock/api/ServerConfig.java | 6 ++---- .../tngtech/keycloakmock/impl/helper/TokenHelper.java | 9 ++++----- .../keycloakmock/impl/helper/TokenHelperTest.java | 8 ++++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java b/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java index 83ab7e6..f324985 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/api/ServerConfig.java @@ -1,7 +1,6 @@ package com.tngtech.keycloakmock.api; import com.tngtech.keycloakmock.impl.Protocol; - import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -382,12 +381,11 @@ public Builder withDefaultScope(@Nonnull final String defaultScope) { } /** - * Set default access token lifespan ("exp" filed will be set as issuedAt + tokenLifespan) - * By default lifespan 10 hours. + * Set default access token lifespan ("exp" filed will be set as issuedAt + tokenLifespan). + By + * default lifespan 10 hours. * * @param tokenLifespan as duration * @return builder - * */ @Nonnull public Builder withTokenLifespan(@Nonnull final Duration tokenLifespan) { diff --git a/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java b/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java index 6ea2a65..dff30ae 100644 --- a/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java +++ b/mock/src/main/java/com/tngtech/keycloakmock/impl/helper/TokenHelper.java @@ -7,7 +7,6 @@ import com.tngtech.keycloakmock.impl.UrlConfiguration; import com.tngtech.keycloakmock.impl.session.Session; import com.tngtech.keycloakmock.impl.session.UserData; - import java.time.Duration; import java.util.List; import java.util.Map; @@ -32,10 +31,10 @@ public class TokenHelper { @Inject TokenHelper( - @Nonnull TokenGenerator tokenGenerator, - @Nonnull @Named("resources") List resourcesToMapRolesTo, - @Nonnull @Named("scopes") Set defaultScopes, - @Nonnull @Named("tokenLifespan") Duration tokenLifespan) { + @Nonnull TokenGenerator tokenGenerator, + @Nonnull @Named("resources") List resourcesToMapRolesTo, + @Nonnull @Named("scopes") Set defaultScopes, + @Nonnull @Named("tokenLifespan") Duration tokenLifespan) { this.tokenGenerator = tokenGenerator; this.resourcesToMapRolesTo = resourcesToMapRolesTo; this.defaultScopes = defaultScopes; diff --git a/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java b/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java index 95da198..cfc5e31 100644 --- a/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java +++ b/mock/src/test/java/com/tngtech/keycloakmock/impl/helper/TokenHelperTest.java @@ -56,7 +56,9 @@ void setup() { @Test void token_is_correctly_generated() { - uut = new TokenHelper(tokenGenerator, Collections.emptyList(), Collections.emptySet(), Duration.ofHours(100)); + uut = + new TokenHelper( + tokenGenerator, Collections.emptyList(), Collections.emptySet(), Duration.ofHours(100)); uut.getToken(session, urlConfiguration); @@ -83,7 +85,9 @@ void token_is_correctly_generated() { @Test void resource_roles_are_used_if_configured() { - uut = new TokenHelper(tokenGenerator, CONFIGURED_RESOURCES, Collections.emptySet(), Duration.ofHours(10)); + uut = + new TokenHelper( + tokenGenerator, CONFIGURED_RESOURCES, Collections.emptySet(), Duration.ofHours(10)); uut.getToken(session, urlConfiguration);