Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Bearer tokens (OAuth 2.0) and Basic ones #94

Open
Djaytan opened this issue Oct 3, 2024 · 5 comments
Open

Support Bearer tokens (OAuth 2.0) and Basic ones #94

Djaytan opened this issue Oct 3, 2024 · 5 comments
Labels
enhancement New feature or request

Comments

@Djaytan
Copy link

Djaytan commented Oct 3, 2024

Description

I would like the following code:

String myAccessToken = "access-token-here";
Git git = ...;
git.push()
    .setCredentialsProvider(new OAuthCredentialsProvider(myAccessToken))
    .setPushAll()
    .call();

to include the following HTTP header in the dispatched request toward the Git server:

Authorization: Bearer access-token-here

Motivation

Nowadays, OAuth 2.0 is a widespread standard for authorization. This is what is typically used by GitHub and Bitbucket.

However, JGit doesn't support this type of authentication, thus leading to troubles. Fortunately, a workaround exists but ideally it would be better to integrate directly the solution inside JGit.

Alternatives considered

The workaround which has been found:

String myAccessToken = "access-token-here"
Git git = ...;
git.push()
    .setTransportConfigCallback(
        transport -> {
          if (transport instanceof TransportHttp transportHttp) {
            transportHttp.setAdditionalHeaders(
                Map.of("Authorization", "Bearer " + myAccessToken));
          }
        })
    .setPushAll()
    .call();

Additional context

Related Stack Overflow question:

@mytest4mail03
Copy link

mytest4mail03 commented Dec 3, 2024

I'm not able to authenticate even with this workaround.

Caused by: org.eclipse.jgit.errors.TransportException: https://github.com/mytest4mail03/spring-petclinic.git: Authentication is required but no CredentialsProvider has been registered

@tomaswolf
Copy link
Contributor

The linked stack overflow post is about accessing Github repositories via HTTPS and appears to be very outdated and/or confused.

For Github, you need to use a Personal Access Token (PAT), and use that as password in a UsernamePasswordCredentialsProvider. This is described in the Egit User's Guide. Using a PAT with Bearer Auth won't work.

@msohn msohn added the enhancement New feature or request label Dec 11, 2024
@msohn
Copy link
Member

msohn commented Dec 11, 2024

Support for OAuth 2 authentication is growing amongst git hosting services [1].
Hence I think that's a valid feature request. Actually I just got the same requirement internally at SAP and was about to file a similar feature request :-)

Implementing typical OAuth authentication flows is not as simple as passing a long-term secret like a GitHub personal access token via bearer header to the application. Instead the client's request is redirected to an OAuth server where the user authenticates using long-term credentials (with a validity of months) and potentially a second factor. On successful authentication the server responds with a short-lived token (validity in the minutes) and redirects the client to the application (here github). The client needs to refresh the short-lived tokens before they expire.

Git has a credentials helper API to retrieve credentials from the user or some credentials store (keychain, cache).
There are implementations of this API supporting OAuth 2, see [2],[3]. We may consider to add the same API to JGit so that it can leverage existing git credentials helpers. Though since this API depends on installation of existing credentials helpers which are not implemented in Java I guess we will use some OAuth Java library to implement OAuth support in JGit.

[1] hickford/git-credential-oauth#17
[2] https://github.com/git-ecosystem/git-credential-manager
[3] https://github.com/hickford/git-credential-oauth

@Djaytan
Copy link
Author

Djaytan commented Dec 29, 2024

Thanks @msohn for your reply!

I guess some clarifications are required from me in order to better explain what is really expected in this ticket.

Clarifications about my request

I started from the assumption that an access token was already available when dealing with JGit (typically after the execution of an OAuth 2.0 authorization grant flow). That's why it was more about providing a convenient way to define a bearer authorization header, without considering (yet) further details like a direct support for OAuth 2.0 authorization grant flows. I realize now that it would be better to make the title more specific... Something like "Support Bearer tokens (OAuth 2.0)".

Doing such small change already answers a bunch of needs. Typically, the cases where long-live tokens can be generated right from the Git hosting solution. In such scenarios, applications just read the access token from an environment variable or a file typically.

Here is an example of process to follow with Bitbucket to generate and then use access tokens. Once generated, the provided usage example that matter to us is the following one:

git clone -c http.extraHeader='Authorization: Bearer MDM0MjM5NDc2MDxxxxxxxxxxxxxxxxxxxxx' https://example.com/scm/projectname/teamsinspace.git

Since the access token needs to be passed as a bearer token in the authorization header, then we need a convenient way through JGit to configure this kind of credentials.

As of today, only the UsernamePasswordCredentialsProvider class is really available to us (ignoring the NetRCCredentialsProvider one). However, it does not support credentials already base64-encoded nor the bearer tokens.

Therefore, the real request here is to provide a convenient way to define basic and bearer tokens.

I already provided the alternative actually available to us for bearer tokens. However, I can provide the one for basic tokens as well since I saw some people being interested by such facility as well. The following should work:

String myBasicToken = "basic-token-here"
Git git = ...;
git.push()
    .setTransportConfigCallback(
        transport -> {
          if (transport instanceof TransportHttp transportHttp) {
            transportHttp.setAdditionalHeaders(
                Map.of("Authorization", "Basic " + myBasicToken));
          }
        })
    .setPushAll()
    .call();

I think this solution is a bit cleaner than the one provided on StackOverflow which consists on exploiting a "hack" when dealing with the UsernamePasswordCredentialsProvider class:

String remoteUrl = "https://${token}@github.com/user/repo.git";
CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider("${token}", "");
git.push().setRemote(remoteUrl).setCredentialsProvider(credentialsProvider).call();

In the end, the target should be (IMHO):

String myBearerToken = "bearer-token-here";
Git git = ...;
git.push()
    .setCredentialsProvider(new HttpBearerTokenCredentialsProvider(myAccessToken))
    .setPushAll()
    .call();

and

String myBasicToken = "basic-token-here";
Git git = ...;
git.push()
    .setCredentialsProvider(new HttpBasicTokenCredentialsProvider(myAccessToken))
    .setPushAll()
    .call();

With UsernamePasswordCredentialsProvider now being a subclass of HttpBasicTokenCredentialsProvider, maybe.

At the beginning I proposed OAuthCredentialsProvider, but now I have a preference for HttpBearerTokenCredentialsProvider in order to align with HttpBasicTokenCredentialsProvider where the prefix correspond to the HTTP authentication scheme.

This is why I'm going to rename the issue "Support Bearer tokens (OAuth 2.0) and Basic ones".

Support OAuth 2.0 authorization grant flows

All of these clarifications now shared about my initial request, it's completely true that having a comprehensive support for OAuth 2.0 makes sense and would be valuable too. That's even more true when we see solutions like GitHub and Bitbucket providing support for some flows (more info here and there for the respective Git host platforms).

In fact, in Amadeus as well we have such needs for administration simplification purposes. Typically, we would like to support interactive flows in order to be able to commit and push changes on behalf of users.

A great source of documentation about the different OAuth 2.0 authorization grant types can be found here. A typical interactive flow is the authorization code with PKCE one.

But I think it would be better to create a separate issue for answering this advanced need.

@Djaytan Djaytan changed the title Support OAuth 2.0 authentication Support Bearer tokens (OAuth 2.0) and Basic ones Dec 29, 2024
@Djaytan
Copy link
Author

Djaytan commented Dec 29, 2024

The linked stack overflow post is about accessing Github repositories via HTTPS and appears to be very outdated and/or confused.

For Github, you need to use a Personal Access Token (PAT), and use that as password in a UsernamePasswordCredentialsProvider. This is described in the Egit User's Guide. Using a PAT with Bearer Auth won't work.

You're right @tomaswolf. I updated my answer accordingly in order to be as comprehensive as possible in regards of the different setups which may exist. Even if the question is old (created 10 years ago), we still face troubles today, hence this feature request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants