Skip to content

Commit

Permalink
Merge pull request #373 from microsoft/users/johsch/preview-release
Browse files Browse the repository at this point in the history
Promote 1.0.2-preview release to 1.0.2 release
  • Loading branch information
JohnSchmeichel committed Mar 28, 2023
2 parents 38b9fe3 + d61dbd8 commit c2bc059
Show file tree
Hide file tree
Showing 28 changed files with 565 additions and 142 deletions.
10 changes: 7 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ __pycache__/
# OpenCover UI analysis results
OpenCover/

# Azure Stream Analytics local run output
# Azure Stream Analytics local run output
ASALocalRun/

# MSBuild Binary and Structured Log
Expand All @@ -326,7 +326,11 @@ ASALocalRun/
# NVidia Nsight GPU debugger configuration file
*.nvuser

# MFractors (Xamarin productivity tool) working folder
# MFractors (Xamarin productivity tool) working folder
.mfractor/

.vscode
.vscode

# MicroBuild build output
MicroBuild
keys
3 changes: 2 additions & 1 deletion Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CredentialProviderVersion>1.0.1</CredentialProviderVersion>
<CredentialProviderVersion>1.0.2</CredentialProviderVersion>
<VersionSuffix></VersionSuffix>
<TargetFrameworks>netcoreapp3.1;net461;net6.0</TargetFrameworks>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright (c) Microsoft. All rights reserved.
//
// Licensed under the MIT license.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Identity.Client;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NuGetCredentialProvider.CredentialProviders.Vsts;

namespace CredentialProvider.Microsoft.Tests.CredentialProviders.Vsts
{
[TestClass]
public class AccountPriorityTests
{
private class TestAccount : IAccount
{
public string Username {get; set;}
public string Environment {get; set;}
public AccountId HomeAccountId {get; set;}
}

private static readonly Guid ContosoTenant = Guid.NewGuid();
private static readonly Guid FabrikamTenant = Guid.NewGuid();

private static readonly IAccount FabrikamUser = new TestAccount
{
Username = "billg@fabrikam.com",
Environment = string.Empty,
HomeAccountId = new AccountId(string.Empty, string.Empty, FabrikamTenant.ToString()),
};

private static readonly IAccount ContosoUser = new TestAccount
{
Username = "billg@contoso.com",
Environment = string.Empty,
HomeAccountId = new AccountId(string.Empty, string.Empty, ContosoTenant.ToString()),
};

private static readonly IAccount MsaUser = new TestAccount
{
Username = "bill.gates@live.com",
Environment = string.Empty,
HomeAccountId = new AccountId(string.Empty, string.Empty, AuthUtil.MsaAccountTenant.ToString()),
};

private static readonly List<List<IAccount>> Permutations = new List<List<IAccount>>()
{
new List<IAccount> { ContosoUser, MsaUser, FabrikamUser },
new List<IAccount> { ContosoUser, FabrikamUser, MsaUser },
new List<IAccount> { MsaUser, ContosoUser, FabrikamUser },
new List<IAccount> { MsaUser, FabrikamUser, ContosoUser },
new List<IAccount> { FabrikamUser, MsaUser, ContosoUser },
new List<IAccount> { FabrikamUser, ContosoUser, MsaUser },
};

[TestMethod]
public void MsaMatchesMsa()
{
foreach (var accounts in Permutations)
{
var applicable = MsalUtil.GetApplicableAccounts(accounts, AuthUtil.FirstPartyTenant, loginHint: null);
Assert.AreEqual(applicable[0].Item1.Username, MsaUser.Username);
}
}

[TestMethod]
public void ContosoMatchesContoso()
{
foreach (var accounts in Permutations)
{
var applicable = MsalUtil.GetApplicableAccounts(accounts, ContosoTenant, loginHint: null);
Assert.AreEqual(applicable[0].Item1.Username, ContosoUser.Username);
}
}

[TestMethod]
public void FabrikamMatchesFabrikam()
{
foreach (var accounts in Permutations)
{
var applicable = MsalUtil.GetApplicableAccounts(accounts, FabrikamTenant, loginHint: null);
Assert.AreEqual(applicable[0].Item1.Username, FabrikamUser.Username);
}
}

[TestMethod]
public void LoginHintOverride()
{
foreach (var accounts in Permutations)
{
foreach (var tenantId in Permutations[0].Select(a => Guid.Parse(a.HomeAccountId.TenantId)))
{
foreach (var loginHint in Permutations[0].Select(a => a.Username))
{
var applicable = MsalUtil.GetApplicableAccounts(accounts, tenantId, loginHint);
Assert.AreEqual(applicable[0].Item1.Username, loginHint);
}
}
}
}

[TestMethod]
public void UnknownAuthorityTenantPrefersMsa()
{
foreach (var accounts in Permutations)
{
var applicable = MsalUtil.GetApplicableAccounts(accounts, Guid.Empty, loginHint: null);
Assert.AreEqual(applicable[0].Item1.Username, MsaUser.Username);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ public async Task MsalGetAadAuthorityUri_WithoutAuthenticateHeadersAndPpeAndPpeO
foreach (var ppeUri in ppeUris)
{
var authorityUri = await authUtil.GetAadAuthorityUriAsync(ppeUri, cancellationToken);
authorityUri.Should().Be(new Uri("https://login.windows-ppe.net/organizations"));
authorityUri.Should().Be(new Uri("https://login.windows-ppe.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a"));
}
}

Expand All @@ -227,7 +227,7 @@ public async Task MsaltAadAuthorityUri_WithoutAuthenticateHeaders_ReturnsCorrect

var authorityUri = await authUtil.GetAadAuthorityUriAsync(requestUri, cancellationToken);

authorityUri.Should().Be(organizationsAuthority);
authorityUri.Should().Be(new Uri("https://login.microsoftonline.com/f8cdef31-a31e-4b4a-93e4-5f571e91255a"));
}


Expand All @@ -250,7 +250,7 @@ public async Task MsalGetAadAuthorityUri_WithoutAuthenticateHeadersAndPpe_Return

var authorityUri = await authUtil.GetAadAuthorityUriAsync(requestUri, cancellationToken);

authorityUri.Should().Be(new Uri("https://login.windows-ppe.net/organizations"));
authorityUri.Should().Be(new Uri("https://login.windows-ppe.net/f8cdef31-a31e-4b4a-93e4-5f571e91255a"));
}

private void MockResponseHeaders(string key, string value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class VstsCredentialProviderTests

private VstsCredentialProvider vstsCredentialProvider;
private IDisposable environmentLock;

[TestInitialize]
public void TestInitialize()
{
Expand All @@ -44,7 +44,7 @@ public void TestInitialize()
mockBearerTokenProvider2.Setup(x => x.ShouldRun(It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<bool>())).Returns(true);
mockBearerTokenProvider2.Setup(x => x.GetTokenAsync(It.IsAny<Uri>(), It.IsAny<CancellationToken>())).ReturnsAsync((string)null);
mockBearerTokenProvidersFactory = new Mock<IBearerTokenProvidersFactory>();
mockBearerTokenProvidersFactory.Setup(x => x.Get(It.IsAny<string>())).Returns(new[] { mockBearerTokenProvider1.Object, mockBearerTokenProvider2.Object });
mockBearerTokenProvidersFactory.Setup(x => x.Get(It.IsAny<Uri>())).Returns(new[] { mockBearerTokenProvider1.Object, mockBearerTokenProvider2.Object });

mockVstsSessionTokenFromBearerTokenProvider = new Mock<IAzureDevOpsSessionTokenFromBearerTokenProvider>();
mockVstsSessionTokenFromBearerTokenProvider.Setup(x => x.GetAzureDevOpsSessionTokenFromBearerToken(It.IsAny<GetAuthenticationCredentialsRequest>(), It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\Credenti
file source=$(PluginBinPath)\CredentialProvider.Microsoft.exe
file source=$(PluginBinPath)\CredentialProvider.Microsoft.exe.config
file source=$(PluginBinPath)\CredentialProvider.Microsoft.pdb
file source=$(PluginBinPath)\Microsoft.Identity.Client.Broker.dll
file source=$(PluginBinPath)\Microsoft.Identity.Client.dll
file source=$(PluginBinPath)\Microsoft.Identity.Client.Extensions.Msal.dll
file source=$(PluginBinPath)\Microsoft.Identity.Client.NativeInterop.dll
file source=$(PluginBinPath)\Microsoft.IdentityModel.Abstractions.dll
file source=$(PluginBinPath)\Microsoft.IdentityModel.Clients.ActiveDirectory.dll
file source=$(PluginBinPath)\Microsoft.Win32.Primitives.dll
Expand Down Expand Up @@ -92,8 +94,8 @@ folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\Credenti
file source=$(PluginBinPath)\System.Runtime.Serialization.Xml.dll
file source=$(PluginBinPath)\System.Security.Claims.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Algorithms.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Csp.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Cng.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Csp.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Encoding.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Pkcs.dll
file source=$(PluginBinPath)\System.Security.Cryptography.Primitives.dll
Expand All @@ -117,3 +119,12 @@ folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\Credenti
file source=$(PluginBinPath)\System.Xml.XmlSerializer.dll
file source=$(PluginBinPath)\System.Xml.XPath.dll
file source=$(PluginBinPath)\System.Xml.XPath.XDocument.dll

folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\CredentialProvider.Microsoft\runtimes\win-arm64\native
file source=$(PluginBinPath)\runtimes\win-arm64\native\msalruntime_arm64.dll

folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\CredentialProvider.Microsoft\runtimes\win-x64\native
file source=$(PluginBinPath)\runtimes\win-x64\native\msalruntime.dll

folder InstallDir:\Common7\IDE\CommonExtensions\Microsoft\NuGet\Plugins\CredentialProvider.Microsoft\runtimes\win-x86\native
file source=$(PluginBinPath)\runtimes\win-x86\native\msalruntime_x86.dll
14 changes: 8 additions & 6 deletions CredentialProvider.Microsoft/CredentialProvider.Microsoft.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), Build.props))\Build.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -17,19 +17,21 @@

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DebugType>portable</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>$(DefineConstants);DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Identity.Client" Version="4.46.2" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="2.18.5" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.50.0" />
<PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.50.0-preview"/>
<PackageReference Include="Microsoft.Identity.Client.NativeInterop" Version="0.13.5"/>
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="2.26.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.9" />
<PackageReference Include="NuGet.Protocol" Version="5.11.3" />
<PackageReference Include="PowerArgs" Version="3.6.0" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public class AdalTokenProvider : IAdalTokenProvider
private readonly string clientId;
private readonly TokenCache tokenCache;

internal AdalTokenProvider(string authority, string resource, string clientId, TokenCache tokenCache)
internal AdalTokenProvider(Uri authority, string resource, string clientId, TokenCache tokenCache)
{
this.authority = authority;
this.authority = authority.ToString();
this.resource = resource;
this.clientId = clientId;
this.tokenCache = tokenCache;
Expand Down Expand Up @@ -74,11 +74,11 @@ public async Task<IAdalToken> AcquireTokenSilentlyAsync(CancellationToken cancel
{
return null;
}
}

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async Task<IAdalToken> AcquireTokenWithUI(CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
}

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async Task<IAdalToken> AcquireTokenWithUI(CancellationToken cancellationToken)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
#if NETFRAMEWORK
var authenticationContext = new AuthenticationContext(authority, tokenCache);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// Licensed under the MIT license.

using System;
using System.Collections.Generic;
using NuGetCredentialProvider.Logging;

Expand All @@ -18,7 +19,7 @@ public BearerTokenProvidersFactory(ILogger logger, IAdalTokenProviderFactory ada
this.logger = logger;
}

public IEnumerable<IBearerTokenProvider> Get(string authority)
public IEnumerable<IBearerTokenProvider> Get(Uri authority)
{
IAdalTokenProvider adalTokenProvider = adalTokenProviderFactory.Get(authority);
return new IBearerTokenProvider[]
Expand All @@ -31,4 +32,4 @@ public IEnumerable<IBearerTokenProvider> Get(string authority)
};
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
//
// Licensed under the MIT license.

using System;

namespace NuGetCredentialProvider.CredentialProviders.Vsts
{
public interface IAdalTokenProviderFactory
{
IAdalTokenProvider Get(string authority);
IAdalTokenProvider Get(Uri authority);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ public class AuthUtil : IAuthUtil
{
public const string VssResourceTenant = "X-VSS-ResourceTenant";
public const string VssAuthorizationEndpoint = "X-VSS-AuthorizationEndpoint";
private const string OrganizationsTenant = "organizations";
private const string CommonTenant = "common";
public static readonly Guid FirstPartyTenant = Guid.Parse("f8cdef31-a31e-4b4a-93e4-5f571e91255a");
public static readonly Guid MsaAccountTenant = Guid.Parse("9188040d-6c67-4c5b-b112-36a304b66dad");
public const string VssE2EID = "X-VSS-E2EID";

private readonly ILogger logger;

public AuthUtil(ILogger logger)
Expand All @@ -54,7 +55,7 @@ public async Task<Uri> GetAadAuthorityUriAsync(Uri uri, CancellationToken cancel

var headers = await GetResponseHeadersAsync(uri, cancellationToken);
var bearerHeaders = headers.WwwAuthenticate.Where(x => x.Scheme.Equals("Bearer", StringComparison.Ordinal));

foreach (var param in bearerHeaders)
{
if (param.Parameter == null)
Expand All @@ -81,7 +82,10 @@ public async Task<Uri> GetAadAuthorityUriAsync(Uri uri, CancellationToken cancel
var aadBase = UsePpeAadUrl(uri) ? "https://login.windows-ppe.net" : "https://login.microsoftonline.com";
logger.Verbose(string.Format(Resources.AADAuthorityNotFound, aadBase));

var tenant = EnvUtil.MsalEnabled() ? OrganizationsTenant: CommonTenant;
// WAM gets confused about the Common tenant, so we'll just assume that if there isn't
// a tenant GUID provided, that it's a consumer tenant.
var tenant = EnvUtil.MsalEnabled() ? FirstPartyTenant.ToString() : CommonTenant;

return new Uri($"{aadBase}/{tenant}");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
//
// Licensed under the MIT license.

using System;
using System.Collections.Generic;

namespace NuGetCredentialProvider.CredentialProviders.Vsts
{
public interface IBearerTokenProvidersFactory
{
IEnumerable<IBearerTokenProvider> Get(string authority);
IEnumerable<IBearerTokenProvider> Get(Uri authority);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ internal interface IMsalTokenProvider
Task<IMsalToken> AcquireTokenWithWindowsIntegratedAuth(CancellationToken cancellationToken);

ILogger Logger {get;}

string NameSuffix {get;}
}

internal interface IMsalToken
Expand Down

0 comments on commit c2bc059

Please sign in to comment.