davido / gerrit-oauth-provider

OAuth2 authentication provider for Gerrit Code Review. Please upload changes for review to: https://gerrit-review.googlesource.com/#/admin/projects/plugins/oauth
Apache License 2.0
140 stars 84 forks source link

Support OAuth for Git-over-HTTP #173

Open rohanj1 opened 1 week ago

rohanj1 commented 1 week ago

Hi, we are trying to move away from SSH and HTTP-password-based authentication to OAuth for git operations. Are there any plans to support OAuth-token authentication for Git-over-HTTP? Based on #84, it seems like the OAuthLoginProvider interface has to be implemented. Is there a specific reason/issue for which this was not implemented? I would be happy to contribute. Thanks.

davido commented 1 week ago

Good point.

Is there a specific reason/issue for which this was not implemented?

Nobody has contributed it until now.

I would be happy to contribute.

👍

@lucamilanesio how Git-over-HTTP works with your GitHub-plugin?

davido commented 1 week ago

Note, that cfoauth plugin actually implements this OAuthLoginProvider interface:

https://gerrit.googlesource.com/plugins/cfoauth/+/refs/heads/master/src/main/java/com/googlesource/gerrit/plugins/cfoauth/CFOAuthService.java#88

  @Override
  public OAuthUserInfo login(String username, String secret)
      throws IOException {
    if (username == null || secret == null) {
      throw new IOException("Authentication error");
    }
    AccessToken accessToken;
    try {
      if (uaaClient.isAccessTokenForClient(username, secret)) {
        // "secret" is an access token for a client, i.e. a
        // technical user; send it to UAA for verification
        if (!uaaClient.verifyAccessToken(secret)) {
          throw new IOException("Authentication error");
        }
        return getAsOAuthUserInfo(username);
      } else {
        if (uaaClient.isAccessTokenForUser(username, secret)) {
          // "secret" is an access token for an ordinary user;
          // send it to UAA for verification
          if (!uaaClient.verifyAccessToken(secret)) {
            throw new IOException("Authentication error");
          }
          accessToken = uaaClient.toAccessToken(secret, EMPTY_STRING);
        } else {
          // "secret" is not an access token but likely a password;
          // send username and password to UAA and try to get an access
          // token; if that succeeds the user is authenticated
          accessToken = uaaClient.getAccessToken(username, secret);
        }
        return getAsOAuthUserInfo(accessToken);
      }
    } catch (UAAClientException e) {
      throw new IOException("Authentication error", e);
    }
  }
davido commented 1 week ago

However, to access the accessToken from the username and password, to implement this interface:

@ExtensionPoint
public interface OAuthLoginProvider {

  /**
   * Performs a login with an OAuth2 provider for Git over HTTP communication.
   *
   * <p>An implementation of this interface must transmit the given user name and secret, which can
   * be either an OAuth2 access token or a password, to the OAuth2 backend for verification.
   *
   * @param username the user's identifier.
   * @param secret the secret to verify, e.g. a previously received access token or a password.
   * @return information about the logged in user, at least external id, user name and email
   *     address.
   * @throws IOException if the login failed.
   */
  OAuthUserInfo login(String username, String secret) throws IOException;
}

grant_type password in OAuth Protocol must be used.

However, the password grant type is prohibited in the latest OAuth 2.0 Security Best Current Practice specification.

That's why it's not implemented.

rohanj1 commented 1 week ago

Sorry, could you elaborate a little bit on what grant_type password means? I was planning to use something like this to obtain temporary access tokens. On a side note, the same project seems to support android.googlesource.com (a gerrit instance) for OAuth based git operations. Do you think they have configured it differently or is there something I'm missing about how to setup such a flow. Thanks!

davido commented 1 week ago

Apparently I confused the current implementation in cfoauth-plugin with the the correct way to validate the OAuth token, to implement the OAuthLoginProvider interface's login method.