238

Inside a script I am trying to clone a GitHub repository with an OAuth token.

According to this tutorial:

https://github.com/blog/1270-easier-builds-and-deployments-using-git-over-https-and-oauth

I should be able to build a command for it like this:

git clone https://<token>@github.com/owner/repo.git

If I try this manually with a proper access token, it still asks for my password.

If I try it on the commandline I am simply getting a repository not found error.

The article is from 2012 and I cannot find any API documentation for this. So I am wondering if this still works.

NoobTW
  • 2,466
  • 2
  • 24
  • 42
Stephan-v
  • 19,255
  • 31
  • 115
  • 201

13 Answers13

281

Just use the HTTPS address to clone with the key as the user, so:

git clone https://oauth-key-goes-here@github.com/username/repo.git

or

git clone https://username:token@github.com/username/repo.git
SKPS
  • 5,433
  • 5
  • 29
  • 63
Andris
  • 4,392
  • 2
  • 20
  • 16
  • 3
    You can also use github Personal Access Token with this command in place of OAuth Key. – Aung Htet Jan 26 '22 at 02:26
  • 33
    It used to work fine for me with classical personal access token, but as of 18th of October, GitHub released also fine-grained personal access token and it looks like for them, you have to use `git clone https://oauth2:@github.com/username/repo.git` – Andy Oct 20 '22 at 12:10
  • Wow. I wonder how the heck this is supposed to work with package managers like composer where the repository info is configured in plain-text JSON. I can't believe that Github doesn't provide a way to pass the key discreetly i.e. through the `COMPOSER_AUTH` environment variable...kind of defeats the purpose of an organization service user use case. – Luke A. Leber Jan 19 '23 at 17:48
  • 2
    The way with `…username:token…` worked for Gitlab as well! – Hi-Angel Apr 06 '23 at 14:50
116

I turned out to be a scope issue. I of course needed full repo scope since I was trying to clone a private repository.

It's a shame Github does not have some clearer error messages for these kind of things, but security wise I understand why.

For anyone trying to figure out what is wrong when trying out something like this, I would suggest to create a personal access token with full access to everything:

settings > developer settings > personal access tokens > generate new token

This way you can easily test if it is a scope issue by comparing your token with a personal access token that has access rights for everything.

Thanks for anyone who still took the time to read this.

Stephan-v
  • 19,255
  • 31
  • 115
  • 201
  • 2
    Mind that if you simply try to access the repo page through a browser you'll still face a 404-not found page. But cloning worked fine regardless in my case. – Herick May 15 '18 at 20:35
  • I provided a scope of `user repo` to the authorization request, and when requesting an access token it always returns with `scope=` (empty scope). Why is that? –  May 06 '20 at 21:46
  • It may seem that there is no way to avoid write access using a Github security token, which is kind of a security limitation for scripts and other integrations where just cloning a private repo is required :( – matanster Jan 29 '22 at 17:53
64

Just clone the repository with HTTP like so:

git clone https://github.com/myuser/myrepo.git

When prompted for Username, fill your username.

When prompted for Password, fill the token instead.

Amit Levy
  • 1,041
  • 8
  • 11
47

Please try this.

git clone `https://oauth2:TOKEN@github.com/username/repo.git`

For example, git clone https://oauth2:ghp_...Gnm61dm4rh@github.com/gituser/testrepo.git

hobbydev
  • 1,513
  • 19
  • 31
  • 3
    it's working. please check the url carefully. @github.com/gituser/testrepo.git – hobbydev Sep 14 '21 at 18:09
  • 4
    This is way better than manually writing the username and password! I can save a github access token variable and user a script with `git clone https://oauth:$GITHUB_TOKEN@github.com/user/repo.git` or just add the token itself to a script. Underrated answer here. – JakeAve Oct 09 '21 at 02:27
  • I get ` remote: Invalid username or password` when using an organization repo :( `git clone https://oauth2:$GITHUB_TOKEN@github.com/MyOrg/repo.git` – A Kingscote Jan 12 '22 at 08:56
  • @AKingscote, please check if your key is correct and not expired. – hobbydev Jan 17 '22 at 09:37
30

Do whatever works for you from these two choices

In your terminal

$ git clone your_repo_url Username:your_token Password:

... there is no password

In your git client app

i.e. Sourcetree, GitKraken, and the GitHub client.

Enter your repo_url (obvsiously without the '$ git clone part')

Username:your_token Password:

... there is no password

OR i.e. in Sourcetree, open preferences and then go to advanced, enter the hostname (i.e. www.x.com) and userName (i.e. your_token)

enter image description here

t.ios
  • 1,024
  • 12
  • 18
  • Using token as username worked for me on windows – John Dec 07 '21 at 16:13
  • I had to use my real username as username and token as a password, not username as of now, maybe I had initially some redundant space in it, or it takes a little while, while the token activation takes places – FantomX1 Jan 26 '22 at 11:56
23

go to https://github.com/settings/tokens and generate a new token, remember to enable access to the repo, after that, you can do the following to clone the repo.

git clone https://<token>@github.com/owner/repo.git

Note: owner is your username if it's your repository else keep username of repository owner(one with all the rights of repo).

TUSHAR BAPECHA
  • 123
  • 1
  • 2
  • 8
sfsf9797
  • 533
  • 5
  • 13
  • remote : repository not found – satendra singh Aug 29 '21 at 09:16
  • 1
    this works for me. i had a dialog for it and after closing it the only way was putting the token in the url. thanks – Laura Liparulo Dec 14 '21 at 13:59
  • 3
    It used to work fine for me with classical personal access token, but as of 18th of October, GitHub released also _fine-grained_ personal access token and it looks like for them, you have to use `git clone https://oauth2:@github.com/owner/repo.git` – Andy Oct 20 '22 at 12:09
4

For lazy folks like future me:

  1. Generate your "Personal access tokens (classic)" from https://github.com/settings/tokens and copy it. (This will behave like password in next steps.)

  2. Run the following git command. It signals git to store the credentials (which will come in step 3)

    git config --global credential.helper manager-core
    git config --global credential.helper store
    
  3. In your first clone you will be asked username and password provide your passowrd coming from item 1 above:

    git clone https://github.com/GithubUserName/repo-to-clone.git
    

For next git commands you should not be asked for credentials.

Mehmet Kaplan
  • 1,723
  • 2
  • 20
  • 43
  • 1
    Note that `manager-core` should be, [from Git 2.39+, `manager` (no longer `manager-core`)](https://stackoverflow.com/a/68768432/6309). And your second `git config --global credential.helper` command would override your first command anyway. – VonC Feb 21 '23 at 13:29
  • 1
    I can not thank enough to past me. This answer was useful 4 times within the last one month only. (I set up 4 different cloud machines, and each time I came here to do this stuff. Thank you past me, I love you!) – Mehmet Kaplan Apr 28 '23 at 12:42
3

Just for those who still have problem "cloning a private repository with a readonly FG token: "remote: Write access to repository not granted."

The error message is a bit misleading. In my case the issue was with the configuration:

  1. Create a readonly token (content: readonly)
  2. Make sure the resource owner is properly set.
  3. For organizations, you have to complete "personal-access-tokens-onboarding".
  4. Clone the repository using https://oauth2:$TOKEN@github.com/myuser/myrepo.git (note the username, as suggested by others, it's oauth2)

With all of the above, I managed to clone a private repository with a readonly token (and no, there was no write access )

Rad
  • 4,292
  • 8
  • 33
  • 71
2

In .net core you can do in this way when dealing with Azure DevOps Repo:

 public void CloneRepository()
        {
            var _gitURL = "URLofGitRemoteRepository";
            var _userName = "PersonalAccessToken";
            var _pswd = ""; //Keep it blank

            var co = new CloneOptions();
            co.CredentialsProvider = (_url, _user, _cred) => new UsernamePasswordCredentials { Username = _userName, Password = _pswd };

            Repository.Clone(_gitURL, filePath, co);
        }
Insa
  • 21
  • 3
2

For me none of the answers above worked. It turns out I had set an expiration of one month on my token so I had to recreate the token using the instructions here: https://www.shanebart.com/clone-repo-using-token/

Ayudh
  • 1,673
  • 1
  • 22
  • 55
1

As of Spring 2023, if you have your access token scopes set correctly, this is a one liner for cloning a repo (no need for any further interaction):

git clone https://ghp_foo_etc:x-oauth-basic@github.com/bar/baz-phoenix.git

Where ghp_foo_etc is your access token. That's it! This is similar to how npm accesses code in private repos. Theres' no need to provide a user name.

I'm pretty certain its' always been so!

Robert Moskal
  • 21,737
  • 8
  • 62
  • 86
1

You need to include a username before the token. GitHub accepts any username. oauth2 works for both GitHub and GitLab.

git clone https://oauth2:token@github.com/owner/repo.git

However including credentials in https Git URL is considered bad practice because it risks inadvert credential exposure from config files and command history.

Also, it will break when the token expires. This is as short as two hours for hosts such as GitLab and BitBucket.

More secure and more reliable is to use a credential-generating helper such as Git Credential Manager (included in Git for Windows) or git-credential-oauth (included in several Linux distributions).

The first time you authenticate, the helper opens a browser window to the host. Subsequent authentication is non interactive.

These helpers refresh expired OAuth tokens as necessary.

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
0

That should be better supported with Git 2.41 (Q2 2023), the credential subsystem learns to help OAuth framework.

See commit a5c7656 (21 Apr 2023) by M Hickford (hickford).
(Merged by Junio C Hamano -- gitster -- in commit 2ca91d1, 10 May 2023)

credential: new attribute oauth_refresh_token

Signed-off-by: M Hickford

Git authentication with OAuth access token is supported by every popular Git host including GitHub, GitLab and BitBucket.
Credential helpers Git Credential Manager (GCM) and git-credential-oauth generate OAuth credentials.
Following RFC 6749, the application prints a link for the user to authorize access in browser.
A loopback redirect communicates the response including access token to the application.

For security, RFC 6749 recommends that OAuth response also includes expiry date and refresh token.
After expiry, applications can use the refresh token to generate a new access token without user reauthorization in browser.
GitLab and BitBucket set the expiry at two hours.
(GitHub doesn't populate expiry or refresh token.)

However the Git credential protocol has no attribute to store the OAuth refresh token (unrecognised attributes are silently discarded).
This means that the user has to regularly reauthorize the helper in browser.
On a browserless system, this is particularly intrusive, requiring a second device.

Introduce a new attribute oauth_refresh_token.
This is especially useful when a storage helper and a read-only OAuth helper are configured together.
Recall that credential fill calls each helper until it has a non-expired password.

    helper = storage  # eg. cache or osxkeychain
    helper = oauth

The OAuth helper can use the stored refresh token forwarded by credential fill to generate a fresh access token without opening the browser.
See https://github.com/hickford/git-credential-oauth/pull/3/files for an implementation tested with this patch.

Add support for the new attribute to credential-cache.
Eventually, I hope to see support in other popular storage helpers.

Alternatives considered: ask helpers to store all unrecognised attributes.
This seems excessively complex for no obvious gain.
Helpers would also need extra information to distinguish between confidential and non-confidential attributes.

Workarounds: GCM abuses the helper get/store/erase contract to store the refresh token during credential get as the password for a fictitious host (I wrote this hack).
This workaround is only feasible for a monolithic helper with its own storage.

git credential now includes in its man page:

oauth_refresh_token

An OAuth refresh token may accompany a password that is an OAuth access token. Helpers must treat this attribute as confidential like the password attribute. Git itself has no special behaviour for this attribute.


With Git 2.43 (Q4 2023), the way authentication related data other than passwords (e.g. oath token and password expiration data) are stored in libsecret keyrings has been rethought.

See commit 0ce02e2 (16 Jun 2023) by M Hickford (hickford).
(Merged by Junio C Hamano -- gitster -- in commit e839608, 28 Aug 2023)

credential/libsecret: store new attributes

Signed-off-by: M Hickford

d208bfd (credential: new attribute password_expiry_utc, 2023-02-18, Git v2.40.0-rc1 -- merge) and a5c7656 (credential: new attribute oauth_refresh_token, 2023-04-21, Git v2.41.0-rc0 -- merge listed in batch #18) introduced new credential attributes.

libsecret assumes attribute values are non-confidential and unchanging, so we encode the new attributes in the secret, separated by newline:

hunter2
password_expiry_utc=1684189401
oauth_refresh_token=xyzzy

This is extensible and backwards compatible.
The credential protocol already assumes that attribute values do not contain newlines.

Alternatives considered: store password_expiry_utc in a libsecret attribute.
This has the problem that libsecret creates new items rather than overwrites when attribute values change.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250