1
0
mirror of synced 2026-08-04 09:17:02 +00:00

Multi-tenancy for Resource Server

Fixes: gh-5351
This commit is contained in:
Josh Cummings
2019-01-04 17:07:24 -07:00
parent e5249bd746
commit 7e8aadeb96
15 changed files with 763 additions and 28 deletions
@@ -68,7 +68,6 @@ public final class JwtAuthenticationProvider implements AuthenticationProvider {
public JwtAuthenticationProvider(JwtDecoder jwtDecoder) {
Assert.notNull(jwtDecoder, "jwtDecoder cannot be null");
this.jwtDecoder = jwtDecoder;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationManagerResolver;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
@@ -51,7 +52,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
* @see JwtAuthenticationProvider
*/
public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter {
private final AuthenticationManager authenticationManager;
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
private final AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource =
new WebAuthenticationDetailsSource();
@@ -60,13 +61,24 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
private AuthenticationEntryPoint authenticationEntryPoint = new BearerTokenAuthenticationEntryPoint();
/**
* Construct a {@code BearerTokenAuthenticationFilter} using the provided parameter(s)
* @param authenticationManagerResolver
*/
public BearerTokenAuthenticationFilter
(AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
Assert.notNull(authenticationManagerResolver, "authenticationManagerResolver cannot be null");
this.authenticationManagerResolver = authenticationManagerResolver;
}
/**
* Construct a {@code BearerTokenAuthenticationFilter} using the provided parameter(s)
* @param authenticationManager
*/
public BearerTokenAuthenticationFilter(AuthenticationManager authenticationManager) {
Assert.notNull(authenticationManager, "authenticationManager cannot be null");
this.authenticationManager = authenticationManager;
this.authenticationManagerResolver = request -> authenticationManager;
}
/**
@@ -104,7 +116,8 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
authenticationRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
try {
Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
AuthenticationManager authenticationManager = this.authenticationManagerResolver.resolve(request);
Authentication authenticationResult = authenticationManager.authenticate(authenticationRequest);
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authenticationResult);
@@ -139,5 +152,4 @@ public final class BearerTokenAuthenticationFilter extends OncePerRequestFilter
Assert.notNull(authenticationEntryPoint, "authenticationEntryPoint cannot be null");
this.authenticationEntryPoint = authenticationEntryPoint;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@@ -17,12 +17,12 @@ package org.springframework.security.oauth2.server.resource.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@@ -31,6 +31,7 @@ import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationManagerResolver;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import org.springframework.security.oauth2.server.resource.BearerTokenError;
@@ -57,6 +58,9 @@ public class BearerTokenAuthenticationFilterTests {
@Mock
AuthenticationManager authenticationManager;
@Mock
AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
@Mock
BearerTokenResolver bearerTokenResolver;
@@ -66,9 +70,6 @@ public class BearerTokenAuthenticationFilterTests {
MockFilterChain filterChain;
@InjectMocks
BearerTokenAuthenticationFilter filter;
@Before
public void httpMocks() {
this.request = new MockHttpServletRequest();
@@ -76,17 +77,31 @@ public class BearerTokenAuthenticationFilterTests {
this.filterChain = new MockFilterChain();
}
@Before
public void setterMocks() {
this.filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
this.filter.setBearerTokenResolver(this.bearerTokenResolver);
}
@Test
public void doFilterWhenBearerTokenPresentThenAuthenticates() throws ServletException, IOException {
when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token");
this.filter.doFilter(this.request, this.response, this.filterChain);
BearerTokenAuthenticationFilter filter =
addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager));
filter.doFilter(this.request, this.response, this.filterChain);
ArgumentCaptor<BearerTokenAuthenticationToken> captor =
ArgumentCaptor.forClass(BearerTokenAuthenticationToken.class);
verify(this.authenticationManager).authenticate(captor.capture());
assertThat(captor.getValue().getPrincipal()).isEqualTo("token");
}
@Test
public void doFilterWhenUsingAuthenticationManagerResolverThenAuthenticates() throws Exception {
BearerTokenAuthenticationFilter filter =
addMocks(new BearerTokenAuthenticationFilter(this.authenticationManagerResolver));
when(this.bearerTokenResolver.resolve(this.request)).thenReturn("token");
when(this.authenticationManagerResolver.resolve(any())).thenReturn(this.authenticationManager);
filter.doFilter(this.request, this.response, this.filterChain);
ArgumentCaptor<BearerTokenAuthenticationToken> captor =
ArgumentCaptor.forClass(BearerTokenAuthenticationToken.class);
@@ -137,36 +152,56 @@ public class BearerTokenAuthenticationFilterTests {
when(this.authenticationManager.authenticate(any(BearerTokenAuthenticationToken.class)))
.thenThrow(exception);
this.filter.doFilter(this.request, this.response, this.filterChain);
BearerTokenAuthenticationFilter filter =
addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager));
filter.doFilter(this.request, this.response, this.filterChain);
verify(this.authenticationEntryPoint).commence(this.request, this.response, exception);
}
@Test
public void setAuthenticationEntryPointWhenNullThenThrowsException() {
assertThatCode(() -> this.filter.setAuthenticationEntryPoint(null))
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager);
assertThatCode(() -> filter.setAuthenticationEntryPoint(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("authenticationEntryPoint cannot be null");
}
@Test
public void setBearerTokenResolverWhenNullThenThrowsException() {
assertThatCode(() -> this.filter.setBearerTokenResolver(null))
BearerTokenAuthenticationFilter filter = new BearerTokenAuthenticationFilter(this.authenticationManager);
assertThatCode(() -> filter.setBearerTokenResolver(null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("bearerTokenResolver cannot be null");
}
@Test
public void constructorWhenNullAuthenticationManagerThenThrowsException() {
assertThatCode(() -> new BearerTokenAuthenticationFilter(null))
assertThatCode(() -> new BearerTokenAuthenticationFilter((AuthenticationManager) null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("authenticationManager cannot be null");
}
@Test
public void constructorWhenNullAuthenticationManagerResolverThenThrowsException() {
assertThatCode(() ->
new BearerTokenAuthenticationFilter((AuthenticationManagerResolver<HttpServletRequest>) null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("authenticationManagerResolver cannot be null");
}
private BearerTokenAuthenticationFilter addMocks(BearerTokenAuthenticationFilter filter) {
filter.setAuthenticationEntryPoint(this.authenticationEntryPoint);
filter.setBearerTokenResolver(this.bearerTokenResolver);
return filter;
}
private void dontAuthenticate()
throws ServletException, IOException {
this.filter.doFilter(this.request, this.response, this.filterChain);
BearerTokenAuthenticationFilter filter =
addMocks(new BearerTokenAuthenticationFilter(this.authenticationManager));
filter.doFilter(this.request, this.response, this.filterChain);
verifyNoMoreInteractions(this.authenticationManager);
}