Merge branch 'stable-2.14' into stable-2.15 * stable-2.14: Upgrade bazlets to latest stable-2.14 Change-Id: Ic6b7e5de740767b34586c6561de9e06ba24ed81d
diff --git a/.gitignore b/.gitignore index 7031893..b9fe628 100644 --- a/.gitignore +++ b/.gitignore
@@ -7,3 +7,4 @@ /bazel-testlogs /eclipse-out /.idea +*.swp
diff --git a/README.md b/README.md index e23b5be..7a156b2 100644 --- a/README.md +++ b/README.md
@@ -7,6 +7,7 @@ With this plugin Gerrit can use OAuth2 protocol for authentication. Supported OAuth providers: +* [AirVantage](https://doc.airvantage.net/av/reference/cloud/API/#API-GeneralInformation-Authentication) * [Bitbucket](https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html) * [CAS](https://www.apereo.org/projects/cas) * [CoreOS Dex](https://github.com/coreos/dex)
diff --git a/WORKSPACE b/WORKSPACE index 003e571..e596bfb 100644 --- a/WORKSPACE +++ b/WORKSPACE
@@ -3,7 +3,7 @@ load("//:bazlets.bzl", "load_bazlets") load_bazlets( - commit = "b07aa8462f2618a83f3b52d6150faa831b24d3e3", + commit = "ec949feac1b9dae6cc2c8c25d254f34924c54296", #local_path = "/home/<user>/projects/bazlets", )
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageApi.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageApi.java new file mode 100644 index 0000000..02f4bd5 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageApi.java
@@ -0,0 +1,56 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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.googlesource.gerrit.plugins.oauth; + +import static java.lang.String.format; + +import org.scribe.builder.api.DefaultApi20; +import org.scribe.extractors.AccessTokenExtractor; +import org.scribe.extractors.JsonTokenExtractor; +import org.scribe.model.OAuthConfig; +import org.scribe.model.Verb; +import org.scribe.oauth.OAuthService; + +public class AirVantageApi extends DefaultApi20 { + + private static final String AUTHORIZE_URL = + "https://eu.airvantage.net/api/oauth/authorize?client_id=%s&response_type=code"; + private static final String ACCESS_TOKEN_ENDPOINT = "https://eu.airvantage.net/api/oauth/token"; + + @Override + public String getAuthorizationUrl(OAuthConfig config) { + return format(AUTHORIZE_URL, config.getApiKey()); + } + + @Override + public String getAccessTokenEndpoint() { + return ACCESS_TOKEN_ENDPOINT; + } + + @Override + public Verb getAccessTokenVerb() { + return Verb.POST; + } + + @Override + public AccessTokenExtractor getAccessTokenExtractor() { + return new JsonTokenExtractor(); + } + + @Override + public OAuthService createService(OAuthConfig config) { + return new OAuth20ServiceImpl(this, config); + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageOAuthService.java new file mode 100644 index 0000000..25edf2e --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/AirVantageOAuthService.java
@@ -0,0 +1,127 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// 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.googlesource.gerrit.plugins.oauth; + +import static com.google.gerrit.server.OutputFormat.JSON; +import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.slf4j.LoggerFactory.getLogger; + +import com.google.common.base.CharMatcher; +import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider; +import com.google.gerrit.extensions.auth.oauth.OAuthToken; +import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo; +import com.google.gerrit.extensions.auth.oauth.OAuthVerifier; +import com.google.gerrit.server.config.CanonicalWebUrl; +import com.google.gerrit.server.config.PluginConfig; +import com.google.gerrit.server.config.PluginConfigFactory; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import java.io.IOException; +import org.scribe.builder.ServiceBuilder; +import org.scribe.model.OAuthRequest; +import org.scribe.model.Response; +import org.scribe.model.Token; +import org.scribe.model.Verb; +import org.scribe.model.Verifier; +import org.scribe.oauth.OAuthService; +import org.slf4j.Logger; + +@Singleton +public class AirVantageOAuthService implements OAuthServiceProvider { + private static final Logger log = getLogger(AirVantageOAuthService.class); + static final String CONFIG_SUFFIX = "-airvantage-oauth"; + private static final String AV_PROVIDER_PREFIX = "airvantage-oauth:"; + private static final String PROTECTED_RESOURCE_URL = + "https://eu.airvantage.net/api/v1/users/current"; + private final OAuthService service; + + @Inject + AirVantageOAuthService( + PluginConfigFactory cfgFactory, + @PluginName String pluginName, + @CanonicalWebUrl Provider<String> urlProvider) { + PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName + CONFIG_SUFFIX); + String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; + + service = + new ServiceBuilder() + .provider(AirVantageApi.class) + .apiKey(cfg.getString(InitOAuth.CLIENT_ID)) + .apiSecret(cfg.getString(InitOAuth.CLIENT_SECRET)) + .callback(canonicalWebUrl + "oauth") + .build(); + } + + @Override + public OAuthUserInfo getUserInfo(OAuthToken token) throws IOException { + OAuthRequest request = new OAuthRequest(Verb.GET, PROTECTED_RESOURCE_URL); + Token t = new Token(token.getToken(), token.getSecret(), token.getRaw()); + service.signRequest(t, request); + Response response = request.send(); + if (response.getCode() != SC_OK) { + throw new IOException( + String.format( + "Status %s (%s) for request %s", + response.getCode(), response.getBody(), request.getUrl())); + } + JsonElement userJson = JSON.newGson().fromJson(response.getBody(), JsonElement.class); + if (log.isDebugEnabled()) { + log.debug("User info response: {}", response.getBody()); + } + if (userJson.isJsonObject()) { + JsonObject jsonObject = userJson.getAsJsonObject(); + JsonElement id = jsonObject.get("uid"); + if (id == null || id.isJsonNull()) { + throw new IOException("Response doesn't contain uid field"); + } + JsonElement email = jsonObject.get("email"); + JsonElement name = jsonObject.get("name"); + return new OAuthUserInfo( + AV_PROVIDER_PREFIX + id.getAsString(), + null, + email.getAsString(), + name.getAsString(), + id.getAsString()); + } + + throw new IOException(String.format("Invalid JSON '%s': not a JSON Object", userJson)); + } + + @Override + public OAuthToken getAccessToken(OAuthVerifier rv) { + Verifier vi = new Verifier(rv.getValue()); + Token to = service.getAccessToken(null, vi); + return new OAuthToken(to.getToken(), to.getSecret(), to.getRawResponse()); + } + + @Override + public String getAuthorizationUrl() { + return service.getAuthorizationUrl(null); + } + + @Override + public String getVersion() { + return service.getVersion(); + } + + @Override + public String getName() { + return "AirVantage OAuth2"; + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/BitbucketOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/BitbucketOAuthService.java index e600067..55680f2 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/BitbucketOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/BitbucketOAuthService.java
@@ -110,7 +110,7 @@ public OAuthToken getAccessToken(OAuthVerifier rv) { Verifier vi = new Verifier(rv.getValue()); Token to = service.getAccessToken(null, vi); - return new OAuthToken(to.getToken(), to.getSecret(), null); + return new OAuthToken(to.getToken(), to.getSecret(), to.getRawResponse()); } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java index 6c5977d..f360cd9 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/CasOAuthService.java
@@ -29,8 +29,10 @@ import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Provider; +import com.google.inject.ProvisionException; import com.google.inject.Singleton; import java.io.IOException; +import java.net.URI; import javax.servlet.http.HttpServletResponse; import org.scribe.builder.ServiceBuilder; import org.scribe.model.OAuthRequest; @@ -60,6 +62,9 @@ @CanonicalWebUrl Provider<String> urlProvider) { PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName + CONFIG_SUFFIX); rootUrl = cfg.getString(InitOAuth.ROOT_URL); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; fixLegacyUserId = cfg.getBoolean(InitOAuth.FIX_LEGACY_USER_ID, false); service =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/DexOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/DexOAuthService.java index ae1ca98..c899e5e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/DexOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/DexOAuthService.java
@@ -30,8 +30,10 @@ import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Provider; +import com.google.inject.ProvisionException; import com.google.inject.Singleton; import java.io.IOException; +import java.net.URI; import org.apache.commons.codec.binary.Base64; import org.scribe.builder.ServiceBuilder; import org.scribe.model.Token; @@ -57,6 +59,9 @@ String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; rootUrl = cfg.getString(InitOAuth.ROOT_URL); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } domain = cfg.getString(InitOAuth.DOMAIN, null); serviceName = cfg.getString(InitOAuth.SERVICE_NAME, "Dex OAuth2"); @@ -93,10 +98,10 @@ JsonElement emailElement = claimObject.get("email"); JsonElement nameElement = claimObject.get("name"); if (emailElement == null || emailElement.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain email field")); + throw new IOException("Response doesn't contain email field"); } if (nameElement == null || nameElement.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain name field")); + throw new IOException("Response doesn't contain name field"); } String email = emailElement.getAsString(); String name = nameElement.getAsString();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/FacebookOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/FacebookOAuthService.java index d3ebe8e..7461154 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/FacebookOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/FacebookOAuthService.java
@@ -96,7 +96,7 @@ JsonObject jsonObject = userJson.getAsJsonObject(); JsonElement id = jsonObject.get("id"); if (id == null || id.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain id field")); + throw new IOException("Response doesn't contain id field"); } JsonElement email = jsonObject.get("email"); JsonElement name = jsonObject.get("name");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java index 8a198d3..13f89cb 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitHubOAuthService.java
@@ -91,7 +91,7 @@ JsonObject jsonObject = userJson.getAsJsonObject(); JsonElement id = jsonObject.get("id"); if (id == null || id.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain id field")); + throw new IOException("Response doesn't contain id field"); } JsonElement email = jsonObject.get("email"); JsonElement name = jsonObject.get("name");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabOAuthService.java index 2d6870a..7e67424 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GitLabOAuthService.java
@@ -31,8 +31,10 @@ import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Provider; +import com.google.inject.ProvisionException; import com.google.inject.Singleton; import java.io.IOException; +import java.net.URI; import org.scribe.builder.ServiceBuilder; import org.scribe.model.OAuthRequest; import org.scribe.model.Response; @@ -59,6 +61,9 @@ PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName + CONFIG_SUFFIX); String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; rootUrl = cfg.getString(InitOAuth.ROOT_URL); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } service = new ServiceBuilder() .provider(new GitLabApi(rootUrl)) @@ -106,7 +111,7 @@ public OAuthToken getAccessToken(OAuthVerifier rv) { Verifier vi = new Verifier(rv.getValue()); Token to = service.getAccessToken(null, vi); - return new OAuthToken(to.getToken(), to.getSecret(), null); + return new OAuthToken(to.getToken(), to.getSecret(), to.getRawResponse()); } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java index e44843a..1199ea3 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/GoogleOAuthService.java
@@ -115,7 +115,7 @@ JsonObject jsonObject = userJson.getAsJsonObject(); JsonElement id = jsonObject.get("id"); if (id == null || id.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain id field")); + throw new IOException("Response doesn't contain id field"); } JsonElement email = jsonObject.get("email"); JsonElement name = jsonObject.get("name");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java index 5348c00..4035a15 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java
@@ -98,5 +98,12 @@ .annotatedWith(Exports.named(Office365OAuthService.CONFIG_SUFFIX)) .to(Office365OAuthService.class); } + + cfg = cfgFactory.getFromGerritConfig(pluginName + AirVantageOAuthService.CONFIG_SUFFIX); + if (cfg.getString(InitOAuth.CLIENT_ID) != null) { + bind(OAuthServiceProvider.class) + .annotatedWith(Exports.named(AirVantageOAuthService.CONFIG_SUFFIX)) + .to(AirVantageOAuthService.class); + } } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java index b8e54e4..9c71792 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java
@@ -13,11 +13,16 @@ // limitations under the License. package com.googlesource.gerrit.plugins.oauth; +import static java.util.Objects.requireNonNull; + +import com.google.common.base.Strings; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.pgm.init.api.ConsoleUI; import com.google.gerrit.pgm.init.api.InitStep; import com.google.gerrit.pgm.init.api.Section; import com.google.inject.Inject; +import com.google.inject.ProvisionException; +import java.net.URI; class InitOAuth implements InitStep { static final String PLUGIN_SECTION = "plugin"; @@ -42,6 +47,7 @@ private final Section dexOAuthProviderSection; private final Section keycloakOAuthProviderSection; private final Section office365OAuthProviderSection; + private final Section airVantageOAuthProviderSection; @Inject InitOAuth(ConsoleUI ui, Section.Factory sections, @PluginName String pluginName) { @@ -64,6 +70,8 @@ sections.get(PLUGIN_SECTION, pluginName + KeycloakOAuthService.CONFIG_SUFFIX); this.office365OAuthProviderSection = sections.get(PLUGIN_SECTION, pluginName + Office365OAuthService.CONFIG_SUFFIX); + this.airVantageOAuthProviderSection = + sections.get(PLUGIN_SECTION, pluginName + AirVantageOAuthService.CONFIG_SUFFIX); } @Override @@ -72,30 +80,30 @@ boolean configureGoogleOAuthProvider = ui.yesno(true, "Use Google OAuth provider for Gerrit login ?"); - if (configureGoogleOAuthProvider) { - configureOAuth(googleOAuthProviderSection); + if (configureGoogleOAuthProvider && configureOAuth(googleOAuthProviderSection)) { googleOAuthProviderSection.string(FIX_LEGACY_USER_ID_QUESTION, FIX_LEGACY_USER_ID, "false"); } boolean configueGitHubOAuthProvider = ui.yesno(true, "Use GitHub OAuth provider for Gerrit login ?"); - if (configueGitHubOAuthProvider) { - configureOAuth(githubOAuthProviderSection); + if (configueGitHubOAuthProvider && configureOAuth(githubOAuthProviderSection)) { githubOAuthProviderSection.string(FIX_LEGACY_USER_ID_QUESTION, FIX_LEGACY_USER_ID, "false"); } boolean configureBitbucketOAuthProvider = ui.yesno(true, "Use Bitbucket OAuth provider for Gerrit login ?"); - if (configureBitbucketOAuthProvider) { - configureOAuth(bitbucketOAuthProviderSection); + if (configureBitbucketOAuthProvider && configureOAuth(bitbucketOAuthProviderSection)) { bitbucketOAuthProviderSection.string( FIX_LEGACY_USER_ID_QUESTION, FIX_LEGACY_USER_ID, "false"); } boolean configureCasOAuthProvider = ui.yesno(true, "Use CAS OAuth provider for Gerrit login ?"); - if (configureCasOAuthProvider) { - casOAuthProviderSection.string("CAS Root URL", ROOT_URL, null); - configureOAuth(casOAuthProviderSection); + if (configureCasOAuthProvider && configureOAuth(casOAuthProviderSection)) { + String rootUrl = casOAuthProviderSection.string("CAS Root URL", ROOT_URL, null); + requireNonNull(rootUrl); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } casOAuthProviderSection.string(FIX_LEGACY_USER_ID_QUESTION, FIX_LEGACY_USER_ID, "false"); } @@ -107,23 +115,32 @@ boolean configureGitLabOAuthProvider = ui.yesno(true, "Use GitLab OAuth provider for Gerrit login ?"); - if (configureGitLabOAuthProvider) { - gitlabOAuthProviderSection.string("GitLab Root URL", ROOT_URL, null); - configureOAuth(gitlabOAuthProviderSection); + if (configureGitLabOAuthProvider && configureOAuth(gitlabOAuthProviderSection)) { + String rootUrl = gitlabOAuthProviderSection.string("GitLab Root URL", ROOT_URL, null); + requireNonNull(rootUrl); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } } boolean configureDexOAuthProvider = ui.yesno(true, "Use Dex OAuth provider for Gerrit login ?"); - if (configureDexOAuthProvider) { - dexOAuthProviderSection.string("Dex Root URL", ROOT_URL, null); - configureOAuth(dexOAuthProviderSection); + if (configureDexOAuthProvider && configureOAuth(dexOAuthProviderSection)) { + String rootUrl = dexOAuthProviderSection.string("Dex Root URL", ROOT_URL, null); + requireNonNull(rootUrl); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } } boolean configureKeycloakOAuthProvider = ui.yesno(true, "Use Keycloak OAuth provider for Gerrit login ?"); - if (configureKeycloakOAuthProvider) { - keycloakOAuthProviderSection.string("Keycloak Root URL", ROOT_URL, null); + if (configureKeycloakOAuthProvider && configureOAuth(keycloakOAuthProviderSection)) { + String rootUrl = keycloakOAuthProviderSection.string("Keycloak Root URL", ROOT_URL, null); + requireNonNull(rootUrl); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } keycloakOAuthProviderSection.string("Keycloak Realm", REALM, null); - configureOAuth(keycloakOAuthProviderSection); } boolean configureOffice365OAuthProvider = @@ -131,11 +148,26 @@ if (configureOffice365OAuthProvider) { configureOAuth(office365OAuthProviderSection); } + + boolean configureAirVantageOAuthProvider = + ui.yesno(true, "Use AirVantage OAuth provider for Gerrit login ?"); + if (configureAirVantageOAuthProvider) { + configureOAuth(airVantageOAuthProviderSection); + } } - private void configureOAuth(Section s) { - s.string("Application client id", CLIENT_ID, null); - s.passwordForKey("Application client secret", CLIENT_SECRET); + /** + * Configure OAuth provider section + * + * @param s section to configure + * @return true if section is present, false otherwise + */ + private boolean configureOAuth(Section s) { + if (!Strings.isNullOrEmpty(s.string("Application client id", CLIENT_ID, null))) { + s.passwordForKey("Application client secret", CLIENT_SECRET); + return true; + } + return false; } @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java index 4b47fdf..99be7ee 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java
@@ -30,7 +30,9 @@ import com.google.gson.JsonObject; import com.google.inject.Inject; import com.google.inject.Provider; +import com.google.inject.ProvisionException; import java.io.IOException; +import java.net.URI; import org.apache.commons.codec.binary.Base64; import org.scribe.builder.ServiceBuilder; import org.scribe.model.Token; @@ -57,6 +59,9 @@ String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; String rootUrl = cfg.getString(InitOAuth.ROOT_URL); + if (!URI.create(rootUrl).isAbsolute()) { + throw new ProvisionException("Root URL must be absolute URL"); + } String realm = cfg.getString(InitOAuth.REALM); serviceName = cfg.getString(InitOAuth.SERVICE_NAME, "Keycloak OAuth2");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java index a9eaddb..ecd8f26 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/OAuth20ServiceImpl.java
@@ -14,6 +14,8 @@ package com.googlesource.gerrit.plugins.oauth; +import static org.slf4j.LoggerFactory.getLogger; + import org.scribe.builder.api.DefaultApi20; import org.scribe.model.OAuthConfig; import org.scribe.model.OAuthConstants; @@ -22,9 +24,11 @@ import org.scribe.model.Token; import org.scribe.model.Verifier; import org.scribe.oauth.OAuthService; +import org.slf4j.Logger; /** TODO(gildur): remove when updating to newer scribe lib */ final class OAuth20ServiceImpl implements OAuthService { + private static final Logger log = getLogger(OAuth20ServiceImpl.class); private static final String VERSION = "2.0"; @@ -56,7 +60,13 @@ request.addBodyParameter(OAuthConstants.SCOPE, config.getScope()); } request.addBodyParameter(GRANT_TYPE, GRANT_TYPE_VALUE); + if (log.isDebugEnabled()) { + log.debug("Access token request: {}", request); + } Response response = request.send(); + if (log.isDebugEnabled()) { + log.debug("Access token response: {}", response.getBody()); + } return api.getAccessTokenExtractor().extract(response.getBody()); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/Office365OAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/Office365OAuthService.java index 360b650..e1ccd29 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/Office365OAuthService.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/Office365OAuthService.java
@@ -97,7 +97,7 @@ JsonObject jsonObject = userJson.getAsJsonObject(); JsonElement id = jsonObject.get("id"); if (id == null || id.isJsonNull()) { - throw new IOException(String.format("Response doesn't contain id field")); + throw new IOException("Response doesn't contain id field"); } JsonElement email = jsonObject.get("mail"); JsonElement name = jsonObject.get("displayName");
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index c16d3ef..757ea1e 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -38,6 +38,10 @@ root-url = "<dex url>" client-id = "<client-id>" client-secret = "<client-secret>" + + [plugin "@PLUGIN@-airvantage-oauth"] + client-id = "<client-id>" + client-secret = "<client-secret>" ``` When one from the sections above is omitted, OAuth SSO is used. @@ -200,3 +204,9 @@ See [Using Dex](https://github.com/coreos/dex/blob/master/Documentation/using-dex.md) for an example. + +### AirVantage + +The client-id and client-secret for AirVantage OAuth can be obtained by registering +a Client application. +See [Getting Started](https://source.sierrawireless.com/airvantage/av/howto/cloud/gettingstarted_api).