+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.authentication;
-
-import java.util.Optional;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.sonar.api.server.ServerSide;
-import org.sonar.server.user.UserSession;
-
-/**
- * Authentication that can create {@link org.sonar.server.user.UserSession}
- * that are not associated to a user.
- * That is convenient for authenticating bots that need special permissions.
- *
- * This is not an extension point, plugins can not provide their own
- * implementations.
- */
-@ServerSide
-public interface CustomAuthentication {
-
- Optional<UserSession> authenticate(HttpServletRequest request, HttpServletResponse response);
-
-}
*/
package org.sonar.server.authentication;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
import java.util.function.Function;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
private final HttpHeadersAuthentication httpHeadersAuthentication;
private final GithubWebhookAuthentication githubWebhookAuthentication;
private final UserSessionFactory userSessionFactory;
- private final List<CustomAuthentication> customAuthentications;
@Autowired(required = false)
public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, UserTokenAuthentication userTokenAuthentication,
HttpHeadersAuthentication httpHeadersAuthentication,
- GithubWebhookAuthentication githubWebhookAuthentication, UserSessionFactory userSessionFactory, CustomAuthentication[] customAuthentications) {
+ GithubWebhookAuthentication githubWebhookAuthentication, UserSessionFactory userSessionFactory) {
this.jwtHttpHandler = jwtHttpHandler;
this.basicAuthentication = basicAuthentication;
this.userTokenAuthentication = userTokenAuthentication;
this.httpHeadersAuthentication = httpHeadersAuthentication;
this.githubWebhookAuthentication = githubWebhookAuthentication;
this.userSessionFactory = userSessionFactory;
- this.customAuthentications = Arrays.asList(customAuthentications);
}
@Autowired(required = false)
public RequestAuthenticatorImpl(JwtHttpHandler jwtHttpHandler, BasicAuthentication basicAuthentication, UserTokenAuthentication userTokenAuthentication,
HttpHeadersAuthentication httpHeadersAuthentication,
UserSessionFactory userSessionFactory, GithubWebhookAuthentication githubWebhookAuthentication) {
- this(jwtHttpHandler, basicAuthentication, userTokenAuthentication, httpHeadersAuthentication, githubWebhookAuthentication, userSessionFactory, new CustomAuthentication[0]);
+ this(jwtHttpHandler, basicAuthentication, userTokenAuthentication, httpHeadersAuthentication, githubWebhookAuthentication, userSessionFactory);
}
@Override
public UserSession authenticate(HttpServletRequest request, HttpServletResponse response) {
- for (CustomAuthentication customAuthentication : customAuthentications) {
- Optional<UserSession> session = customAuthentication.authenticate(request, response);
- if (session.isPresent()) {
- return session.get();
- }
- }
-
UserAuthResult userAuthResult = loadUser(request, response);
if (nonNull(userAuthResult.getUserDto())) {
if (TOKEN.equals(userAuthResult.getAuthType())) {
// SSO authentication should come first in order to update JWT if user from header is not the same is user from JWT
return httpHeadersAuthentication.authenticate(request, response).map(createUserAuthResult.apply(SSO))
.orElseGet(() -> jwtHttpHandler.validateToken(request, response).map(createUserAuthResult.apply(JWT))
- .orElseGet(() -> userTokenAuthentication.authenticate(request)
- .or(() -> githubWebhookAuthentication.authenticate(request))
- .or(() -> basicAuthentication.authenticate(request).map(createUserAuthResult.apply(BASIC)))
- .orElseGet(UserAuthResult::new)));
+ .orElseGet(() -> userTokenAuthentication.authenticate(request)
+ .or(() -> githubWebhookAuthentication.authenticate(request))
+ .or(() -> basicAuthentication.authenticate(request).map(createUserAuthResult.apply(BASIC)))
+ .orElseGet(UserAuthResult::new)));
}
}
import org.junit.Test;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTokenDto;
-import org.sonar.server.authentication.event.AuthenticationEvent;
-import org.sonar.server.authentication.event.AuthenticationException;
import org.sonar.server.tester.AnonymousMockUserSession;
import org.sonar.server.tester.MockUserSession;
import org.sonar.server.user.GithubWebhookUserSession;
private final GithubWebhookAuthentication githubWebhookAuthentication = mock(GithubWebhookAuthentication.class);
private final HttpHeadersAuthentication httpHeadersAuthentication = mock(HttpHeadersAuthentication.class);
private final UserSessionFactory sessionFactory = mock(UserSessionFactory.class);
- private final CustomAuthentication customAuthentication1 = mock(CustomAuthentication.class);
- private final CustomAuthentication customAuthentication2 = mock(CustomAuthentication.class);
private final RequestAuthenticator underTest = new RequestAuthenticatorImpl(jwtHttpHandler, basicAuthentication, userTokenAuthentication, httpHeadersAuthentication,
- githubWebhookAuthentication, sessionFactory,
- new CustomAuthentication[]{customAuthentication1, customAuthentication2});
+ githubWebhookAuthentication, sessionFactory);
private final GithubWebhookUserSession githubWebhookMockUserSession = mock(GithubWebhookUserSession.class);
verify(response, never()).setStatus(anyInt());
}
- @Test
- public void delegate_to_CustomAuthentication() {
- when(customAuthentication1.authenticate(request, response)).thenReturn(Optional.of(new MockUserSession("foo")));
-
- UserSession session = underTest.authenticate(request, response);
-
- assertThat(session.getLogin()).isEqualTo("foo");
- }
-
- @Test
- public void CustomAuthentication_has_priority_over_core_authentications() {
- // use-case: both custom and core authentications check the HTTP header "Authorization".
- // The custom authentication should be able to test the header because that the core authentication
- // throws an exception.
- when(customAuthentication1.authenticate(request, response)).thenReturn(Optional.of(new MockUserSession("foo")));
- when(basicAuthentication.authenticate(request)).thenThrow(AuthenticationException.newBuilder()
- .setSource(AuthenticationEvent.Source.sso())
- .setMessage("message")
- .build());
-
- UserSession session = underTest.authenticate(request, response);
-
- assertThat(session.getLogin()).isEqualTo("foo");
- }
-
private static UserTokenDto mockUserTokenDto(UserDto userDto) {
UserTokenDto userTokenDto = new UserTokenDto();
userTokenDto.setType(USER_TOKEN.name());