forked from jennybc/happy-git-with-r
-
Notifications
You must be signed in to change notification settings - Fork 0
/
connect-credential-caching.Rmd
285 lines (179 loc) · 12.9 KB
/
connect-credential-caching.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# Cache credentials for HTTPS {#credential-caching}
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 \@ref(ssh-keys)).
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](https://stackoverflow.com/a/11041782/2825349), 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`.
## You should get a personal access token (PAT) {#get-a-pat}
### 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](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/about-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
### How to get a PAT?
GitHub offers instructions for [creating a personal access token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/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:
```{r eval = FALSE}
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.
### 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
## 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)
### Call an R function to store your credentials
As of November 2020, there are two R packages for accessing the Git credential store:
* [gitcreds](https://r-lib.github.io/gitcreds/)
* [credentials](https://docs.ropensci.org/credentials/)
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!
#### gitcreds package
If you don't have gitcreds installed, install via `install.packages("gitcreds")`.
Then call `gitcreds_set()`:
```{r eval = FALSE}
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()`:
```{r eval = FALSE}
gitcreds_get()
#> <gitcreds>
#> protocol: https
#> host : github.com
#> username: PersonalAccessToken
#> password: <-- hidden -->
```
#### credentials package
If you don't have credentials installed, install via `install.packages("credentials")`.
Then call `set_github_pat()`:
```{r eval = FALSE}
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:
```{r eval = FALSE}
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.
### 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 \@ref(push-pull-github)) from your local computer, that test repo will be perfect.
If you have just verified that you can work with GitHub from RStudio (chapter \@ref(rstudio-git-github)), 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 \@ref(shell)) 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.
### 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>`](https://git-scm.com/docs/git-credential) command.
For keeners, that documentation can shed some light on how credentials are stored and looked up.
### 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".
## Activating a Git credential helper
### You might not need to do anything!
As of October 2020, if you install Git using the [methods recommended here in Happy Git](#install-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.
### 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:
``` bash
$ 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](https://docs.github.com/en/free-pro-team@latest/github/using-git/caching-your-github-credentials-in-git)
### 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):
``` bash
$ 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](https://docs.github.com/en/free-pro-team@latest/github/using-git/caching-your-github-credentials-in-git)
### 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](https://docs.github.com/en/free-pro-team@latest/github/using-git/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:
``` bash
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.