Merge pull request #329 from whoisj/improve-basic-authentication
Improve basic authentication support.
This commit is contained in:
Коммит
8889c3d75a
|
@ -365,6 +365,20 @@ namespace Microsoft.Alm.Cli
|
|||
var secrets = new SecretStore(secretsNamespace, null, null, Secret.UriToName);
|
||||
BaseAuthentication authority = null;
|
||||
|
||||
var basicCredentialCallback = (operationArguments.UseModalUi)
|
||||
? new AcquireCredentialsDelegate(Program.ModalPromptForCredentials)
|
||||
: new AcquireCredentialsDelegate(Program.BasicCredentialPrompt);
|
||||
|
||||
var githubCredentialCallback = (operationArguments.UseModalUi)
|
||||
? new GitHubAuthentication.AcquireCredentialsDelegate(GitHub.Authentication.AuthenticationPrompts.CredentialModalPrompt)
|
||||
: new GitHubAuthentication.AcquireCredentialsDelegate(Program.GitHubCredentialPrompt);
|
||||
|
||||
var githubAuthcodeCallback = (operationArguments.UseModalUi)
|
||||
? new GitHubAuthentication.AcquireAuthenticationCodeDelegate(GitHub.Authentication.AuthenticationPrompts.AuthenticationCodeModalPrompt)
|
||||
: new GitHubAuthentication.AcquireAuthenticationCodeDelegate(Program.GitHubAuthCodePrompt);
|
||||
|
||||
NtlmSupport basicNtlmSupport = NtlmSupport.Auto;
|
||||
|
||||
switch (operationArguments.Authority)
|
||||
{
|
||||
case AuthorityType.Auto:
|
||||
|
@ -377,13 +391,9 @@ namespace Microsoft.Alm.Cli
|
|||
?? GitHubAuthentication.GetAuthentication(operationArguments.TargetUri,
|
||||
GitHubCredentialScope,
|
||||
secrets,
|
||||
operationArguments.UseModalUi
|
||||
? new GitHubAuthentication.AcquireCredentialsDelegate(GitHub.Authentication.AuthenticationPrompts.CredentialModalPrompt)
|
||||
: new GitHubAuthentication.AcquireCredentialsDelegate(GitHubCredentialPrompt),
|
||||
operationArguments.UseModalUi
|
||||
? new GitHubAuthentication.AcquireAuthenticationCodeDelegate(GitHub.Authentication.AuthenticationPrompts.AuthenticationCodeModalPrompt)
|
||||
: new GitHubAuthentication.AcquireAuthenticationCodeDelegate(GitHubAuthCodePrompt),
|
||||
null); ;
|
||||
githubCredentialCallback,
|
||||
githubAuthcodeCallback,
|
||||
null);
|
||||
|
||||
if (authority != null)
|
||||
{
|
||||
|
@ -416,28 +426,20 @@ namespace Microsoft.Alm.Cli
|
|||
return authority ?? new VstsAadAuthentication(Guid.Empty, VstsCredentialScope, secrets);
|
||||
|
||||
case AuthorityType.Basic:
|
||||
default:
|
||||
Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is basic.");
|
||||
|
||||
// return a generic username + password authentication object
|
||||
return authority ?? new BasicAuthentication(secrets,
|
||||
operationArguments.UseModalUi
|
||||
? new AcquireCredentialsDelegate(Program.ModalPromptForCredentials)
|
||||
: new AcquireCredentialsDelegate(Program.BasicCredentialPrompt),
|
||||
null);
|
||||
// enforce basic authentication only
|
||||
basicNtlmSupport = NtlmSupport.Never;
|
||||
goto default;
|
||||
|
||||
case AuthorityType.GitHub:
|
||||
Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is GitHub.");
|
||||
|
||||
|
||||
|
||||
// return a GitHub authentication object
|
||||
return authority ?? new GitHubAuthentication(GitHubCredentialScope,
|
||||
secrets,
|
||||
operationArguments.UseModalUi
|
||||
? new GitHubAuthentication.AcquireCredentialsDelegate(GitHub.Authentication.AuthenticationPrompts.CredentialModalPrompt)
|
||||
: new GitHubAuthentication.AcquireCredentialsDelegate(GitHubCredentialPrompt),
|
||||
operationArguments.UseModalUi
|
||||
? new GitHubAuthentication.AcquireAuthenticationCodeDelegate(GitHub.Authentication.AuthenticationPrompts.AuthenticationCodeModalPrompt)
|
||||
: new GitHubAuthentication.AcquireAuthenticationCodeDelegate(GitHubAuthCodePrompt),
|
||||
githubCredentialCallback,
|
||||
githubAuthcodeCallback,
|
||||
null);
|
||||
|
||||
case AuthorityType.MicrosoftAccount:
|
||||
|
@ -445,6 +447,17 @@ namespace Microsoft.Alm.Cli
|
|||
|
||||
// return the allocated authority or a generic MSA backed VSTS authentication object
|
||||
return authority ?? new VstsMsaAuthentication(VstsCredentialScope, secrets);
|
||||
|
||||
case AuthorityType.Ntlm:
|
||||
// enforce NTLM authentication only
|
||||
basicNtlmSupport = NtlmSupport.Always;
|
||||
goto default;
|
||||
|
||||
default:
|
||||
Git.Trace.WriteLine($"authority for '{operationArguments.TargetUri}' is basic with NTLM={basicNtlmSupport}.");
|
||||
|
||||
// return a generic username + password authentication object
|
||||
return authority ?? new BasicAuthentication(secrets, basicNtlmSupport, basicCredentialCallback, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -963,7 +976,8 @@ namespace Microsoft.Alm.Cli
|
|||
Task.Run(async () =>
|
||||
{
|
||||
// attempt to get cached creds or acquire creds if interactivity is allowed
|
||||
if ((credentials = authentication.GetCredentials(operationArguments.TargetUri)) != null
|
||||
if ((operationArguments.Interactivity != Interactivity.Always
|
||||
&&(credentials = authentication.GetCredentials(operationArguments.TargetUri)) != null)
|
||||
|| (operationArguments.Interactivity != Interactivity.Never
|
||||
&& (credentials = await basicAuth.AcquireCredentials(operationArguments.TargetUri)) != null))
|
||||
{
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Microsoft.Alm.Authentication.Test
|
|||
{
|
||||
ICredentialStore credentialStore = new SecretCache(@namespace);
|
||||
|
||||
return new BasicAuthentication(credentialStore, null, null);
|
||||
return new BasicAuthentication(credentialStore, NtlmSupport.Auto, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,12 @@ namespace Microsoft.Alm.Authentication
|
|||
/// <param name="credentialStore">
|
||||
/// The <see cref="ICredentialStore"/> to delegate to.
|
||||
/// </param>
|
||||
/// <param name="ntlmSupport">
|
||||
/// <para>The level of NTLM support to be provided by this instance.</para>
|
||||
/// <para>If `<see cref="NtlmSupport.Always"/>` is used, the
|
||||
/// `<paramref name="acquireCredentialsCallback"/>` and `<paramref name="acquireResultCallback"/>`
|
||||
/// will be ignored by `<see cref="GetCredentials(TargetUri)"/>`.</para>
|
||||
/// </param>
|
||||
/// <param name="acquireCredentialsCallback">
|
||||
/// (optional) delegate for acquiring credentials.
|
||||
/// </param>
|
||||
|
@ -51,6 +57,7 @@ namespace Microsoft.Alm.Authentication
|
|||
/// </param>
|
||||
public BasicAuthentication(
|
||||
ICredentialStore credentialStore,
|
||||
NtlmSupport ntlmSupport,
|
||||
AcquireCredentialsDelegate acquireCredentialsCallback,
|
||||
AcquireResultDelegate acquireResultCallback)
|
||||
{
|
||||
|
@ -60,27 +67,34 @@ namespace Microsoft.Alm.Authentication
|
|||
_acquireCredentials = acquireCredentialsCallback;
|
||||
_acquireResult = acquireResultCallback;
|
||||
_credentialStore = credentialStore;
|
||||
_ntlmSupport = ntlmSupport;
|
||||
}
|
||||
|
||||
public BasicAuthentication(ICredentialStore credentialStore)
|
||||
: this(credentialStore, null, null)
|
||||
: this(credentialStore, NtlmSupport.Auto, null, null)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BasicAuthentication"/> object with an underlying credential store.
|
||||
/// Gets the underlying credential store for this instance of <see cref="BasicAuthentication"/>.
|
||||
/// </summary>
|
||||
/// <param name="credentialStore">
|
||||
/// The <see cref="ICredentialStore"/> to delegate to.
|
||||
/// </param>
|
||||
internal ICredentialStore CredentialStore
|
||||
{
|
||||
get { return _credentialStore; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the level of NTLM support for this instance of <see cref="BasicAuthentication"/>.
|
||||
/// </summary>
|
||||
public NtlmSupport NtlmSupport
|
||||
{
|
||||
get { return _ntlmSupport; }
|
||||
}
|
||||
|
||||
private readonly AcquireCredentialsDelegate _acquireCredentials;
|
||||
private readonly AcquireResultDelegate _acquireResult;
|
||||
private readonly ICredentialStore _credentialStore;
|
||||
private AuthenticationHeaderValue[] _httpAuthenticateOptions;
|
||||
private NtlmSupport _ntlmSupport;
|
||||
|
||||
/// <summary>
|
||||
/// Acquires credentials via the registered callbacks.
|
||||
|
@ -94,22 +108,26 @@ namespace Microsoft.Alm.Authentication
|
|||
{
|
||||
BaseSecureStore.ValidateTargetUri(targetUri);
|
||||
|
||||
// get the WWW-Authenticate headers (if any)
|
||||
if (_httpAuthenticateOptions == null)
|
||||
if (_ntlmSupport != NtlmSupport.Never)
|
||||
{
|
||||
_httpAuthenticateOptions = await WwwAuthenticateHelper.GetHeaderValues(targetUri);
|
||||
}
|
||||
// get the WWW-Authenticate headers (if any)
|
||||
if (_httpAuthenticateOptions == null)
|
||||
{
|
||||
_httpAuthenticateOptions = await WwwAuthenticateHelper.GetHeaderValues(targetUri);
|
||||
}
|
||||
|
||||
// if the headers contain NTML as an option, then fall back to NTLM
|
||||
if (_httpAuthenticateOptions.Any(x=> WwwAuthenticateHelper.IsNtlm(x)))
|
||||
{
|
||||
Git.Trace.WriteLine($"'{targetUri}' supports NTLM, sending NTLM credentials instead");
|
||||
// if the headers contain NTML as an option, then fall back to NTLM
|
||||
if (_httpAuthenticateOptions.Any(x => WwwAuthenticateHelper.IsNtlm(x)))
|
||||
{
|
||||
Git.Trace.WriteLine($"'{targetUri}' supports NTLM, sending NTLM credentials instead");
|
||||
|
||||
return NtlmCredentials;
|
||||
return NtlmCredentials;
|
||||
}
|
||||
}
|
||||
|
||||
Credential credentials = null;
|
||||
if (_acquireCredentials != null)
|
||||
|
||||
if (_ntlmSupport != NtlmSupport.Always && _acquireCredentials != null)
|
||||
{
|
||||
Git.Trace.WriteLine($"prompting user for credentials for '{targetUri}'.");
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<Compile Include="Global.cs" />
|
||||
<Compile Include="IGitHubAuthentication.cs" />
|
||||
<Compile Include="IGitHubAuthority.cs" />
|
||||
<Compile Include="NtlmSupport.cs" />
|
||||
<Compile Include="WwwAuthenticateHelper.cs" />
|
||||
<Compile Include="VstsLocationServiceException.cs" />
|
||||
<Compile Include="SecretCache.cs" />
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/**** Git Credential Manager for Windows ****
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the """"Software""""), to deal
|
||||
* in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
|
||||
**/
|
||||
|
||||
namespace Microsoft.Alm.Authentication
|
||||
{
|
||||
public enum NtlmSupport
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>The authentication class should attempt to detect and prefer
|
||||
/// NTML credentials over basic credentials.</para>
|
||||
/// <para>This is the default.</para>
|
||||
/// </summary>
|
||||
Auto,
|
||||
/// <summary>
|
||||
/// The authentication class should only detect and return NTML
|
||||
/// credentials.
|
||||
/// </summary>
|
||||
Never,
|
||||
/// <summary>
|
||||
/// The authentication class should never detect nor return
|
||||
/// NTML credentials.
|
||||
/// </summary>
|
||||
Always,
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче