Polish MFA Samples

This commit removes unneeded AuthorizationManagerFactory
implementations, simplifies the custom AuthorizationManagerFactory
example, and updates usage of hasAllAuthorities.

Issue gh-17934
This commit is contained in:
Josh Cummings 2025-09-24 17:53:33 -06:00
parent f652920bb3
commit ad6fe4fdc3
No known key found for this signature in database
GPG Key ID: 869B37A20E876129
8 changed files with 78 additions and 269 deletions

View File

@ -13,10 +13,6 @@ import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler;
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasRole;
import static org.springframework.security.authorization.AuthorizationManagers.allOf;
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class ListAuthoritiesEverywhereConfiguration {
@ -27,8 +23,8 @@ public class ListAuthoritiesEverywhereConfiguration {
// @formatter:off
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers("/admin/**").access(allOf(hasAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY), hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY), hasRole("ADMIN"))) // <1>
.anyRequest().access(allOf(hasAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY), hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY)))
.requestMatchers("/admin/**").hasAllAuthorities(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY, GrantedAuthorities.FACTOR_OTT_AUTHORITY, "ROLE_ADMIN") // <1>
.anyRequest().hasAllAuthorities(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY, GrantedAuthorities.FACTOR_OTT_AUTHORITY)
)
.formLogin(Customizer.withDefaults())
.oneTimeTokenLogin(Customizer.withDefaults());

View File

@ -1,16 +1,12 @@
package org.springframework.security.docs.servlet.authentication.customauthorizationmanagerfactory;
import java.util.Collection;
import java.util.function.Supplier;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.SecurityExpressionOperations;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.authorization.AuthorityAuthorizationDecision;
import org.springframework.security.authorization.AuthorityAuthorizationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationManagerFactory;
@ -21,10 +17,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler;
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
@ -51,50 +46,31 @@ class CustomAuthorizationManagerFactory {
// tag::authorizationManager[]
@Component
class OptInToMfaAuthorizationManager implements AuthorizationManager<Object> {
class UserBasedOttAuthorizationManager implements AuthorizationManager<Object> {
@Override
public AuthorizationResult authorize(Supplier<? extends @Nullable Authentication> authentication, Object context) {
MyPrincipal principal = (MyPrincipal) authentication.get().getPrincipal();
if (principal.optedIn()) {
SecurityExpressionOperations sec = new SecurityExpressionRoot<>(authentication, context) {};
return new AuthorityAuthorizationDecision(sec.hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY),
AuthorityUtils.createAuthorityList(GrantedAuthorities.FACTOR_OTT_AUTHORITY));
if ("admin".equals(authentication.get().getName())) {
return AuthorityAuthorizationManager.hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY)
.authorize(authentication, context);
} else {
return new AuthorizationDecision(true);
}
return new AuthorizationDecision(true);
}
}
// end::authorizationManager[]
// tag::authorizationManagerFactory[]
@Bean
AuthorizationManagerFactory<Object> authorizationManagerFactory(OptInToMfaAuthorizationManager optIn) {
AuthorizationManagerFactory<Object> authorizationManagerFactory(UserBasedOttAuthorizationManager optIn) {
DefaultAuthorizationManagerFactory<Object> defaults = new DefaultAuthorizationManagerFactory<>();
defaults.setAdditionalAuthorization(optIn);
return defaults;
}
// end::authorizationManagerFactory[]
@NullMarked
record MyPrincipal(String username, boolean optedIn) implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return AuthorityUtils.createAuthorityList("app");
}
@Override
public @Nullable String getPassword() {
return null;
}
@Override
public String getUsername() {
return this.username;
}
}
@Bean
UserDetailsService users() {
return (username) -> new MyPrincipal(username, username.equals("optedin"));
public UserDetailsService users() {
return new InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin());
}
@Bean

View File

@ -20,19 +20,18 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.config.test.SpringTestContext;
import org.springframework.security.config.test.SpringTestContextExtension;
import org.springframework.security.core.GrantedAuthorities;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.docs.servlet.authentication.servletx509config.CustomX509Configuration;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user;
import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
@ -43,7 +42,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Rob Winch
*/
@ExtendWith(SpringTestContextExtension.class)
@ExtendWith({SpringExtension.class, SpringTestContextExtension.class})
@TestExecutionListeners(WithSecurityContextTestExecutionListener.class)
public class CustomAuthorizationManagerFactoryTests {
public final SpringTestContext spring = new SpringTestContext(this);
@ -51,40 +51,36 @@ public class CustomAuthorizationManagerFactoryTests {
@Autowired
MockMvc mockMvc;
@Autowired
UserDetailsService users;
@Test
void getWhenOptedInThenRedirectsToOtt() throws Exception {
@WithMockUser(username = "admin")
void getWhenAdminThenRedirectsToOtt() throws Exception {
this.spring.register(CustomAuthorizationManagerFactory.class, Http200Controller.class).autowire();
UserDetails user = this.users.loadUserByUsername("optedin");
// @formatter:off
this.mockMvc.perform(get("/").with(user(user)))
this.mockMvc.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("http://localhost/login?factor=ott"));
// @formatter:on
}
@Test
void getWhenNotOptedInThenAllows() throws Exception {
@WithMockUser
void getWhenNotAdminThenAllows() throws Exception {
this.spring.register(CustomAuthorizationManagerFactory.class, Http200Controller.class).autowire();
UserDetails user = this.users.loadUserByUsername("user");
// @formatter:off
this.mockMvc.perform(get("/").with(user(user)))
this.mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("user"));
// @formatter:on
}
@Test
void getWhenOptedAndHasFactorThenAllows() throws Exception {
@WithMockUser(username = "admin", authorities = GrantedAuthorities.FACTOR_OTT_AUTHORITY)
void getWhenAdminAndHasFactorThenAllows() throws Exception {
this.spring.register(CustomAuthorizationManagerFactory.class, Http200Controller.class).autowire();
UserDetails user = this.users.loadUserByUsername("optedin");
TestingAuthenticationToken token = new TestingAuthenticationToken(user, "", GrantedAuthorities.FACTOR_OTT_AUTHORITY);
// @formatter:off
this.mockMvc.perform(get("/").with(authentication(token)))
this.mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("optedin"));
.andExpect(authenticated().withUsername("admin"));
// @formatter:on
}

View File

@ -13,9 +13,6 @@ import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler;
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler;
import static org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
import static org.springframework.security.authorization.AuthorizationManagers.allOf;
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
class ListAuthoritiesConfiguration {
@ -26,7 +23,7 @@ class ListAuthoritiesConfiguration {
// @formatter:off
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().access(allOf(hasAuthority(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY), hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY))) // <1>
.anyRequest().hasAllAuthorities(GrantedAuthorities.FACTOR_PASSWORD_AUTHORITY, GrantedAuthorities.FACTOR_OTT_AUTHORITY) // <1>
)
.formLogin(Customizer.withDefaults())
.oneTimeTokenLogin(Customizer.withDefaults());
@ -36,7 +33,7 @@ class ListAuthoritiesConfiguration {
// end::httpSecurity[]
@Bean
UserDetailsService userDetailsService() {
UserDetailsService users() {
return new InMemoryUserDetailsManager(
User.withDefaultPasswordEncoder()
.username("user")

View File

@ -8,8 +8,6 @@ import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationManagerFactory;
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
import org.springframework.security.config.Customizer;
@ -22,12 +20,8 @@ import org.springframework.security.oauth2.client.registration.InMemoryClientReg
import org.springframework.security.oauth2.client.registration.TestClientRegistrations;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;
import static org.springframework.security.authorization.AllAuthoritiesAuthorizationManager.hasAllAuthorities;
import static org.springframework.security.authorization.AuthorizationManagers.allOf;
@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
class MissingAuthorityConfiguration {
@ -53,83 +47,13 @@ class MissingAuthorityConfiguration {
// tag::authorizationManagerFactoryBean[]
@Bean
AuthorizationManagerFactory<RequestAuthorizationContext> authz() {
return new FactorAuthorizationManagerFactory(hasAllAuthorities(GrantedAuthorities.FACTOR_X509_AUTHORITY, GrantedAuthorities.FACTOR_AUTHORIZATION_CODE_AUTHORITY));
AuthorizationManagerFactory<Object> authz() {
return DefaultAuthorizationManagerFactory.builder()
.requireAdditionalAuthorities(GrantedAuthorities.FACTOR_X509_AUTHORITY, GrantedAuthorities.FACTOR_AUTHORIZATION_CODE_AUTHORITY)
.build();
}
// end::authorizationManagerFactoryBean[]
// tag::authorizationManagerFactory[]
class FactorAuthorizationManagerFactory implements AuthorizationManagerFactory<RequestAuthorizationContext> {
private final AuthorizationManager<RequestAuthorizationContext> hasAuthorities;
private final DefaultAuthorizationManagerFactory<RequestAuthorizationContext> delegate =
new DefaultAuthorizationManagerFactory<>();
FactorAuthorizationManagerFactory(AuthorizationManager<RequestAuthorizationContext> hasAuthorities) {
this.hasAuthorities = hasAuthorities;
}
@Override
public AuthorizationManager<RequestAuthorizationContext> permitAll() {
return this.delegate.permitAll();
}
@Override
public AuthorizationManager<RequestAuthorizationContext> denyAll() {
return this.delegate.denyAll();
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasRole(String role) {
return hasAnyRole(role);
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasAnyRole(String... roles) {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.hasAnyRole(roles));
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasAllRoles(String... roles) {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.hasAllRoles(roles));
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasAuthority(String authority) {
return hasAnyAuthority(authority);
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasAnyAuthority(String... authorities) {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.hasAnyAuthority(authorities));
}
@Override
public AuthorizationManager<RequestAuthorizationContext> hasAllAuthorities(String... authorities) {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.hasAllAuthorities(authorities));
}
@Override
public AuthorizationManager<RequestAuthorizationContext> authenticated() {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.authenticated());
}
@Override
public AuthorizationManager<RequestAuthorizationContext> fullyAuthenticated() {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.fullyAuthenticated());
}
@Override
public AuthorizationManager<RequestAuthorizationContext> rememberMe() {
return allOf(new AuthorizationDecision(false), this.hasAuthorities, this.delegate.rememberMe());
}
@Override
public AuthorizationManager<RequestAuthorizationContext> anonymous() {
return this.delegate.anonymous();
}
}
// end::authorizationManagerFactory[]
// tag::authenticationEntryPoint[]
@Component
class ScopeRetrievingAuthenticationEntryPoint implements AuthenticationEntryPoint {

View File

@ -1,19 +1,16 @@
package org.springframework.security.kt.docs.servlet.authentication.customauthorizationmanagerfactory
import org.jspecify.annotations.NullMarked
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.security.access.expression.SecurityExpressionRoot
import org.springframework.security.authorization.*
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.invoke
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthorities
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.AuthorityUtils
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.PasswordEncodedUser
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.provisioning.InMemoryUserDetailsManager
import org.springframework.security.web.SecurityFilterChain
import org.springframework.security.web.authentication.ott.OneTimeTokenGenerationSuccessHandler
import org.springframework.security.web.authentication.ott.RedirectOneTimeTokenGenerationSuccessHandler
@ -43,50 +40,31 @@ internal class CustomAuthorizationManagerFactory {
// tag::authorizationManager[]
@Component
internal open class OptInToMfaAuthorizationManager : AuthorizationManager<Object> {
internal open class UserBasedOttAuthorizationManager : AuthorizationManager<Object> {
override fun authorize(
authentication: Supplier<out Authentication?>, context: Object): AuthorizationResult {
val principal = authentication.get().getPrincipal() as MyPrincipal?
if (principal!!.optedIn) {
val root = object : SecurityExpressionRoot<Object>(authentication, context) { }
return AuthorityAuthorizationDecision(
root.hasAuthority(GrantedAuthorities.FACTOR_OTT_AUTHORITY),
AuthorityUtils.createAuthorityList(GrantedAuthorities.FACTOR_OTT_AUTHORITY)
)
return if ("admin" == authentication.get().name) {
AuthorityAuthorizationManager.hasAuthority<Object>(GrantedAuthorities.FACTOR_OTT_AUTHORITY)
.authorize(authentication, context)
} else {
AuthorizationDecision(true)
}
return AuthorizationDecision(true)
}
}
// end::authorizationManager[]
// tag::authorizationManagerFactory[]
@Bean
fun authorizationManagerFactory(optIn: OptInToMfaAuthorizationManager?): AuthorizationManagerFactory<Object> {
fun authorizationManagerFactory(optIn: UserBasedOttAuthorizationManager?): AuthorizationManagerFactory<Object> {
val defaults = DefaultAuthorizationManagerFactory<Object>()
defaults.setAdditionalAuthorization(optIn)
return defaults
}
// end::authorizationManagerFactory[]
@NullMarked
class MyPrincipal(val user: String, val optedIn: Boolean) : UserDetails {
override fun getAuthorities(): MutableCollection<out GrantedAuthority> {
return AuthorityUtils.createAuthorityList("app")
}
override fun getPassword(): String? {
return null
}
override fun getUsername(): String {
return this.user
}
}
@Bean
fun users(): UserDetailsService {
return UserDetailsService { username: String? -> MyPrincipal(username!!, username == "optedin") }
return InMemoryUserDetailsManager(PasswordEncodedUser.user(), PasswordEncodedUser.admin())
}
@Bean

View File

@ -18,16 +18,18 @@ package org.springframework.security.kt.docs.servlet.authentication.customauthor
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.authentication.TestingAuthenticationToken
import org.springframework.security.config.test.SpringTestContext
import org.springframework.security.config.test.SpringTestContextExtension
import org.springframework.security.core.GrantedAuthorities
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers
import org.springframework.security.test.context.support.WithMockUser
import org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
import org.springframework.test.context.TestExecutionListeners
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@ -36,7 +38,8 @@ import org.springframework.web.bind.annotation.RestController
*
* @author Rob Winch
*/
@ExtendWith(SpringTestContextExtension::class)
@ExtendWith(SpringExtension::class, SpringTestContextExtension::class)
@TestExecutionListeners(WithSecurityContextTestExecutionListener::class)
class CustomAuthorizationManagerFactoryTests {
@JvmField
val spring: SpringTestContext = SpringTestContext(this)
@ -44,44 +47,40 @@ class CustomAuthorizationManagerFactoryTests {
@Autowired
var mockMvc: MockMvc? = null
@Autowired
var users: UserDetailsService? = null
@Test
@Throws(Exception::class)
fun getWhenOptedInThenRedirectsToOtt() {
@WithMockUser(username = "admin")
fun getWhenAdminThenRedirectsToOtt() {
this.spring.register(CustomAuthorizationManagerFactory::class.java, Http200Controller::class.java).autowire()
val user = this.users!!.loadUserByUsername("optedin")
// @formatter:off
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/").with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(MockMvcResultMatchers.status().is3xxRedirection())
.andExpect(MockMvcResultMatchers.redirectedUrl("http://localhost/login?factor=ott"))
// @formatter:on
this.mockMvc!!.perform(get("/"))
.andExpect(status().is3xxRedirection())
.andExpect(redirectedUrl("http://localhost/login?factor=ott"))
// @formatter:on
}
@Test
@Throws(Exception::class)
fun getWhenNotOptedInThenAllows() {
@WithMockUser
fun getWhenNotAdminThenAllows() {
this.spring.register(CustomAuthorizationManagerFactory::class.java, Http200Controller::class.java).autowire()
val user = this.users!!.loadUserByUsername("user")
// @formatter:off
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/").with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(SecurityMockMvcResultMatchers.authenticated().withUsername("user"))
// @formatter:on
this.mockMvc!!.perform(get("/"))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("user"))
// @formatter:on
}
@Test
@Throws(Exception::class)
fun getWhenOptedAndHasFactorThenAllows() {
@WithMockUser(username = "admin", authorities = [GrantedAuthorities.FACTOR_OTT_AUTHORITY])
fun getWhenAdminAndHasFactorThenAllows() {
this.spring.register(CustomAuthorizationManagerFactory::class.java, Http200Controller::class.java).autowire()
val user = this.users!!.loadUserByUsername("optedin")
val token = TestingAuthenticationToken(user, "", GrantedAuthorities.FACTOR_OTT_AUTHORITY)
// @formatter:off
this.mockMvc!!.perform(MockMvcRequestBuilders.get("/").with(SecurityMockMvcRequestPostProcessors.authentication(token)))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(SecurityMockMvcResultMatchers.authenticated().withUsername("optedin"))
// @formatter:on
this.mockMvc!!.perform(get("/"))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername("admin"))
// @formatter:on
}
@RestController

View File

@ -58,70 +58,13 @@ internal class MissingAuthorityConfiguration {
// tag::authorizationManagerFactoryBean[]
@Bean
fun authz(): AuthorizationManagerFactory<RequestAuthorizationContext> {
return FactorAuthorizationManagerFactory(hasAllAuthorities(GrantedAuthorities.FACTOR_X509_AUTHORITY, GrantedAuthorities.FACTOR_AUTHORIZATION_CODE_AUTHORITY))
fun authz(): AuthorizationManagerFactory<Object> {
return DefaultAuthorizationManagerFactory.builder<Object>()
.requireAdditionalAuthorities(GrantedAuthorities.FACTOR_X509_AUTHORITY, GrantedAuthorities.FACTOR_AUTHORIZATION_CODE_AUTHORITY)
.build()
}
// end::authorizationManagerFactoryBean[]
// tag::authorizationManagerFactory[]
internal inner class FactorAuthorizationManagerFactory(private val hasAuthorities: AuthorizationManager<RequestAuthorizationContext>) :
AuthorizationManagerFactory<RequestAuthorizationContext> {
private val delegate = DefaultAuthorizationManagerFactory<RequestAuthorizationContext>()
override fun permitAll(): AuthorizationManager<RequestAuthorizationContext> {
return this.delegate.permitAll()
}
override fun denyAll(): AuthorizationManager<RequestAuthorizationContext> {
return this.delegate.denyAll()
}
override fun hasRole(role: String): AuthorizationManager<RequestAuthorizationContext> {
return hasAnyRole(role)
}
override fun hasAnyRole(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.hasAnyRole(*roles))
}
override fun hasAllRoles(vararg roles: String): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.hasAllRoles(*roles))
}
override fun hasAuthority(authority: String): AuthorizationManager<RequestAuthorizationContext> {
return hasAnyAuthority(authority)
}
override fun hasAnyAuthority(vararg authorities: String): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.hasAnyAuthority(*authorities))
}
override fun hasAllAuthorities(vararg authorities: String): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.hasAllAuthorities(*authorities))
}
override fun authenticated(): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.authenticated())
}
override fun fullyAuthenticated(): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.fullyAuthenticated())
}
override fun rememberMe(): AuthorizationManager<RequestAuthorizationContext> {
return addFactors(this.delegate.rememberMe())
}
override fun anonymous(): AuthorizationManager<RequestAuthorizationContext> {
return this.delegate.anonymous()
}
private fun addFactors(delegate: AuthorizationManager<RequestAuthorizationContext>): AuthorizationManager<RequestAuthorizationContext> {
return allOf(AuthorizationDecision(false), this.hasAuthorities, delegate)
}
}
// end::authorizationManagerFactory[]
@Bean
fun clients(): ClientRegistrationRepository {
return InMemoryClientRegistrationRepository(TestClientRegistrations.clientRegistration().build())