Chapter 10 Cache credentials for HTTPS

If you plan to push/pull using HTTPS, you want to cache your credentials (e.g. password), so you don’t need to enter them over and over again. Alternatively, you could set up SSH keys (chapter 11). I suggest you set up one of these methods of authentication on each computer you want to connect to GitHub from.

I find HTTPS easier to get working quickly and strongly recommend it when you first start working with Git/GitHub. HTTPS is what GitHub recommends, presumably for exactly the same reasons. I started with HTTPS, preferred SSH for a while, and have returned to HTTPS. Either is fine, you can change your mind later, and you can use HTTPS on one machine and SSH on another.

Remember: the transport protocol is controlled by the URL you use for remote repo access.

HTTPS remotes look like https://github.com/<OWNER>/<REPO>.git.
SSH remotes look like git@github.com:<OWNER>/<REPO>.git.

10.1 You should get a personal access token (PAT)

10.1.1 Why a PAT?

Password-based authentication for Git is deprecated, i.e. you really should not be sending your username and password every time you push or pull. Here, I’m referring to the username and password you would use to login to GitHub in the browser.

What should you do instead?

Get a personal access token (PAT) and use that as your credential for HTTPS operations. (The PAT will actually be sent as the password and the username is somewhat artificial, consulted only for credential lookup.)

If you turn on two-factor authentication (a.k.a. “2FA”) for GitHub and you use HTTPS, you absolutely must send a personal access token. And, really, it’s a good idea for everyone to turn on 2FA and for everyone who uses HTTPS to use a PAT.

The final selling point is that once you configure a PAT, several R packages, including usethis and gh, will be able to work with the GitHub API on your behalf, automagically. Therefore, a properly configured PAT means all of this will work seamlessly:

  • Remote HTTPS operations via command line Git and, therefore, via RStudio
  • Remote HTTPS operations via the gert R package and, therefore, usethis
  • GitHub API operations via the gh R package and, therefore, usethis

10.1.2 How to get a PAT?

GitHub offers instructions for creating a personal access token.

The usethis package has a helper function that takes you to the web form to create a PAT, with the added benefit that it pre-selects the recommended scopes:

usethis::create_github_token()

Once you are happy with the selected scopes, click “Generate token”. As the page says, you must store this token somewhere, because you’ll never be able to see it again, once you leave that page or close the window.

10.1.3 How to manage a PAT?

Treat this PAT like a password! If you use a password management app, such as 1Password or LastPass (which you should), it is highly recommended to add this PAT to your entry for GitHub. Below, we will add your PAT to the Git credential store as a semi-persistent convenience, sort of like “remember me” on a website. But, just like logging into websites, it is entirely possible that your PAT will somehow be forgotten from the credential store and you will need to re-enter it.

If you goof this up, i.e. generate a PAT but fail to capture it on your system, you’ll have to generate another one. This is not the end of the world, but you should delete the “lost” PAT on GitHub. If you aren’t disciplined about labelling PATs and deleting lost PATs, you will find yourself in an unsettling situation where you can’t be sure which PAT(s) are in use. When logged into your GitHub account, you can manage your PATs here:

https://github.com/settings/tokens

Do not ever hard-wire your PAT into your code! A PAT should always be retrieved implicitly, for example, from the Git credential store or from an environment variable.

At this point, I assume you’ve generated a PAT and have it available, either:

  • In a secure, long-term system for storing secrets, like 1Password or LastPass (recommended)
  • For the next few minutes, e.g. in a browser window or on the clipboard

10.2 Store your credential

There are many ways to get your credential into the Git store. You need to trigger a prompt for your credential and usually it will be stored for next time.

If your credential doesn’t seem to be stored and re-discovered, see the last section.

If something has been stored and is being re-discovered, but you’re not 100% sure it’s what you want (e.g. username and password vs. PAT), we give some pointers below.

Ways to access the credential store, in order of relevance:

  • Call an R function to store (or update) your credentials
  • Organic Git use, e.g. via the command line or even RStudio (clunky)
  • Make an explicit call to the Git credential manager (for keeners only)
  • Go into your OS-level credential store (for keeners only)

10.2.1 Call an R function to store your credentials

As of November 2020, there are two R packages for accessing the Git credential store:

It is likely that these packages will eventually combine into one and, even now, they are largely interoperable. You don’t need to follow the instructions for both packages – pick one!

10.2.1.1 gitcreds package

If you don’t have gitcreds installed, install via install.packages("gitcreds").

Then call gitcreds_set():

library(gitcreds)

gitcreds_set()

gitcreds::gitcreds_set() is a very handy function, since it reports any current credential, allows you to see it, allows you to keep or replace an existing credential, and can also store a credential for the first time.

Respond to the prompt with your personal access token (PAT).

You can check that you’ve stored a credential with gitcreds_get():

gitcreds_get()
#> <gitcreds>
#>   protocol: https
#>   host    : github.com
#>   username: PersonalAccessToken
#>   password: <-- hidden -->

10.2.1.2 credentials package

If you don’t have credentials installed, install via install.packages("credentials").

Then call set_github_pat():

library(credentials)

set_github_pat()

Respond to the prompt with your personal access token (PAT).

If successful, your initial (and subsequent) calls will look like this:

set_github_pat()
#> If prompted for GitHub credentials, enter your PAT in the password field
#> Using GITHUB_PAT from Jennifer (Jenny) Bryan (credential helper: osxkeychain)

Other functions are available if you need more control, such as credentials::git_credential_forget() for clearing a credential.

10.2.2 Store credentials through organic Git use

Before gitcreds and credentials existed (see above), we had to store the PAT through organic Git use. We still show this method, but we now recommend using the approaches above, because they are much more direct.

Pre-requisite: You need a functioning test Git repository. One that exists locally and remotely on GitHub, with the local repo tracking the remote.

If you have just verified that you can interact with GitHub (chapter 9) from your local computer, that test repo will be perfect.

If you have just verified that you can work with GitHub from RStudio (chapter 12), that test repo will also be perfect.

You may proceed when

  • You have a test repo.

  • You know where it lives on your local computer. Example:

    • /home/jenny/tmp/myrepo
  • You know where it lives on GitHub. Example:

    • https://github.com/jennybc/myrepo
  • You know the GitHub repo is setup as a remote. In a shell (Appendix A) working directory set to the local Git repo, enter:

    git remote -v

    Output like this confirms that fetch and push are set to remote URLs that point to your GitHub repo:

    origin  https://github.com/jennybc/myrepo (fetch)
    origin  https://github.com/jennybc/myrepo (push)

    Now enter:

    git branch -vv

    Here we confirm that the local master branch is tracking your GitHub master branch (origin/master). Gibberish? Just check that your output looks similar to mine:

    master b8e03e3 [origin/master] line added locally

Trigger a username / password challenge

Change a file in your local repo and commit it. Do that however you wish. Here are shell commands that will work:

echo "adding a line" >> README.md
git add -A
git commit -m "A commit from my local computer"

Now push!

git push -u origin master

You should be asked for your username and password. If you’ve taken our advice to get a PAT, provide your PAT as the password. Hopefully, this credential will be stored.

Now push AGAIN.

git push

You should NOT be asked for your username and password, instead you should see Everything up-to-date.

Rejoice and close the shell.

10.2.3 Access the Git credential manager directly

This is not a recommended interface for regular Git users. It is what the gitcreds and credentials packages and command line Git do on your behalf, when they need a credential.

But for completeness, let it be known that, behind the scenes, there is the git credential <fill|approve|reject> command. For keeners, that documentation can shed some light on how credentials are stored and looked up.

10.2.4 Access the OS-level keychain or wallet

On Windows, your Git credentials are probably being stored via Credential Manager.

On macOS, your Git credentials are probably being stored in the Keychain.

So if you really want to poke around directly to explore or clean out your GitHub credentials, launch Credential Manager (Windows) or Keychain Access (macOS) and search for “github.com”.

10.3 Activating a Git credential helper

10.3.1 You might not need to do anything!

As of October 2020, if you install Git using the methods recommended here in Happy Git, it is likely that Git is already configured to use a credential helper, backed by a proper credential store provided by your operating system. Of course, you will have to provide your credential at least once, but most users do not need to do anything special to arrange for their credentials to be stored and retrieved later.

Specifically, if you are on macOS or Windows, don’t do anything described here until you have actual proof that it’s necessary, i.e. until you have experienced repeated challenges for your credentials when using HTTPS.

10.3.2 Windows

In my most recent experiments, Git for Windows is configured to store credentials via the Credential Manager.

Here’s a command to reveal the configuration and the output I see in a fresh installation of Git for Windows:

$ git config --show-origin --get credential.helper
file:C:/Program Files/Git/mingw64/etc/gitconfig manager

In the unlikely event that you need to activate a credential helper, GitHub’s instructions are the best bet, in terms of being current:

Caching your GitHub credentials in Git

10.3.3 macOS

I have not needed to explicitly activate a credential helper on macOS in a long while.

Here’s a command to reveal the current credential helper and the output I see (October 2020, macOS 10.15.6, Git 2.24.3):

$ git config --show-origin --get credential.helper
file:/Users/jenny/.gitconfig    osxkeychain

I expect most users to see the osxkeychain helper, configured either at the system or user level.

In the unlikely event that you need to activate a credential helper, GitHub’s instructions are the best bet, in terms of being current:

Caching your GitHub credentials in Git

10.3.4 Linux

As opposed to Windows and macOS, Linux users are the ones for whom credential storage may not “just work” out of the box. The easiest thing to do is to configure Git to “cache” your credentials (vs “store”), which is more time-limited. Then set the cache timeout to some suitably long period of time. You can expect to re-enter your PAT more often than Windows and macOS users.

We paraphrase the Linux instructions from GitHub’s documentation Caching your GitHub credentials in Git, which should be regarded the best and most current source.

In the shell, turn on the “cache” credential helper and set its timeout:

git config --global credential.helper 'cache --timeout=10000000'

Above, we set the timeout to ten million seconds or around 16 weeks, enough for a semester.