Skip to content

Commit

Permalink
Fix for #1606 - use request authority is app authority is not set
Browse files Browse the repository at this point in the history
  • Loading branch information
bgavrilMS committed Feb 26, 2020
1 parent ffa7889 commit a27a7d1
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 12 deletions.
11 changes: 11 additions & 0 deletions src/client/Microsoft.Identity.Client/AppConfig/AuthorityInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,17 @@ internal static string CanonicalizeAuthorityUri(string uri)
return uri.ToLowerInvariant();
}

internal bool IsDefaultAuthority
{
get
{
return string.Equals(
CanonicalAuthority,
ClientApplicationBase.DefaultAuthority,
StringComparison.OrdinalIgnoreCase);
}
}

#endregion

private static void ValidateAuthorityUri(string authority)
Expand Down
29 changes: 29 additions & 0 deletions src/client/Microsoft.Identity.Client/Instance/Authority.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ protected Authority(AuthorityInfo authorityInfo)
/// 2. If there is a request authority, try to use it.
/// 2.1. If the request authority is not "common", then use it
/// 2.2 If the request authority is "common", ignore it, and use 1.1
///
/// Special cases:
///
/// - if the authority is not defined at the application level and the request level is not AAD, use the request authority
/// - if the authority is defined at app level, and the request level authority of is of different type, throw an exception
///
/// </summary>
public static Authority CreateAuthorityForRequest(
Expand All @@ -49,6 +54,8 @@ public static Authority CreateAuthorityForRequest(
throw new ArgumentNullException(nameof(configAuthorityInfo));
}

ValidateTypeMismatch(configAuthorityInfo, requestAuthorityInfo);

switch (configAuthorityInfo.AuthorityType)
{
// ADFS and B2C are tenantless, no need to consider tenant
Expand All @@ -73,6 +80,13 @@ public static Authority CreateAuthorityForRequest(
return CreateAuthorityWithTenant(configAuthorityInfo, requestHomeAccountTenantId);
}

// In case the authority is defined only at the request level
if (configAuthorityInfo.IsDefaultAuthority &&
requestAuthorityInfo.AuthorityType != AuthorityType.Aad)
{
return CreateAuthority(requestAuthorityInfo);
}

var requestAuthority = new AadAuthority(requestAuthorityInfo);
if (!requestAuthority.IsCommonOrganizationsOrConsumersTenant())
{
Expand All @@ -88,6 +102,21 @@ public static Authority CreateAuthorityForRequest(
}
}

private static void ValidateTypeMismatch(AuthorityInfo configAuthorityInfo, AuthorityInfo requestAuthorityInfo)
{
if (!configAuthorityInfo.IsDefaultAuthority &&
requestAuthorityInfo != null &&
configAuthorityInfo.AuthorityType != requestAuthorityInfo.AuthorityType)
{
throw new MsalClientException(
MsalError.AuthorityTypeMismatch,
MsalErrorMessage.AuthorityTypeMismatch(
configAuthorityInfo.AuthorityType,
requestAuthorityInfo.AuthorityType));
}
}


public static Authority CreateAuthority(string authority, bool validateAuthority = false)
{
return CreateAuthority(AuthorityInfo.FromAuthorityUri(authority, validateAuthority));
Expand Down
6 changes: 6 additions & 0 deletions src/client/Microsoft.Identity.Client/MsalError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,12 @@ public static class MsalError
/// </summary>
public const string InvalidJsonClaimsFormat = "invalid_json_claims_format";

/// <summary>
/// <para>What happens?</para>The authority configured at the application level is different than the authority configured at the request level
/// <para>Mitigation</para>Ensure the same authority type is used
/// </summary>
public const string AuthorityTypeMismatch = "authority_type_mismatch";

#if iOS
/// <summary>
/// Xamarin.iOS specific. This error indicates that keychain access has not be enabled for the application.
Expand Down
12 changes: 12 additions & 0 deletions src/client/Microsoft.Identity.Client/MsalErrorMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,18 @@ public static string RedirectUriMismatch(string expectedUri, string actualUri)
"You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. ";
public const string SSHCertUsedAsHttpHeader = "MSAL was configured to request SSH certificates from AAD, and these cannot be used as an HTTP authentication header. Developers are responsible for transporting the SSH certificates to the target machines.";
public const string BrokerApplicationRequired = "Installation of broker failed. The broker application must be installed to continue authentication";
public static string AuthorityTypeMismatch(
AuthorityType appAuthorityType,
AuthorityType requestAuthorityType)
{
return string.Format(
CultureInfo.InvariantCulture,
"A authority of type {0} was used at the application and of type {1} at the request level. " +
"Please use the same authority type between the two.",
appAuthorityType,
requestAuthorityType);
}

public const string NoAndroidBrokerAccountFound = "Android account manager could not find an account that matched the provided account information.";
public static string ExperimentalFeature(string methodName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,88 @@

using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Instance;
using Microsoft.Identity.Test.Common.Core.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.Identity.Test.Unit.ApiConfigTests
{
[TestClass]
public class AuthorityTests
{
private static readonly AuthorityInfo s_commonAuthority =
AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityCommonTenant, true);
private static readonly AuthorityInfo s_utidAuthority =
AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityUtidTenant, true);
private static readonly AuthorityInfo s_utid2Authority =
AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityUtid2Tenant, true);
private static readonly AuthorityInfo s_b2cAuthority =
AuthorityInfo.FromAuthorityUri(TestConstants.B2CAuthority, true);

[TestMethod]
public void VerifyAuthorityTest()
{
var commonAuthority = AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityCommonTenant, true);
var utidAuthority = AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityUtidTenant, true);
var utid2Authority = AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityUtid2Tenant, true);
var utid = TestConstants.Utid;
var utid2 = TestConstants.Utid2;

VerifyAuthority(
config: commonAuthority,
config: s_commonAuthority,
request: null,
accountTid: null,
resultTid: "common");

VerifyAuthority(
config: commonAuthority,
request: commonAuthority,
config: s_commonAuthority,
request: s_commonAuthority,
accountTid: null,
resultTid: "common");

VerifyAuthority(
config: commonAuthority,
request: commonAuthority,
config: s_commonAuthority,
request: s_commonAuthority,
accountTid: utid,
resultTid: utid);

VerifyAuthority(
config: commonAuthority,
request: utidAuthority,
config: s_commonAuthority,
request: s_utidAuthority,
accountTid: null,
resultTid: utid);

VerifyAuthority(
config: commonAuthority,
request: utid2Authority,
config: s_commonAuthority,
request: s_utid2Authority,
accountTid: utid,
resultTid: utid2);
}

[TestMethod]
public void AuthorityMismatchTest()
{
var ex = AssertException.Throws<MsalClientException>(() =>
Authority.CreateAuthorityForRequest(s_utidAuthority, s_b2cAuthority, null));

Assert.AreEqual(MsalError.AuthorityTypeMismatch, ex.ErrorCode);
}

[TestMethod]
// Regression https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1606
public void DefaultAuthorityDifferentTypeTest()
{
Authority result = Authority.CreateAuthorityForRequest(s_commonAuthority, s_b2cAuthority, null);
Assert.AreEqual(s_b2cAuthority.CanonicalAuthority, result.AuthorityInfo.CanonicalAuthority);
}

[TestMethod]
public void IsDefaultAuthorityTest()
{
Assert.IsTrue(
Authority.CreateAuthority(ClientApplicationBase.DefaultAuthority)
.AuthorityInfo.IsDefaultAuthority);

Assert.IsFalse(s_utidAuthority.IsDefaultAuthority);
Assert.IsFalse(s_b2cAuthority.IsDefaultAuthority);
}

private static void VerifyAuthority(
AuthorityInfo config,
AuthorityInfo request,
Expand Down

0 comments on commit a27a7d1

Please sign in to comment.