Fix auth_time claim should represent authentication time
Closes gh-18282
This commit is contained in:
+15
-7
@@ -60,6 +60,7 @@ import org.springframework.security.config.test.SpringTestContext;
|
|||||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
import org.springframework.security.core.session.SessionRegistry;
|
import org.springframework.security.core.session.SessionRegistry;
|
||||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||||
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
|
||||||
@@ -210,7 +211,8 @@ public class OidcTests {
|
|||||||
registeredClient);
|
registeredClient);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user").roles("A", "B")))
|
.with(user("user").roles("A", "B")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
||||||
@@ -270,7 +272,8 @@ public class OidcTests {
|
|||||||
registeredClient);
|
registeredClient);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user").roles("A", "B")))
|
.with(user("user").roles("A", "B")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
||||||
@@ -335,7 +338,8 @@ public class OidcTests {
|
|||||||
registeredClient);
|
registeredClient);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)).queryParams(authorizationRequestParameters)
|
.perform(get(issuer.concat(DEFAULT_AUTHORIZATION_ENDPOINT_URI)).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user")))
|
.with(user("user")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
@@ -388,7 +392,8 @@ public class OidcTests {
|
|||||||
registeredClient1);
|
registeredClient1);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user1")))
|
.with(user("user1")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
@@ -424,7 +429,8 @@ public class OidcTests {
|
|||||||
authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient2);
|
authorizationRequestParameters = getAuthorizationRequestParameters(registeredClient2);
|
||||||
mvcResult = this.mvc
|
mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user2")))
|
.with(user("user2")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
@@ -497,7 +503,8 @@ public class OidcTests {
|
|||||||
registeredClient);
|
registeredClient);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user")))
|
.with(user("user")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
||||||
@@ -537,7 +544,8 @@ public class OidcTests {
|
|||||||
registeredClient);
|
registeredClient);
|
||||||
MvcResult mvcResult = this.mvc
|
MvcResult mvcResult = this.mvc
|
||||||
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
.perform(get(DEFAULT_AUTHORIZATION_ENDPOINT_URI).queryParams(authorizationRequestParameters)
|
||||||
.with(user("user")))
|
.with(user("user")
|
||||||
|
.authorities(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY))))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andReturn();
|
.andReturn();
|
||||||
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
|
||||||
|
|||||||
+17
-1
@@ -24,6 +24,9 @@ import java.util.Date;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
import org.springframework.security.core.session.SessionInformation;
|
import org.springframework.security.core.session.SessionInformation;
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||||
@@ -141,7 +144,7 @@ public final class JwtGenerator implements OAuth2TokenGenerator<Jwt> {
|
|||||||
SessionInformation sessionInformation = context.get(SessionInformation.class);
|
SessionInformation sessionInformation = context.get(SessionInformation.class);
|
||||||
if (sessionInformation != null) {
|
if (sessionInformation != null) {
|
||||||
claimsBuilder.claim("sid", sessionInformation.getSessionId());
|
claimsBuilder.claim("sid", sessionInformation.getSessionId());
|
||||||
claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, sessionInformation.getLastRequest());
|
claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, getAuthenticationTime(context.getPrincipal()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (AuthorizationGrantType.REFRESH_TOKEN.equals(context.getAuthorizationGrantType())) {
|
else if (AuthorizationGrantType.REFRESH_TOKEN.equals(context.getAuthorizationGrantType())) {
|
||||||
@@ -222,4 +225,17 @@ public final class JwtGenerator implements OAuth2TokenGenerator<Jwt> {
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Date getAuthenticationTime(Authentication authentication) {
|
||||||
|
Instant authenticationTime = null;
|
||||||
|
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
|
||||||
|
if (grantedAuthority instanceof FactorGrantedAuthority factorGrantedAuthority) {
|
||||||
|
if (authenticationTime == null || factorGrantedAuthority.getIssuedAt().isAfter(authenticationTime)) {
|
||||||
|
authenticationTime = factorGrantedAuthority.getIssuedAt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.notNull(authenticationTime, "authenticationTime cannot be null");
|
||||||
|
return Date.from(authenticationTime);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -24,6 +24,9 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.authority.FactorGrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||||
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||||
@@ -85,6 +88,9 @@ public final class TestOAuth2Authorizations {
|
|||||||
.additionalParameters(authorizationRequestAdditionalParameters)
|
.additionalParameters(authorizationRequestAdditionalParameters)
|
||||||
.state("state")
|
.state("state")
|
||||||
.build();
|
.build();
|
||||||
|
Authentication principal = new TestingAuthenticationToken("principal", null,
|
||||||
|
new SimpleGrantedAuthority("ROLE_A"), new SimpleGrantedAuthority("ROLE_B"),
|
||||||
|
FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY));
|
||||||
OAuth2Authorization.Builder builder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
OAuth2Authorization.Builder builder = OAuth2Authorization.withRegisteredClient(registeredClient)
|
||||||
.id("id")
|
.id("id")
|
||||||
.principalName("principal")
|
.principalName("principal")
|
||||||
@@ -93,8 +99,7 @@ public final class TestOAuth2Authorizations {
|
|||||||
.token(authorizationCode)
|
.token(authorizationCode)
|
||||||
.attribute(OAuth2ParameterNames.STATE, "consent-state")
|
.attribute(OAuth2ParameterNames.STATE, "consent-state")
|
||||||
.attribute(OAuth2AuthorizationRequest.class.getName(), authorizationRequest)
|
.attribute(OAuth2AuthorizationRequest.class.getName(), authorizationRequest)
|
||||||
.attribute(Principal.class.getName(),
|
.attribute(Principal.class.getName(), principal);
|
||||||
new TestingAuthenticationToken("principal", null, "ROLE_A", "ROLE_B"));
|
|
||||||
if (accessToken != null) {
|
if (accessToken != null) {
|
||||||
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now(),
|
OAuth2RefreshToken refreshToken = new OAuth2RefreshToken("refresh-token", Instant.now(),
|
||||||
Instant.now().plus(1, ChronoUnit.HOURS));
|
Instant.now().plus(1, ChronoUnit.HOURS));
|
||||||
|
|||||||
+1
-1
@@ -363,7 +363,7 @@ public class JwtGeneratorTests {
|
|||||||
SessionInformation sessionInformation = tokenContext.get(SessionInformation.class);
|
SessionInformation sessionInformation = tokenContext.get(SessionInformation.class);
|
||||||
assertThat(jwtClaimsSet.<String>getClaim("sid")).isEqualTo(sessionInformation.getSessionId());
|
assertThat(jwtClaimsSet.<String>getClaim("sid")).isEqualTo(sessionInformation.getSessionId());
|
||||||
assertThat(jwtClaimsSet.<Date>getClaim(IdTokenClaimNames.AUTH_TIME))
|
assertThat(jwtClaimsSet.<Date>getClaim(IdTokenClaimNames.AUTH_TIME))
|
||||||
.isEqualTo(sessionInformation.getLastRequest());
|
.isEqualTo(JwtGenerator.getAuthenticationTime(tokenContext.getPrincipal()));
|
||||||
}
|
}
|
||||||
else if (tokenContext.getAuthorizationGrantType().equals(AuthorizationGrantType.REFRESH_TOKEN)) {
|
else if (tokenContext.getAuthorizationGrantType().equals(AuthorizationGrantType.REFRESH_TOKEN)) {
|
||||||
OidcIdToken currentIdToken = tokenContext.getAuthorization().getToken(OidcIdToken.class).getToken();
|
OidcIdToken currentIdToken = tokenContext.getAuthorization().getToken(OidcIdToken.class).getToken();
|
||||||
|
|||||||
Reference in New Issue
Block a user