KEYCLOAK-5499: Use authentication token type rather than token source detection to identify interactive and non-interactive authentications. (#4488)
- access_token URL parameter wasn't interpreted correctly as a non-interactive authentication.
This commit is contained in:
parent
cb43e3d763
commit
e2f5ac60cf
10 changed files with 149 additions and 79 deletions
|
@ -50,7 +50,7 @@ public class KeycloakAuthenticationProvider implements AuthenticationProvider {
|
||||||
for (String role : token.getAccount().getRoles()) {
|
for (String role : token.getAccount().getRoles()) {
|
||||||
grantedAuthorities.add(new KeycloakRole(role));
|
grantedAuthorities.add(new KeycloakRole(role));
|
||||||
}
|
}
|
||||||
return new KeycloakAuthenticationToken(token.getAccount(), mapAuthorities(grantedAuthorities));
|
return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), mapAuthorities(grantedAuthorities));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<? extends GrantedAuthority> mapAuthorities(
|
private Collection<? extends GrantedAuthority> mapAuthorities(
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class SpringSecurityRequestAuthenticator extends RequestAuthenticator {
|
||||||
|
|
||||||
logger.debug("Completing bearer authentication. Bearer roles: {} ",roles);
|
logger.debug("Completing bearer authentication. Bearer roles: {} ",roles);
|
||||||
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, false));
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
@ -36,6 +37,7 @@ import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticatio
|
||||||
import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
|
import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
|
||||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
import org.keycloak.adapters.springsecurity.token.AdapterTokenStoreFactory;
|
import org.keycloak.adapters.springsecurity.token.AdapterTokenStoreFactory;
|
||||||
|
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||||
import org.keycloak.adapters.springsecurity.token.SpringSecurityAdapterTokenStoreFactory;
|
import org.keycloak.adapters.springsecurity.token.SpringSecurityAdapterTokenStoreFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -61,19 +63,19 @@ import org.springframework.util.Assert;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
|
public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
|
||||||
|
|
||||||
public static final String DEFAULT_LOGIN_URL = "/sso/login";
|
public static final String DEFAULT_LOGIN_URL = "/sso/login";
|
||||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
public static final String SCHEME_BEARER = "bearer ";
|
|
||||||
public static final String SCHEME_BASIC = "basic ";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request matcher that matches requests to the {@link KeycloakAuthenticationEntryPoint#DEFAULT_LOGIN_URI default login URI}
|
* Request matcher that matches requests to the {@link KeycloakAuthenticationEntryPoint#DEFAULT_LOGIN_URI default login URI}
|
||||||
* and any request with a <code>Authorization</code> header.
|
* and any request with a <code>Authorization</code> header.
|
||||||
*/
|
*/
|
||||||
public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
|
public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
|
||||||
new OrRequestMatcher(new AntPathRequestMatcher(DEFAULT_LOGIN_URL), new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER));
|
new OrRequestMatcher(
|
||||||
|
new AntPathRequestMatcher(DEFAULT_LOGIN_URL),
|
||||||
|
new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER),
|
||||||
|
new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN)
|
||||||
|
);
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
|
||||||
|
|
||||||
|
@ -181,36 +183,10 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the request was made with a bearer token authorization header.
|
|
||||||
*
|
|
||||||
* @param request the current <code>HttpServletRequest</code>
|
|
||||||
*
|
|
||||||
* @return <code>true</code> if the <code>request</code> was made with a bearer token authorization header;
|
|
||||||
* <code>false</code> otherwise.
|
|
||||||
*/
|
|
||||||
protected boolean isBearerTokenRequest(HttpServletRequest request) {
|
|
||||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
|
||||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BEARER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the request was made with a Basic authentication authorization header.
|
|
||||||
*
|
|
||||||
* @param request the current <code>HttpServletRequest</code>
|
|
||||||
* @return <code>true</code> if the <code>request</code> was made with a Basic authentication authorization header;
|
|
||||||
* <code>false</code> otherwise.
|
|
||||||
*/
|
|
||||||
protected boolean isBasicAuthRequest(HttpServletRequest request) {
|
|
||||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
|
||||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BASIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||||
Authentication authResult) throws IOException, ServletException {
|
Authentication authResult) throws IOException, ServletException {
|
||||||
|
if (authResult instanceof KeycloakAuthenticationToken && ((KeycloakAuthenticationToken) authResult).isInteractive()) {
|
||||||
if (!(this.isBearerTokenRequest(request) || this.isBasicAuthRequest(request))) {
|
|
||||||
super.successfulAuthentication(request, response, chain, authResult);
|
super.successfulAuthentication(request, response, chain, authResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -231,7 +207,6 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
||||||
} finally {
|
} finally {
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.adapters.springsecurity.filter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring RequestMatcher that checks for the presence of a query parameter.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:glavoie@gmail.com">Gabriel Lavoie</a>
|
||||||
|
*/
|
||||||
|
public class QueryParamPresenceRequestMatcher implements RequestMatcher {
|
||||||
|
private String param;
|
||||||
|
|
||||||
|
public QueryParamPresenceRequestMatcher(String param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(HttpServletRequest httpServletRequest) {
|
||||||
|
return param != null && httpServletRequest.getParameter(param) != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,24 +38,27 @@ import java.util.Collection;
|
||||||
public class KeycloakAuthenticationToken extends AbstractAuthenticationToken implements Authentication {
|
public class KeycloakAuthenticationToken extends AbstractAuthenticationToken implements Authentication {
|
||||||
|
|
||||||
private Principal principal;
|
private Principal principal;
|
||||||
|
private boolean interactive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new, unauthenticated Keycloak security token for the given account.
|
* Creates a new, unauthenticated Keycloak security token for the given account.
|
||||||
*/
|
*/
|
||||||
public KeycloakAuthenticationToken(KeycloakAccount account) {
|
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive) {
|
||||||
super(null);
|
super(null);
|
||||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||||
this.principal = account.getPrincipal();
|
this.principal = account.getPrincipal();
|
||||||
this.setDetails(account);
|
this.setDetails(account);
|
||||||
|
this.interactive = interactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakAuthenticationToken(KeycloakAccount account, Collection<? extends GrantedAuthority> authorities) {
|
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||||
this.principal = account.getPrincipal();
|
this.principal = account.getPrincipal();
|
||||||
this.setDetails(account);
|
this.setDetails(account);
|
||||||
|
this.interactive = interactive;
|
||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,4 +75,8 @@ public class KeycloakAuthenticationToken extends AbstractAuthenticationToken imp
|
||||||
public OidcKeycloakAccount getAccount() {
|
public OidcKeycloakAccount getAccount() {
|
||||||
return (OidcKeycloakAccount) this.getDetails();
|
return (OidcKeycloakAccount) this.getDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInteractive() {
|
||||||
|
return interactive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ public class SpringSecurityTokenStore implements AdapterTokenStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Saving account info {}", account);
|
logger.debug("Saving account info {}", account);
|
||||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,6 +44,7 @@ import static org.mockito.Mockito.mock;
|
||||||
public class KeycloakAuthenticationProviderTest {
|
public class KeycloakAuthenticationProviderTest {
|
||||||
private KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
|
private KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
|
||||||
private KeycloakAuthenticationToken token;
|
private KeycloakAuthenticationToken token;
|
||||||
|
private KeycloakAuthenticationToken interactiveToken;
|
||||||
private Set<String> roles = Sets.newSet("user", "admin");
|
private Set<String> roles = Sets.newSet("user", "admin");
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -52,18 +53,18 @@ public class KeycloakAuthenticationProviderTest {
|
||||||
RefreshableKeycloakSecurityContext securityContext = mock(RefreshableKeycloakSecurityContext.class);
|
RefreshableKeycloakSecurityContext securityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
||||||
|
|
||||||
token = new KeycloakAuthenticationToken(account);
|
token = new KeycloakAuthenticationToken(account, false);
|
||||||
|
interactiveToken = new KeycloakAuthenticationToken(account, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticate() throws Exception {
|
public void testAuthenticate() throws Exception {
|
||||||
Authentication result = provider.authenticate(token);
|
assertAuthenticationResult(provider.authenticate(token));
|
||||||
assertNotNull(result);
|
}
|
||||||
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
|
||||||
assertTrue(result.isAuthenticated());
|
@Test
|
||||||
assertNotNull(result.getPrincipal());
|
public void testAuthenticateInteractive() throws Exception {
|
||||||
assertNotNull(result.getCredentials());
|
assertAuthenticationResult(provider.authenticate(interactiveToken));
|
||||||
assertNotNull(result.getDetails());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -83,4 +84,13 @@ public class KeycloakAuthenticationProviderTest {
|
||||||
assertEquals(Sets.newSet("ROLE_USER", "ROLE_ADMIN"),
|
assertEquals(Sets.newSet("ROLE_USER", "ROLE_ADMIN"),
|
||||||
AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertAuthenticationResult(Authentication result) {
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||||
|
assertTrue(result.isAuthenticated());
|
||||||
|
assertNotNull(result.getPrincipal());
|
||||||
|
assertNotNull(result.getCredentials());
|
||||||
|
assertNotNull(result.getDetails());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class SimpleHttpFacadeTest {
|
||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
RefreshableKeycloakSecurityContext keycloakSecurityContext = mock(RefreshableKeycloakSecurityContext.class);
|
RefreshableKeycloakSecurityContext keycloakSecurityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, keycloakSecurityContext);
|
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, keycloakSecurityContext);
|
||||||
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account);
|
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account, false);
|
||||||
springSecurityContext.setAuthentication(token);
|
springSecurityContext.setAuthentication(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@ import java.util.UUID;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.anyString;
|
|
||||||
import static org.mockito.Mockito.eq;
|
import static org.mockito.Mockito.eq;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
@ -124,34 +123,6 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||||
filter.afterPropertiesSet();
|
filter.afterPropertiesSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBearerTokenRequest() throws Exception {
|
|
||||||
assertFalse(filter.isBearerTokenRequest(request));
|
|
||||||
this.setBearerAuthHeader(request);
|
|
||||||
assertTrue(filter.isBearerTokenRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBearerTokenRequestCaseInsensitive() throws Exception {
|
|
||||||
assertFalse(filter.isBearerTokenRequest(request));
|
|
||||||
this.setAuthorizationHeader(request, "bearer");
|
|
||||||
assertTrue(filter.isBearerTokenRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBasicAuthRequest() throws Exception {
|
|
||||||
assertFalse(filter.isBasicAuthRequest(request));
|
|
||||||
this.setBasicAuthHeader(request);
|
|
||||||
assertTrue(filter.isBasicAuthRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBasicAuthRequestCaseInsensitive() throws Exception {
|
|
||||||
assertFalse(filter.isBasicAuthRequest(request));
|
|
||||||
this.setAuthorizationHeader(request, "basic");
|
|
||||||
assertTrue(filter.isBasicAuthRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAttemptAuthenticationExpectRedirect() throws Exception {
|
public void testAttemptAuthenticationExpectRedirect() throws Exception {
|
||||||
when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
|
when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
|
||||||
|
@ -180,7 +151,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationInteractive() throws Exception {
|
public void testSuccessfulAuthenticationInteractive() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, true, authorities);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
verify(successHandler).onAuthenticationSuccess(eq(request), eq(response), eq(authentication));
|
verify(successHandler).onAuthenticationSuccess(eq(request), eq(response), eq(authentication));
|
||||||
|
@ -189,7 +160,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationBearer() throws Exception {
|
public void testSuccessfulAuthenticationBearer() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||||
this.setBearerAuthHeader(request);
|
this.setBearerAuthHeader(request);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
|
@ -200,7 +171,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationBasicAuth() throws Exception {
|
public void testSuccessfulAuthenticationBasicAuth() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||||
this.setBasicAuthHeader(request);
|
this.setBasicAuthHeader(request);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.adapters.springsecurity.filter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
|
||||||
|
public class QueryParamPresenceRequestMatcherTest {
|
||||||
|
private static final String ROOT_CONTEXT_PATH = "";
|
||||||
|
|
||||||
|
private static final String VALID_PARAMETER = "access_token";
|
||||||
|
|
||||||
|
private QueryParamPresenceRequestMatcher matcher = new QueryParamPresenceRequestMatcher(VALID_PARAMETER);
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
request = new MockHttpServletRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotMatchWithoutQueryParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.EMPTY_MAP);
|
||||||
|
assertFalse(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMatchesWithValidParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap(VALID_PARAMETER, (Object) "123"));
|
||||||
|
assertTrue(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotMatchWithInvalidParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap("some_parameter", (Object) "123"));
|
||||||
|
assertFalse(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareRequest(HttpMethod method, String contextPath, String uri, Map<String, Object> params) {
|
||||||
|
request.setMethod(method.name());
|
||||||
|
request.setContextPath(contextPath);
|
||||||
|
request.setRequestURI(contextPath + "/" + uri);
|
||||||
|
request.setParameters(params);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue