Merge "Remove unnecessary whitespaces before ? during init"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java
index 037281d..dc41e8b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java
@@ -22,6 +22,7 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.oauth.sap.SAPIasModule;
import com.googlesource.gerrit.plugins.oauth.sap.SAPIasOAuthLoginProvider;
import java.util.List;
import org.eclipse.jgit.lib.Config;
@@ -58,21 +59,22 @@
externalIdFactory, OAuthServiceProviderExternalIdScheme.create(provider)));
}
- boolean loginProviderBound = bindOAuthLoginProvider(SAPIasOAuthLoginProvider.class);
+ boolean oAuthModuleInstalled =
+ installOAuthModule(SAPIasOAuthLoginProvider.class, new SAPIasModule());
- if (!loginProviderBound) {
+ if (!oAuthModuleInstalled) {
bind(OAuthLoginProvider.class)
.annotatedWith(Exports.named(pluginName))
.to(DisabledOAuthLoginProvider.class);
}
}
- private boolean bindOAuthLoginProvider(Class<SAPIasOAuthLoginProvider> loginClass) {
+ private boolean installOAuthModule(
+ Class<? extends OAuthLoginProvider> loginClass, AbstractModule oAuthModule) {
String loginProviderName = loginClass.getAnnotation(OAuthServiceProviderConfig.class).name();
String cfgSuffix = OAuthPluginConfigFactory.getConfigSuffix(loginProviderName);
- String extIdScheme = OAuthServiceProviderExternalIdScheme.create(loginProviderName);
if (cfg.getString("plugin", pluginName + cfgSuffix, InitOAuth.CLIENT_ID) != null) {
- bind(OAuthLoginProvider.class).annotatedWith(Exports.named(extIdScheme)).to(loginClass);
+ install(oAuthModule);
return true;
}
return false;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasModule.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasModule.java
new file mode 100644
index 0000000..11fefe3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasModule.java
@@ -0,0 +1,37 @@
+// Copyright (C) 2025 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.sap;
+
+import com.google.gerrit.extensions.annotations.Exports;
+import com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider;
+import com.google.inject.AbstractModule;
+import com.google.inject.TypeLiteral;
+import com.googlesource.gerrit.plugins.oauth.OAuthServiceProviderExternalIdScheme;
+import com.sap.cloud.security.token.Token;
+import com.sap.cloud.security.token.validation.CombiningValidator;
+
+public class SAPIasModule extends AbstractModule {
+ @Override
+ public void configure() {
+ String extIdScheme =
+ OAuthServiceProviderExternalIdScheme.create(SAPIasOAuthService.PROVIDER_NAME);
+ bind(new TypeLiteral<CombiningValidator<Token>>() {})
+ .toProvider(SAPIasTokenValidatorProvider.class)
+ .asEagerSingleton();
+ bind(OAuthLoginProvider.class)
+ .annotatedWith(Exports.named(extIdScheme))
+ .to(SAPIasOAuthLoginProvider.class);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthLoginProvider.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthLoginProvider.java
index a029cec..138e1e0 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthLoginProvider.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthLoginProvider.java
@@ -25,6 +25,7 @@
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.account.externalids.ExternalIds;
+import com.google.gerrit.server.config.PluginConfig;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@@ -56,11 +57,10 @@
OAuthPluginConfigFactory cfgFactory,
ExternalIds externalIds,
ExternalIdKeyFactory externalIdKeyFactory) {
+ PluginConfig cfg = cfgFactory.create(SAPIasOAuthService.PROVIDER_NAME);
this.service = service;
this.enableResourceOwnerPasswordFlow =
- cfgFactory
- .create(SAPIasOAuthService.PROVIDER_NAME)
- .getBoolean("enable-resource-owner-password-flow", false);
+ cfg.getBoolean("enable-resource-owner-password-flow", false);
this.externalIds = externalIds;
this.externalIdKeyFactory = externalIdKeyFactory;
this.extIdScheme =
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthService.java
index a41c500..4aa2b53 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthService.java
@@ -38,6 +38,9 @@
import com.googlesource.gerrit.plugins.oauth.OAuthServiceProviderExternalIdScheme;
import com.sap.cloud.security.json.DefaultJsonObject;
import com.sap.cloud.security.token.SapIdToken;
+import com.sap.cloud.security.token.Token;
+import com.sap.cloud.security.token.validation.CombiningValidator;
+import com.sap.cloud.security.token.validation.ValidationResult;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
@@ -57,10 +60,13 @@
private final boolean enablePKCE;
private final AuthorizationUrlBuilder authorizationUrlBuilder;
private final String extIdScheme;
+ private final CombiningValidator<Token> tokenValidator;
@Inject
SAPIasOAuthService(
- OAuthPluginConfigFactory cfgFactory, @CanonicalWebUrl Provider<String> urlProvider) {
+ OAuthPluginConfigFactory cfgFactory,
+ @CanonicalWebUrl Provider<String> urlProvider,
+ CombiningValidator<Token> tokenValidator) {
PluginConfig cfg = cfgFactory.create(PROVIDER_NAME);
String canonicalWebUrl = urlProvider.get();
rootUrl = cfg.getString(InitOAuth.ROOT_URL);
@@ -78,6 +84,7 @@
.build(new SAPIasApi(rootUrl));
authorizationUrlBuilder = service.createAuthorizationUrlBuilder();
extIdScheme = OAuthServiceProviderExternalIdScheme.create(PROVIDER_NAME);
+ this.tokenValidator = tokenValidator;
}
@Override
@@ -86,8 +93,14 @@
return getUserInfo(t);
}
- public OAuthUserInfo getUserInfo(OAuth2AccessToken token) {
+ public OAuthUserInfo getUserInfo(OAuth2AccessToken token) throws IOException {
SapIdToken sapToken = new SapIdToken(getIdToken(token));
+ ValidationResult res = tokenValidator.validate(sapToken);
+ if (!res.isValid()) {
+ log.warn("Invalid token received for " + sapToken.getClaimAsString("sub"));
+ throw new IOException("Authentication error");
+ }
+
String username = sapToken.getClaimAsString("sub");
String externalId = this.extIdScheme + ":" + username;
String email = sapToken.getClaimAsString("email");
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasTokenValidatorProvider.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasTokenValidatorProvider.java
new file mode 100644
index 0000000..2f1c28d
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasTokenValidatorProvider.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2025 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.sap;
+
+import static com.googlesource.gerrit.plugins.oauth.sap.SAPIasOAuthService.PROVIDER_NAME;
+
+import com.google.common.base.Splitter;
+import com.google.gerrit.server.config.PluginConfig;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.oauth.InitOAuth;
+import com.googlesource.gerrit.plugins.oauth.OAuthPluginConfigFactory;
+import com.sap.cloud.security.client.DefaultHttpClientFactory;
+import com.sap.cloud.security.config.ClientCredentials;
+import com.sap.cloud.security.config.OAuth2ServiceConfiguration;
+import com.sap.cloud.security.config.OAuth2ServiceConfigurationBuilder;
+import com.sap.cloud.security.config.Service;
+import com.sap.cloud.security.token.Token;
+import com.sap.cloud.security.token.validation.CombiningValidator;
+import com.sap.cloud.security.token.validation.validators.JwtValidatorBuilder;
+import java.util.List;
+
+@Singleton
+public class SAPIasTokenValidatorProvider implements Provider<CombiningValidator<Token>> {
+ private static final String ONDEMAND_DOMAIN = ".ondemand.com";
+ private static final String CLOUD_DOMAIN = ".cloud.sap";
+
+ private final PluginConfig cfg;
+ private final OAuth2ServiceConfiguration serviceConfiguration;
+
+ @Inject
+ SAPIasTokenValidatorProvider(OAuthPluginConfigFactory cfgFactory) {
+ cfg = cfgFactory.create(PROVIDER_NAME);
+
+ List<String> rootUrlParts = Splitter.on('.').splitToList(cfg.getString(InitOAuth.ROOT_URL));
+ String universeSubdomain = rootUrlParts.get(rootUrlParts.size() - 3);
+ serviceConfiguration =
+ OAuth2ServiceConfigurationBuilder.forService(Service.IAS)
+ .withUrl(cfg.getString(InitOAuth.ROOT_URL))
+ .withClientId(cfg.getString(InitOAuth.CLIENT_ID))
+ .withDomains(universeSubdomain + ONDEMAND_DOMAIN, universeSubdomain + CLOUD_DOMAIN)
+ .build();
+ }
+
+ @Override
+ public CombiningValidator<Token> get() {
+ ClientCredentials clientCredentials =
+ new ClientCredentials(
+ cfg.getString(InitOAuth.CLIENT_ID), cfg.getString(InitOAuth.CLIENT_SECRET));
+ return JwtValidatorBuilder.getInstance(serviceConfiguration)
+ .withHttpClient(new DefaultHttpClientFactory().createClient(clientCredentials))
+ .build();
+ }
+}