[SAP IAS] Add basic OAuth support for GitOverHttp This allows to login with an OAuth token sent as a password. Change-Id: Iaec21b0e23b061601bc3e78aad72fca003be7672
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 0d3ed1d..037281d 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/Module.java
@@ -16,29 +16,35 @@ import com.google.gerrit.extensions.annotations.Exports; import com.google.gerrit.extensions.annotations.PluginName; +import com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider; import com.google.gerrit.server.account.AccountExternalIdCreator; import com.google.gerrit.server.account.externalids.ExternalIdFactory; import com.google.gerrit.server.config.GerritServerConfig; import com.google.inject.AbstractModule; import com.google.inject.Inject; +import com.googlesource.gerrit.plugins.oauth.sap.SAPIasOAuthLoginProvider; import java.util.List; import org.eclipse.jgit.lib.Config; public class Module extends AbstractModule { private final List<String> configuredProviders; private final ExternalIdFactory externalIdFactory; + private final String pluginName; + private final Config cfg; @Inject public Module( @GerritServerConfig Config config, @PluginName String pluginName, ExternalIdFactory externalIdFactory) { + this.pluginName = pluginName; configuredProviders = config.getSubsections("plugin").stream() .filter(s -> s.startsWith(pluginName)) .map(s -> s.substring(pluginName.length() + 1, s.length() - 6)) .toList(); this.externalIdFactory = externalIdFactory; + this.cfg = config; } @Override @@ -51,5 +57,24 @@ new OAuthExternalIdCreator( externalIdFactory, OAuthServiceProviderExternalIdScheme.create(provider))); } + + boolean loginProviderBound = bindOAuthLoginProvider(SAPIasOAuthLoginProvider.class); + + if (!loginProviderBound) { + bind(OAuthLoginProvider.class) + .annotatedWith(Exports.named(pluginName)) + .to(DisabledOAuthLoginProvider.class); + } + } + + private boolean bindOAuthLoginProvider(Class<SAPIasOAuthLoginProvider> loginClass) { + 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); + return true; + } + return false; } }
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 new file mode 100644 index 0000000..5d31e8c --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/sap/SAPIasOAuthLoginProvider.java
@@ -0,0 +1,51 @@ +// 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.github.scribejava.core.model.OAuth2AccessToken; +import com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider; +import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import com.googlesource.gerrit.plugins.oauth.OAuthServiceProviderConfig; +import java.io.IOException; + +@Singleton +@OAuthServiceProviderConfig(name = SAPIasOAuthService.PROVIDER_NAME) +public class SAPIasOAuthLoginProvider implements OAuthLoginProvider { + private final SAPIasOAuthService service; + + @Inject + SAPIasOAuthLoginProvider(SAPIasOAuthService service) { + this.service = service; + } + + @Override + public OAuthUserInfo login(String username, String token) throws IOException { + if (token == null) { + throw new IOException("Authentication error"); + } + OAuth2AccessToken accessToken = new OAuth2AccessToken(token); + OAuthUserInfo userInfo = service.getUserInfo(accessToken); + // A username does not have to be provided, but if it is, it should match + // the username provided by the IDP to prevent confusion. The username is + // not taken into account in the later authentication, only the provided + // external ID is. + if (username != null && !username.equals(userInfo.getUserName())) { + throw new IOException("Authentication error: username does not match"); + } + return userInfo; + } +}