Skip to content

Commit

Permalink
use clientinfo endpoint to determine home object id and home tenant i… (
Browse files Browse the repository at this point in the history
#177)

* use clientinfo endpoint to determine home object id and home tenant id for guest scenarios

* Update src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>

* Update src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>

* Update src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>

* Update src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>

* Update src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>

Co-authored-by: pmaytak <34331512+pmaytak@users.noreply.github.com>
  • Loading branch information
jennyf19 and pmaytak authored May 27, 2020
1 parent dbb91d6 commit 448ce07
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 96 deletions.
11 changes: 9 additions & 2 deletions src/Microsoft.Identity.Web/ClaimConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,16 @@ public static class ClaimConstants
public const string ClientInfo = "client_info";

/// <summary>
/// UniqueObjectIdentifier: "utid".
/// UniqueObjectIdentifier: "uid".
/// Home Object Id.
/// </summary>
public const string UniqueObjectIdentifier = "utid";
public const string UniqueObjectIdentifier = "uid";

/// <summary>
/// UniqueTenantIdentifier: "utid".
/// Home Tenant Id.
/// </summary>
public const string UniqueTenantIdentifier = "utid";

/// <summary>
/// Older scope claim: "http://schemas.microsoft.com/identity/claims/scope".
Expand Down
53 changes: 40 additions & 13 deletions src/Microsoft.Identity.Web/ClaimsPrincipalExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,19 @@ public static class ClaimsPrincipalExtensions
/// <returns>A string corresponding to an account identifier as defined in <see cref="Microsoft.Identity.Client.AccountId.Identifier"/>.</returns>
public static string GetMsalAccountId(this ClaimsPrincipal claimsPrincipal)
{
string userObjectId = claimsPrincipal.GetObjectId();
string nameIdentifierId = claimsPrincipal.GetNameIdentifierId();

This comment has been minimized.

Copy link
@felickz

felickz Jun 3, 2020

this old code led me to this issue: #171

string tenantId = claimsPrincipal.GetTenantId();
string userFlowId = claimsPrincipal.GetUserFlowId();

if (!string.IsNullOrWhiteSpace(nameIdentifierId) &&
!string.IsNullOrWhiteSpace(tenantId) &&
!string.IsNullOrWhiteSpace(userFlowId))
if (claimsPrincipal == null)
{
// B2C pattern: {oid}-{userFlow}.{tid}
return $"{nameIdentifierId}.{tenantId}";
throw new ArgumentNullException(nameof(claimsPrincipal));
}
else if (!string.IsNullOrWhiteSpace(userObjectId) && !string.IsNullOrWhiteSpace(tenantId))

string uniqueObjectIdentifier = claimsPrincipal.GetHomeObjectId();
string uniqueTenantIdentifier = claimsPrincipal.GetHomeTenantId();

if (!string.IsNullOrWhiteSpace(uniqueObjectIdentifier) && !string.IsNullOrWhiteSpace(uniqueTenantIdentifier))
{
// AAD pattern: {oid}.{tid}
return $"{userObjectId}.{tenantId}";
// AAD pattern: {uid}.{utid}
// B2C pattern: {uid}-{userFlow}.{utid} -> userflow is included in the uid for B2C
return $"{uniqueObjectIdentifier}.{uniqueTenantIdentifier}";
}

return null;
Expand Down Expand Up @@ -146,6 +143,36 @@ public static string GetUserFlowId(this ClaimsPrincipal claimsPrincipal)
return userFlowId;
}

/// <summary>
/// Gets the Home Object ID associated with the <see cref="ClaimsPrincipal"/>.
/// </summary>
/// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/> from which to retrieve the sub claim.</param>
/// <returns>Home Object ID (sub) of the identity, or <c>null</c> if it cannot be found.</returns>
public static string GetHomeObjectId(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal == null)
{
throw new ArgumentNullException(nameof(claimsPrincipal));
}

return claimsPrincipal.FindFirstValue(ClaimConstants.UniqueObjectIdentifier);
}

/// <summary>
/// Gets the Home Tenant ID associated with the <see cref="ClaimsPrincipal"/>.
/// </summary>
/// <param name="claimsPrincipal">The <see cref="ClaimsPrincipal"/> from which to retrieve the sub claim.</param>
/// <returns>Home Tenant ID (sub) of the identity, or <c>null</c> if it cannot be found.</returns>
public static string GetHomeTenantId(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal == null)
{
throw new ArgumentNullException(nameof(claimsPrincipal));
}

return claimsPrincipal.FindFirstValue(ClaimConstants.UniqueTenantIdentifier);
}

/// <summary>
/// Gets the NameIdentifierId associated with the <see cref="ClaimsPrincipal"/>.
/// </summary>
Expand Down
10 changes: 2 additions & 8 deletions src/Microsoft.Identity.Web/TokenAcquisition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,14 +302,8 @@ public async Task RemoveAccountAsync(RedirectContext context)
}
else
{
account = await app.GetAccountAsync(context.HttpContext.User.GetMsalAccountId()).ConfigureAwait(false);

// Workaround for the guest account
if (account == null)
{
var accounts = await app.GetAccountsAsync().ConfigureAwait(false);
account = accounts.FirstOrDefault(a => a.Username == user.GetLoginHint());
}
string identifier = context.HttpContext.User.GetMsalAccountId();
account = await app.GetAccountAsync(identifier).ConfigureAwait(false);

if (account != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
Expand Down Expand Up @@ -130,6 +129,8 @@ public static AuthenticationBuilder AddSignIn(
context.Properties.Parameters.Remove(OpenIdConnectParameterNames.DomainHint);
}

context.ProtocolMessage.SetParameter("client_info", "1");

// Additional claims
if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims))
{
Expand All @@ -140,8 +141,6 @@ public static AuthenticationBuilder AddSignIn(

if (microsoftIdentityOptions.IsB2C)
{
context.ProtocolMessage.SetParameter("client_info", "1");

// When a new Challenge is returned using any B2C user flow different than susi, we must change
// the ProtocolMessage.IssuerAddress to the desired user flow otherwise the redirect would use the susi user flow
await b2cOidcHandlers.OnRedirectToIdentityProvider(context).ConfigureAwait(false);
Expand Down
21 changes: 9 additions & 12 deletions src/Microsoft.Identity.Web/WebAppServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,22 +207,19 @@ public static IServiceCollection AddWebAppCallsProtectedWebApi(
var onTokenValidatedHandler = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
if (!context.Principal.HasClaim(c => c.Type == ClaimConstants.Tid || c.Type == ClaimConstants.TenantId))
ClientInfo clientInfoFromServer;
if (context.Request.Form.ContainsKey(ClaimConstants.ClientInfo))
{
ClientInfo clientInfoFromServer;
if (context.Request.Form.ContainsKey(ClaimConstants.ClientInfo))
context.Request.Form.TryGetValue(ClaimConstants.ClientInfo, out Microsoft.Extensions.Primitives.StringValues value);

if (!string.IsNullOrEmpty(value))
{
context.Request.Form.TryGetValue(ClaimConstants.ClientInfo, out Microsoft.Extensions.Primitives.StringValues value);
clientInfoFromServer = ClientInfo.CreateFromJson(value);

if (!string.IsNullOrEmpty(value))
if (clientInfoFromServer != null)
{
clientInfoFromServer = ClientInfo.CreateFromJson(value);

if (clientInfoFromServer != null)
{
context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.Tid, clientInfoFromServer.UniqueTenantIdentifier));
context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier));
}
context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.UniqueTenantIdentifier, clientInfoFromServer.UniqueTenantIdentifier));
context.Principal.Identities.FirstOrDefault().AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier));
}
}
}
Expand Down
14 changes: 10 additions & 4 deletions tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@ public static class TestConstants
public const string ApiAudience = "api://" + ApiClientId;
public const string ApiClientId = "1EE5A092-0DFD-42B6-88E5-C517C0141321";

public const string UserOne = "User One";
public const string UserTwo = "User Two";

public const string ClientId = "87f0ee88-8251-48b3-8825-e0c9563f5234";
public const string TenantId = "some-tenant-id";
public const string TenantId = "guest-tenant-id";
public const string TenantIdAsGuid = "da41245a5-11b3-996c-00a8-4d99re19f292";
public const string ObjectIdAsGuid = "6364bb70-9521-3fa8-989d-c2c19ff90223";
public const string Domain = "contoso.onmicrosoft.com";
public const string Uid = "my-uid";
public const string Utid = "my-utid";
public const string Uid = "my-home-object-id";
public const string Oid = "my-guest-object-id";
public const string Utid = "my-home-tenant-id";
public const string LoginHint = "login_hint";
public const string DomainHint = "domain_hint";
public const string Claims = "additional_claims";
public const string PreferredUsername = "preferred_username";

public const string AadInstance = "https://login.microsoftonline.com";
public const string AuthorityCommonTenant = AadInstance + "/common/";
Expand Down Expand Up @@ -99,4 +105,4 @@ public static class TestConstants
y1NFZmB24rMoq8C+HPOpuVLzkwBr+qcCq7ry2326auogvVMGaxhHlwSLR4Q1OhRjKs8JctCk2+5Qs1NHfawa7jWHxdAK6cLm7Rv/c0ig2Jow7wRaI5ciAcEjX7
m1t9gRT1mNeeluL4cZa6WyVXqXc6U2wfR5DY6GOMUubN5Nr1n8Czew8TPfab4OG37BuEMNmBpqoRrRgFnDzVtItOnhuFTa0=";
}
}
}
Loading

0 comments on commit 448ce07

Please sign in to comment.