Add ability to set principalClaimName in ReactiveJwtAuthenticationConverter

Closes #12907
This commit is contained in:
Marcus Kainth 2023-03-20 19:38:27 +00:00 committed by Josh Cummings
parent 46a40e7b38
commit f0ef54050e
2 changed files with 64 additions and 3 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,6 +23,7 @@ import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtClaimNames;
import org.springframework.util.Assert;
/**
@ -30,6 +31,7 @@ import org.springframework.util.Assert;
* a {@link AbstractAuthenticationToken Mono<AbstractAuthenticationToken>}.
*
* @author Eric Deandrea
* @author Marcus Kainth
* @since 5.2
*/
public final class ReactiveJwtAuthenticationConverter implements Converter<Jwt, Mono<AbstractAuthenticationToken>> {
@ -37,12 +39,17 @@ public final class ReactiveJwtAuthenticationConverter implements Converter<Jwt,
private Converter<Jwt, Flux<GrantedAuthority>> jwtGrantedAuthoritiesConverter = new ReactiveJwtGrantedAuthoritiesConverterAdapter(
new JwtGrantedAuthoritiesConverter());
private String principalClaimName = JwtClaimNames.SUB;
@Override
public Mono<AbstractAuthenticationToken> convert(Jwt jwt) {
// @formatter:off
return this.jwtGrantedAuthoritiesConverter.convert(jwt)
.collectList()
.map((authorities) -> new JwtAuthenticationToken(jwt, authorities));
.map((authorities) -> {
String principalName = jwt.getClaimAsString(this.principalClaimName);
return new JwtAuthenticationToken(jwt, authorities, principalName);
});
// @formatter:on
}
@ -58,4 +65,14 @@ public final class ReactiveJwtAuthenticationConverter implements Converter<Jwt,
this.jwtGrantedAuthoritiesConverter = jwtGrantedAuthoritiesConverter;
}
/**
* Sets the principal claim name. Defaults to {@link JwtClaimNames#SUB}.
* @param principalClaimName The principal claim name
* @since 6.1
*/
public void setPrincipalClaimName(String principalClaimName) {
Assert.hasText(principalClaimName, "principalClaimName cannot be empty");
this.principalClaimName = principalClaimName;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* Tests for {@link ReactiveJwtAuthenticationConverter}
*
* @author Eric Deandrea
* @author Marcus Kainth
* @since 5.2
*/
public class ReactiveJwtAuthenticationConverterTests {
@ -68,4 +69,47 @@ public class ReactiveJwtAuthenticationConverterTests {
assertThat(authorities).containsExactly(new SimpleGrantedAuthority("blah"));
}
@Test
public void whenSettingNullPrincipalClaimName() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.jwtAuthenticationConverter.setPrincipalClaimName(null))
.withMessage("principalClaimName cannot be empty");
// @formatter:on
}
@Test
public void whenSettingEmptyPrincipalClaimName() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.jwtAuthenticationConverter.setPrincipalClaimName(""))
.withMessage("principalClaimName cannot be empty");
// @formatter:on
}
@Test
public void whenSettingBlankPrincipalClaimName() {
// @formatter:off
assertThatIllegalArgumentException()
.isThrownBy(() -> this.jwtAuthenticationConverter.setPrincipalClaimName(" "))
.withMessage("principalClaimName cannot be empty");
// @formatter:on
}
@Test
public void convertWhenPrincipalClaimNameSet() {
this.jwtAuthenticationConverter.setPrincipalClaimName("user_id");
Jwt jwt = TestJwts.jwt().claim("user_id", "100").build();
AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block();
assertThat(authentication.getName()).isEqualTo("100");
}
@Test
public void convertWhenPrincipalClaimNameSetAndClaimValueIsNotString() {
this.jwtAuthenticationConverter.setPrincipalClaimName("user_id");
Jwt jwt = TestJwts.jwt().claim("user_id", 100).build();
AbstractAuthenticationToken authentication = this.jwtAuthenticationConverter.convert(jwt).block();
assertThat(authentication.getName()).isEqualTo("100");
}
}