Skip to content

Commit 3fc6791

Browse files
authored
Merge pull request #307 from microsoft/master
Cut new release with experimental No-PAT support for AzRepos
2 parents 161775c + 293204e commit 3fc6791

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3675
-882
lines changed

docs/azrepos-users-and-tokens.md

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# Azure Repos: Access tokens and Accounts
2+
3+
## Different credential types
4+
5+
The Azure Repos host provider supports creating multiple types of credential:
6+
7+
- Azure DevOps personal access tokens
8+
- Microsoft identity OAuth tokens (experimental)
9+
10+
### Azure DevOps personal access tokens
11+
12+
Historically, the only option supported by the Azure Repos host provider was
13+
Azure DevOps Personal Access Tokens (PATs).
14+
15+
These PATs are only used by Azure DevOps, and must be [managed through the Azure
16+
DevOps user settings page](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page).
17+
18+
PATs have a limited lifetime and new tokens must be created once they expire. In
19+
Git Credential Manager, when a PAT expired (or was manually revoked) this
20+
resulted in a new authentication prompt.
21+
22+
### Microsoft identity OAuth tokens (experimental)
23+
24+
"Microsoft identity OAuth token" is the generic term for OAuth-based access
25+
tokens issued by Azure Active Directory for either Work and School Accounts
26+
(AAD tokens) or Personal Accounts (Microsoft Account/MSA tokens).
27+
28+
Azure DevOps supports Git authentication using Microsoft identity OAuth tokens
29+
as well as PATs. Microsoft identity OAuth tokens created by Git Credential
30+
Manager are scoped to Azure DevOps only.
31+
32+
Unlike PATs, Microsoft identity OAuth tokens get automatically refreshed and
33+
renewed as long as you are actively using them to perform Git operations.
34+
35+
These tokens are also securely shared with other Microsoft developer tools
36+
including the Visual Studio IDE and Azure CLI. This means that as long as you're
37+
using Git or one of these tools with the same account, you'll never need to
38+
re-authenticate due to expired tokens!
39+
40+
#### User accounts
41+
42+
In versions of Git Credential Manager that support Microsoft identity OAuth
43+
tokens, the user account used to authenticate for a particular Azure DevOps
44+
organization will now be remembered.
45+
46+
The first time you clone, fetch or push from/to an Azure DevOps organization you
47+
will be prompted to sign-in and select a user account. Git Credential Manager
48+
will remember which account you used and continue to use that for all future
49+
remote Git operations (clone/fetch/push). An account is said to be "bound" to
50+
an Azure DevOps organization.
51+
52+
---
53+
54+
**Note:** If GCM is set to use PAT credentials, this account will **NOT** be
55+
used and you will continue to be prompted to select a user account to renew the
56+
credential. This may change in the future.
57+
58+
---
59+
60+
Normally you won't need to worry about managing which user accounts Git
61+
Credential Manager is using as this is configured automatically when you first
62+
authenticate for a particular Azure DevOps organziation.
63+
64+
In advanced scenarios (such as using multiple accounts) you can interact with
65+
and manage remembered user accounts using the 'azure-repos' provider command:
66+
67+
```shell
68+
git-credential-manager-core azure-repos [ list | bind | unbind | ... ] <options>
69+
```
70+
71+
##### Listing remembered accounts
72+
73+
You can list all bound user accounts by Git Credential Manager for each Azure
74+
DevOps organization using the `list` command:
75+
76+
```shell
77+
$ git-credential-manager-core azure-repos list
78+
contoso:
79+
(global) -> [email protected]
80+
fabrikam:
81+
(global) -> [email protected]
82+
```
83+
84+
In the above example, the `contoso` Azure DevOps organization is associated with
85+
the `[email protected]` user account, while the `fabrikam` organization is
86+
associated to the `[email protected]` user account.
87+
88+
Global "bindings" apply to all remote Git operations for the current computer
89+
user profile and are stored in `~/.gitconfig` or `%USERPROFILE%\.gitconfig`.
90+
91+
##### Using different accounts within a repository
92+
93+
If you generally use one account for an Azure DevOps organization, the default
94+
global bindings will be sufficient. However, if you wish to use a different
95+
user account for an organization in a particular repository you can use a local
96+
binding.
97+
98+
Local account bindings only apply within a single repository and are stored in
99+
the `.git/config` file. If there are local bindings in a repository you can show
100+
them with the `list` command:
101+
102+
```shell
103+
~/myrepo$ git-credential-manager-core azure-repos list
104+
contoso:
105+
(global) -> [email protected]
106+
(local) -> [email protected]
107+
```
108+
109+
Within the `~/myrepo` repository, the `[email protected]` account will be
110+
used by Git and GCM for the `contoso` Azure DevOps organization.
111+
112+
To create a local binding, use the `bind` command with the `--local` option when
113+
inside a repository:
114+
115+
```shell
116+
~/myrepo$ git-credential-manager-core azure-repos bind --local contoso [email protected]
117+
```
118+
119+
```diff
120+
contoso:
121+
(global) -> [email protected]
122+
+ (local) -> [email protected]
123+
```
124+
125+
##### Forget an account
126+
127+
To have Git Credential Manager forget a user account, use the `unbind` command:
128+
129+
```shell
130+
git-credential-manager-core azure-repos unbind fabrikam
131+
```
132+
133+
```diff
134+
contoso:
135+
(global) -> [email protected]
136+
- fabrikam:
137+
- (global) -> [email protected]
138+
```
139+
140+
In the above example, and global account binding for the `fabrikam` organization
141+
will be forgotten. The next time you need to renew a PAT (if using PATs) or
142+
perform any remote Git operation (is using Azure tokens) you will be prompted
143+
to authenticate again.
144+
145+
To forget or remove a local binding, within the repository run the `unbind`
146+
command with the `--local` option:
147+
148+
```shell
149+
~/myrepo$ git-credential-manager-core azure-repos unbind --local contoso
150+
```
151+
152+
```diff
153+
contoso:
154+
(global) -> [email protected]
155+
- (local) -> [email protected]
156+
```
157+
158+
##### Using different accounts for specific Git remotes
159+
160+
As well as global and local user account bindings, you can instruct Git
161+
Credential Manager to use a specific user account for an individual Git remotes
162+
within the same local repository.
163+
164+
To show which accounts are being used for each Git remote in a repository use
165+
the `list` command with the `--show-remotes` option:
166+
167+
```shell
168+
~/myrepo$ git-credential-manager-core azure-repos list --show-remotes
169+
contoso:
170+
(global) -> [email protected]
171+
origin:
172+
(fetch) -> (inherit)
173+
(push) -> (inherit)
174+
fabrikam:
175+
(global) -> [email protected]
176+
```
177+
178+
In the above example, the `~/myrepo` repository has a single Git remote named
179+
`origin` that points to the `contoso` Azure DevOps organziation. There is no
180+
user account specifically associated with the `origin` remote, so the global
181+
user account binding for `contoso` will be used (the global binding is
182+
inherited).
183+
184+
To associate a user account with a particular Git remote you must manually edit
185+
the remote URL using `git config` commands to include the username in the
186+
[user information](https://tools.ietf.org/html/rfc3986#section-3.2.1) part of
187+
the URL.
188+
189+
```shell
190+
git config --local remote.origin.url https://alice-alt%[email protected]/project/_git/repo
191+
```
192+
193+
In the above example the `[email protected]` account is being set as the
194+
account to use for the `origin` Git remote.
195+
196+
---
197+
198+
**Note:** All special characters must be URL encoded/escaped, for example `@`
199+
becomes `%40`.
200+
201+
---
202+
203+
The `list --show-remotes` command will show the user account specified in the
204+
remote URL:
205+
206+
```shell
207+
~/myrepo$ git-credential-manager-core azure-repos list --show-remotes
208+
contoso:
209+
(global) -> [email protected]
210+
origin:
211+
(fetch) -> [email protected]
212+
213+
fabrikam:
214+
(global) -> [email protected]
215+
```

docs/configuration.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,26 @@ Credential: "git:https://[email protected]/example/myrepo" (user = bob)
333333
334334
https://[email protected]/example/myrepo
335335
```
336+
337+
---
338+
339+
### credential.azreposCredentialType _(experimental)_
340+
341+
Specify the type of credential the Azure Repos host provider should return.
342+
343+
Defaults to the value `pat`.
344+
345+
Value|Description
346+
-|-
347+
`pat` _(default)_|Azure DevOps personal access tokens
348+
`oauth`|Microsoft identity OAuth tokens (AAD or MSA tokens)
349+
350+
More information about Azure Access tokens can be found [here](azrepos-azuretokens.md).
351+
352+
#### Example
353+
354+
```shell
355+
git config --global credential.azreposCredentialType oauth
356+
```
357+
358+
**Also see: [GCM_AZREPOS_CREDENTIALTYPE](environment.md#GCM_AZREPOS_CREDENTIALTYPE-experimental)**

docs/environment.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,32 @@ export GCM_MSAUTH_FLOW="devicecode"
424424
```
425425

426426
**Also see: [credential.msauthFlow](configuration.md#credentialmsauthflow)**
427+
428+
---
429+
430+
### GCM_AZREPOS_CREDENTIALTYPE _(experimental)_
431+
432+
Specify the type of credential the Azure Repos host provider should return.
433+
434+
Defaults to the value `pat`.
435+
436+
Value|Description
437+
-|-
438+
`pat` _(default)_|Azure DevOps personal access tokens
439+
`oauth`|Microsoft identity OAuth tokens (AAD or MSA tokens)
440+
441+
More information about Azure Access tokens can be found [here](azrepos-azuretokens.md).
442+
443+
##### Windows
444+
445+
```batch
446+
SET GCM_AZREPOS_CREDENTIALTYPE="oauth"
447+
```
448+
449+
##### macOS/Linux
450+
451+
```bash
452+
export GCM_AZREPOS_CREDENTIALTYPE="oauth"
453+
```
454+
455+
**Also see: [credential.azreposCredentialType](configuration.md#azreposcredentialtype-experimental)**

docs/usage.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,10 @@ Read the [Git manual](https://git-scm.com/docs/gitcredentials#_custom_helpers) a
3030
Set your user-level Git configuration (`~/.gitconfig`) to use GCM Core. If you pass
3131
`--system` to these commands, they act on the system-level Git configuration
3232
(`/etc/gitconfig`) instead.
33+
34+
### azure-repos (experimental)
35+
36+
Interact with the Azure Repos host provider to bind/unbind user accounts to Azure DevOps
37+
organizations or specific remote URLs, and manage the authentication authority cache.
38+
39+
For more information about managing user account bindings see [here](azrepos-users-and-tokens.md#useraccounts).

src/shared/Atlassian.Bitbucket/BitbucketHostProvider.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ public bool IsSupported(InputArguments input)
4646
}
4747

4848
// Split port number and hostname from host input argument
49-
input.TryGetHostAndPort(out string hostName, out _);
49+
if (!input.TryGetHostAndPort(out string hostName, out _))
50+
{
51+
return false;
52+
}
5053

5154
// We do not support unencrypted HTTP communications to Bitbucket,
5255
// but we report `true` here for HTTP so that we can show a helpful

src/shared/GitHub/GitHubHostProvider.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ public override bool IsSupported(InputArguments input)
6363
}
6464

6565
// Split port number and hostname from host input argument
66-
input.TryGetHostAndPort(out string hostName, out _);
66+
if (!input.TryGetHostAndPort(out string hostName, out _))
67+
{
68+
return false;
69+
}
6770

6871
if (StringComparer.OrdinalIgnoreCase.Equals(hostName, GitHubConstants.GitHubBaseUrlHost) ||
6972
StringComparer.OrdinalIgnoreCase.Equals(hostName, GitHubConstants.GistBaseUrlHost))

0 commit comments

Comments
 (0)