1
0
Форкнуть 0

Merge pull request #329 from whoisj/improve-basic-authentication

Improve basic authentication support.
This commit is contained in:
J Wyman 2016-12-12 09:53:54 -05:00 коммит произвёл GitHub
Родитель 7f48135363 436fec2914
Коммит 8889c3d75a
5 изменённых файлов: 119 добавлений и 39 удалений

Просмотреть файл

@ -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,
}
}