/* * Copyright 2017 ThoughtWorks, Inc. * * 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 com.thoughtworks.go.server.security; import com.thoughtworks.go.config.SecurityAuthConfig; import com.thoughtworks.go.config.SecurityConfig; import com.thoughtworks.go.plugin.access.authorization.AuthorizationExtension; import com.thoughtworks.go.server.security.tokens.PreAuthenticatedAuthenticationToken; import com.thoughtworks.go.server.service.GoConfigService; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationManager; import org.springframework.security.context.SecurityContextHolder; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; public class PreAuthenticatedRequestsProcessingFilterTest { private HttpServletRequest request; private HttpServletResponse response; private FilterChain filterChain; private AuthenticationManager authenticationManager; private PreAuthenticatedRequestsProcessingFilter filter; private AuthorizationExtension authorizationExtension; private GoConfigService configService; private SecurityConfig securityConfig; @Before public void setUp() throws Exception { request = mock(HttpServletRequest.class); response = mock(HttpServletResponse.class); filterChain = mock(FilterChain.class); authenticationManager = mock(AuthenticationManager.class); authorizationExtension = mock(AuthorizationExtension.class); configService = mock(GoConfigService.class); filter = new PreAuthenticatedRequestsProcessingFilter(authorizationExtension, configService); securityConfig = new SecurityConfig(); filter.setAuthenticationManager(authenticationManager); filter.setFilterProcessesUrl("^/go/plugin/([\\w\\-.]+)/authenticate$"); stub(configService.security()).toReturn(securityConfig); stub(request.getHeaderNames()).toReturn(Collections.emptyEnumeration()); } @After public void tearDown() throws Exception { SecurityContextHolder.getContext().setAuthentication(null); } @Test public void shouldAttemptAuthenticationOnlyForPluginAuthRequests() throws IOException, ServletException { when(request.getRequestURI()).thenReturn("/go/plugin/github.oauth/authenticate"); filter.attemptAuthentication(request); verify(authenticationManager).authenticate(any(PreAuthenticatedAuthenticationToken.class)); } @Test public void shouldNotAttemptAuthenticationForAuthenticationPluginRequests() throws IOException, ServletException { when(request.getRequestURI()).thenReturn("/go/plugin/interact/github.oauth/authenticate"); filter.doFilter(request, response, filterChain); verifyZeroInteractions(authenticationManager); verifyZeroInteractions(authorizationExtension); } @Test public void shouldIgnoreAuthenticationIfUserIsAlreadyAuthenticated() throws IOException, ServletException { when(request.getRequestURI()).thenReturn("/go/plugin/github.oauth/authenticate"); SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(null, null, null)); filter.setAuthenticationManager(authenticationManager); filter.doFilter(request, response, filterChain); verifyZeroInteractions(authenticationManager); verify(filterChain).doFilter(request, response); } @Test public void shouldIgnoreNonPluginAuthenticationRequests() throws IOException, ServletException { when(request.getRequestURI()).thenReturn("/go/api/agents"); filter.setAuthenticationManager(authenticationManager); filter.doFilter(request, response, filterChain); verifyZeroInteractions(authenticationManager); verify(filterChain).doFilter(request, response); } @Test public void shouldFetchAuthorizationServerAccessTokenFromThePlugin() { HashMap<String, String[]> params = new HashMap<>(); params.put("code", new String[]{"some_auth_code"}); SecurityAuthConfig githubAuthConfig = new SecurityAuthConfig("github", "github.oauth"); securityConfig.securityAuthConfigs().add(githubAuthConfig); when(request.getRequestURI()).thenReturn("/go/plugin/github.oauth/authenticate"); when(request.getParameterMap()).thenReturn(params); when(request.getHeaderNames()).thenReturn(Collections.enumeration(Arrays.asList("Authorization"))); when(request.getHeader("Authorization")).thenReturn("qwe123"); when(authorizationExtension.fetchAccessToken("github.oauth", Collections.singletonMap("Authorization", "qwe123"), Collections.singletonMap("code", "some_auth_code"), Collections.singletonList(githubAuthConfig))). thenReturn(Collections.singletonMap("access_token", "token")); Map<String, String> credentials = filter.fetchAuthorizationServerAccessToken(request); assertThat(credentials, hasEntry("access_token", "token")); } @Test public void shouldAuthenticateUsersWithCredentials() throws IOException, ServletException { PreAuthenticatedAuthenticationToken token = mock(PreAuthenticatedAuthenticationToken.class); HashMap<String, String[]> params = new HashMap<>(); params.put("code", new String[]{"some_auth_code"}); SecurityAuthConfig githubAuthConfig = new SecurityAuthConfig("github", "github.oauth"); securityConfig.securityAuthConfigs().add(githubAuthConfig); when(request.getRequestURI()).thenReturn("/go/plugin/github.oauth/authenticate"); when(request.getHeaderNames()).thenReturn(Collections.enumeration(Arrays.asList("Authorization"))); when(request.getHeader("Authorization")).thenReturn("qwe123"); when(request.getParameterMap()).thenReturn(params); when(authorizationExtension.fetchAccessToken("github.oauth", Collections.singletonMap("Authorization", "qwe123"), Collections.singletonMap("code", "some_auth_code"), Collections.singletonList(githubAuthConfig))). thenReturn(Collections.singletonMap("access_token", "token")); when(authenticationManager.authenticate(any(PreAuthenticatedAuthenticationToken.class))).thenReturn(token); filter.setDefaultTargetUrl("/"); filter.doFilter(request, response, filterChain); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); assertThat(authentication, is(token)); } }