Complete check on message displayed in ui when functional authentication errors are generated
Add ITs when errors are generated during callback of OAuth2 authentication plugins
import org.sonar.api.config.Settings;
import org.sonar.api.server.authentication.Display;
import org.sonar.api.server.authentication.OAuth2IdentityProvider;
+import org.sonar.api.server.authentication.UnauthorizedException;
import org.sonar.api.server.authentication.UserIdentity;
public class FakeOAuth2IdProvider implements OAuth2IdentityProvider {
private static final String ENABLED = "sonar.auth.fake-oauth2-id-provider.enabled";
+ private static final String ALLOWS_USERS_TO_SIGN_UP = "sonar.auth.fake-oauth2-id-provider.allowsUsersToSignUp";
private static final String URL = "sonar.auth.fake-oauth2-id-provider.url";
private static final String USER_INFO = "sonar.auth.fake-oauth2-id-provider.user";
+ private static final String THROW_UNAUTHORIZED_EXCEPTION = "sonar.auth.fake-oauth2-id-provider.throwUnauthorizedMessage";
+
private final Settings settings;
public FakeOAuth2IdProvider(Settings settings) {
this.settings = settings;
}
-
@Override
public void init(InitContext context) {
String url = settings.getString(URL);
if (userInfoProperty == null) {
throw new IllegalStateException(String.format("The property %s is required", USER_INFO));
}
+ boolean throwUnauthorizedException = settings.getBoolean(THROW_UNAUTHORIZED_EXCEPTION);
+ if (throwUnauthorizedException) {
+ throw new UnauthorizedException("A functional error has happened");
+ }
+
String[] userInfos = userInfoProperty.split(",");
context.authenticate(UserIdentity.builder()
.setLogin(userInfos[0])
@Override
public boolean allowsUsersToSignUp() {
+ if (settings.hasKey(ALLOWS_USERS_TO_SIGN_UP)) {
+ return settings.getBoolean(ALLOWS_USERS_TO_SIGN_UP);
+ }
+ // If property is not defined, default behaviour is not always allow users to sign up
return true;
+
}
}
/**
* TODO : Add missing ITs
- * - creating new user using email already used
* - display multiple identity provider plugins (probably in another class)
*/
public class BaseIdentityProviderTest {
}
@Test
- public void authenticate_user() throws Exception {
+ public void authenticate_user_through_ui() throws Exception {
enablePlugin();
setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
userRule.verifyUserDoesNotExist(USER_LOGIN);
}
+ @Test
+ public void fail_when_email_already_exists() throws Exception {
+ enablePlugin();
+ setUserCreatedByAuthPlugin(USER_LOGIN, USER_PROVIDER_ID, USER_NAME, USER_EMAIL);
+ userRule.createUser("another", "Another", USER_EMAIL, "another");
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("fail when email already exists",
+ "/user/BaseIdentityProviderTest/fail_when_email_already_exists.html").build()).runOn(ORCHESTRATOR);
+
+ File logFile = ORCHESTRATOR.getServer().getWebLogs();
+ assertThat(FileUtils.readFileToString(logFile))
+ .doesNotContain("You can't sign up because email 'john@email.com' is already used by an existing user. This means that you probably already registered with another account");
+ }
+
@Test
public void fail_to_authenticate_when_not_allowed_to_sign_up() throws Exception {
enablePlugin();
setServerProperty(ORCHESTRATOR, "sonar.auth.fake-base-id-provider.throwUnauthorizedMessage", "true");
new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("fail_to_authenticate_when_not_allowed_to_sign_up",
- "/user/BaseIdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html").build()).runOn(ORCHESTRATOR);
+ "/user/BaseIdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html").build()).runOn(ORCHESTRATOR);
File logFile = ORCHESTRATOR.getServer().getWebLogs();
assertThat(FileUtils.readFileToString(logFile)).doesNotContain("A functional error has happened");
package it.user;
import com.sonar.orchestrator.Orchestrator;
+import com.sonar.orchestrator.selenium.Selenese;
import it.Category4Suite;
+import java.io.File;
import java.net.HttpURLConnection;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
+import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.WsClient;
import org.sonarqube.ws.client.WsResponse;
+import util.selenium.SeleneseTest;
import util.user.UserRule;
import static org.assertj.core.api.Assertions.assertThat;
import static util.ItUtils.newAdminWsClient;
+import static util.ItUtils.resetSettings;
import static util.ItUtils.setServerProperty;
/**
fakeServerAuthProvider = new MockWebServer();
fakeServerAuthProvider.start();
fakeServerAuthProviderUrl = fakeServerAuthProvider.url("").url().toString();
+ userRule.resetUsers();
+ resetSettings(ORCHESTRATOR, null, "sonar.auth.fake-oauth2-id-provider.enabled",
+ "sonar.auth.fake-oauth2-id-provider.url",
+ "sonar.auth.fake-oauth2-id-provider.user",
+ "sonar.auth.fake-oauth2-id-provider.throwUnauthorizedMessage",
+ "sonar.auth.fake-oauth2-id-provider.allowsUsersToSignUp");
}
@After
public void tearDown() throws Exception {
fakeServerAuthProvider.shutdown();
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.enabled", null);
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.url", null);
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.user", null);
}
@Test
public void create_new_user_when_authenticate() throws Exception {
simulateRedirectionToCallback();
-
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.enabled", "true");
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.url", fakeServerAuthProviderUrl);
- setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.user", USER_LOGIN + "," + USER_PROVIDER_ID + "," + USER_NAME + "," + USER_EMAIL);
+ enablePlugin();
authenticateWithFakeAuthProvider();
userRule.verifyUserExists(USER_LOGIN, USER_NAME, USER_EMAIL);
}
+ @Test
+ public void authenticate_user_through_ui() throws Exception {
+ simulateRedirectionToCallback();
+ enablePlugin();
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("authenticate_user",
+ "/user/OAuth2IdentityProviderTest/authenticate_user.html").build()).runOn(ORCHESTRATOR);
+
+ userRule.verifyUserExists(USER_LOGIN, USER_NAME, USER_EMAIL);
+ }
+
+ @Test
+ public void display_unauthorized_page_when_authentication_failed_in_callback() throws Exception {
+ simulateRedirectionToCallback();
+ enablePlugin();
+
+ // As this property is null, the plugin will throw an exception
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.user", null);
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("display_unauthorized_page_when_authentication_failed",
+ "/user/OAuth2IdentityProviderTest/display_unauthorized_page_when_authentication_failed.html").build()).runOn(ORCHESTRATOR);
+
+ userRule.verifyUserDoesNotExist(USER_LOGIN);
+ }
+
+ @Test
+ public void fail_to_authenticate_when_not_allowed_to_sign_up() throws Exception {
+ simulateRedirectionToCallback();
+ enablePlugin();
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.allowsUsersToSignUp", "false");
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("fail_to_authenticate_when_not_allowed_to_sign_up",
+ "/user/OAuth2IdentityProviderTest/fail_to_authenticate_when_not_allowed_to_sign_up.html").build()).runOn(ORCHESTRATOR);
+
+ userRule.verifyUserDoesNotExist(USER_LOGIN);
+ }
+
+ @Test
+ public void display_message_in_ui_but_not_in_log_when_unauthorized_exception_in_callback() throws Exception {
+ simulateRedirectionToCallback();
+ enablePlugin();
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.throwUnauthorizedMessage", "true");
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("display_message_in_ui_but_not_in_log_when_unauthorized_exception",
+ "/user/OAuth2IdentityProviderTest/display_message_in_ui_but_not_in_log_when_unauthorized_exception.html").build()).runOn(ORCHESTRATOR);
+
+ File logFile = ORCHESTRATOR.getServer().getWebLogs();
+ assertThat(FileUtils.readFileToString(logFile)).doesNotContain("A functional error has happened");
+ assertThat(FileUtils.readFileToString(logFile)).doesNotContain("UnauthorizedException");
+
+ userRule.verifyUserDoesNotExist(USER_LOGIN);
+ }
+
+ @Test
+ public void fail_when_email_already_exists() throws Exception {
+ simulateRedirectionToCallback();
+ enablePlugin();
+ userRule.createUser("another", "Another", USER_EMAIL, "another");
+
+ new SeleneseTest(Selenese.builder().setHtmlTestsInClasspath("fail_when_email_already_exists",
+ "/user/OAuth2IdentityProviderTest/fail_when_email_already_exists.html").build()).runOn(ORCHESTRATOR);
+
+ File logFile = ORCHESTRATOR.getServer().getWebLogs();
+ assertThat(FileUtils.readFileToString(logFile))
+ .doesNotContain("You can't sign up because email 'john@email.com' is already used by an existing user. This means that you probably already registered with another account");
+ }
+
private void authenticateWithFakeAuthProvider() {
WsResponse response = adminWsClient.wsConnector().call(
new GetRequest(("/sessions/init/" + FAKE_PROVIDER_KEY)));
.setBody("Redirect to SonarQube"));
}
+ private void enablePlugin() {
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.enabled", "true");
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.url", fakeServerAuthProviderUrl);
+ setServerProperty(ORCHESTRATOR, "sonar.auth.fake-oauth2-id-provider.user", USER_LOGIN + "," + USER_PROVIDER_ID + "," + USER_NAME + "," + USER_EMAIL);
+ }
+
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head profile="http://selenium-ide.openqa.org/profiles/test-case">
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <title>fail_to_authenticate_when_not_allowed_to_sign_up</title>
-</head>
-<body>
-<table cellpadding="1" cellspacing="1" border="1">
- <thead>
- <tr>
- <td rowspan="1" colspan="3">french</td>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>open</td>
- <td>/sessions/init/fake-base-id-provider</td>
- <td></td>
- </tr>
- <tr>
- <td>waitForText</td>
- <td>bd</td>
- <td>*You're not authorized to access this page. Please contact the administrator.*Reason : A functional error has happened*</td>
- </tr>
- </tbody>
-</table>
-</body>
-</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>fail_to_authenticate_when_not_allowed_to_sign_up</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake base identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ </tr>
+ <tr>
+ <td>assertText</td>
+ <td>bd</td>
+ <td>*Reason : A functional error has happened*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
<tbody>
<tr>
<td>open</td>
- <td>/sessions/init/fake-base-id-provider</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake base identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
<td></td>
</tr>
<tr>
<tbody>
<tr>
<td>open</td>
- <td>/sessions/init/fake-base-id-provider</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake base identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
<td></td>
</tr>
<tr>
<td>waitForText</td>
<td>bd</td>
- <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-base-id-provider' users are not allowed to sign up*</td>
</tr>
</tbody>
</table>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>fail_when_email_already_exists</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake base identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ </tr>
+ <tr>
+ <td>assertText</td>
+ <td>bd</td>
+ <td>*You can't sign up because email 'john@email.com' is already used by an existing user. This means that you probably already registered with another account*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake oauth2 identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>id=global-navigation</td>
+ <td>*John*</td>
+ </tr>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>fail_to_authenticate_when_not_allowed_to_sign_up</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake oauth2 identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ </tr>
+ <tr>
+ <td>assertText</td>
+ <td>bd</td>
+ <td>*Reason : A functional error has happened*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>display_unauthorized_page_when_authentication_failed</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake oauth2 identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>fail_to_authenticate_when_not_allowed_to_sign_up</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake oauth2 identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*Reason : 'fake-oauth2-id-provider' users are not allowed to sign up*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <title>fail_when_email_already_exists</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+ <thead>
+ <tr>
+ <td rowspan="1" colspan="3">french</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>open</td>
+ <td>/sessions/new</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>content</td>
+ <td>*Log in with Fake oauth2 identity provider*</td>
+ </tr>
+ <tr>
+ <td>click</td>
+ <td>css=.oauth-providers a</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>waitForText</td>
+ <td>bd</td>
+ <td>*You're not authorized to access this page. Please contact the administrator.*</td>
+ </tr>
+ <tr>
+ <td>assertText</td>
+ <td>bd</td>
+ <td>*You can't sign up because email 'john@email.com' is already used by an existing user. This means that you probably already registered with another account*</td>
+ </tr>
+ </tbody>
+</table>
+</body>
+</html>