Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added all claims to Get-AzToken output token type as Claims property #44

Merged
merged 2 commits into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Source/AzAuth.Core/CacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,17 @@ internal static async Task<AzToken> GetTokenInteractiveAsync(

var result = await tokenBuilder.ExecuteAsync(cancellationToken);

var resultClaims = new ClaimsDictionary();
foreach (var claim in result.ClaimsPrincipal.Claims)
{
resultClaims.Add(claim.Type, claim.Value);
}

return new AzToken(
result.AccessToken,
result.Scopes.ToArray(),
result.ExpiresOn,
resultClaims,
result.Account.Username ?? result.Account.HomeAccountId.ObjectId,
result.TenantId
);
Expand Down Expand Up @@ -117,10 +124,17 @@ internal static async Task<AzToken> GetTokenDeviceCodeAsync(

var result = await tokenBuilder.ExecuteAsync(cancellationToken);

var resultClaims = new ClaimsDictionary();
foreach (var claim in result.ClaimsPrincipal.Claims)
{
resultClaims.Add(claim.Type, claim.Value);
}

return new AzToken(
result.AccessToken,
result.Scopes.ToArray(),
result.ExpiresOn,
resultClaims,
result.Account.Username ?? result.Account.HomeAccountId.ObjectId,
result.TenantId
);
Expand Down Expand Up @@ -152,10 +166,17 @@ internal static async Task<AzToken> GetTokenFromCacheSilentAsync(

var result = await tokenBuilder.ExecuteAsync(cancellationToken);

var resultClaims = new ClaimsDictionary();
foreach (var claim in result.ClaimsPrincipal.Claims)
{
resultClaims.Add(claim.Type, claim.Value);
}

return new AzToken(
result.AccessToken,
result.Scopes.ToArray(),
result.ExpiresOn,
resultClaims,
result.Account.Username ?? result.Account.HomeAccountId.ObjectId,
result.TenantId
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ public class AzToken
public string? Identity { get; }
public string? TenantId { get; }
public string[] Scopes { get; }
public ClaimsDictionary Claims { get; }

public AzToken(string token, string[] scopes, DateTimeOffset expiresOn, string? identity = null, string? tenantId = null)
public AzToken(string token, string[] scopes, DateTimeOffset expiresOn, ClaimsDictionary claims, string? identity = null, string? tenantId = null)
{
Token = token;
Identity = identity;
TenantId = tenantId;
Scopes = scopes;
ExpiresOn = expiresOn;
Claims = claims;
}

public override string ToString()
{
return Token;
}
public override string ToString() => Token;
}
28 changes: 28 additions & 0 deletions Source/AzAuth.Core/Models/ClaimList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Collections;

namespace PipeHow.AzAuth;

public class ClaimList : IReadOnlyList<string>
{
private List<string> _list;

public ClaimList() => _list = new List<string>();

public string this[int index] => _list[index];

public int Count => _list.Count;

public IEnumerator<string> GetEnumerator() => _list.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();

public void Add(string claim)
{
_list.Add(claim);
}

public override string ToString()
{
return string.Join(", ", _list);
}
}
44 changes: 44 additions & 0 deletions Source/AzAuth.Core/Models/ClaimsDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System.Collections;

namespace PipeHow.AzAuth;

// Custom dictionary to index claims which are key value pairs with one or more strings as values
public class ClaimsDictionary : IReadOnlyDictionary<string, ClaimList?>
{
private readonly Dictionary<string, ClaimList> _dictionary;

public ClaimsDictionary() => _dictionary = new Dictionary<string, ClaimList>();

public ClaimList? this[string key] => _dictionary.ContainsKey(key) ? _dictionary[key] : null;

public IEnumerable<string> Keys => _dictionary.Keys;

public IEnumerable<ClaimList> Values => _dictionary.Values;

public int Count => _dictionary.Count;

public bool ContainsKey(string key) => _dictionary.ContainsKey(key);

public bool TryGetValue(string key, out ClaimList value) => _dictionary.TryGetValue(key, out value);

public IEnumerator<KeyValuePair<string, ClaimList?>> GetEnumerator() => _dictionary.GetEnumerator();

IEnumerator IEnumerable.GetEnumerator() => _dictionary.GetEnumerator();

public void Add(string key, string value)
{
if (_dictionary.ContainsKey(key))
{
_dictionary[key].Add(value);
}
else
{
_dictionary[key] = new ClaimList { value };
}
}

public override string ToString()
{
return string.Join(", ", _dictionary.Select(kvp => $"[{kvp.Key}: {string.Join(", ", kvp.Value ?? Enumerable.Empty<string>())}]"));
}
}
8 changes: 8 additions & 0 deletions Source/AzAuth.Core/TokenManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,25 @@ internal static async Task<AzToken> GetTokenAsync(TokenRequestContext tokenReque
// Parse token to get info from claims
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadJwtToken(token.Token);

// Get upn of user if available, or email if personal account, otherwise object id of identity used (such as managed identity)
var identity = (jsonToken.Claims.FirstOrDefault(c => c.Type == "upn") ??
jsonToken.Claims.FirstOrDefault(c => c.Type == "email") ??
jsonToken.Claims.FirstOrDefault(c => c.Type == "oid"))?.Value;
var tenantId = jsonToken.Claims.FirstOrDefault(c => c.Type == "tid");
var scopes = jsonToken.Claims.FirstOrDefault(c => c.Type == "scp");

var claims = new ClaimsDictionary();
foreach (var claim in jsonToken.Claims)
{
claims.Add(claim.Type, claim.Value);
}

return new AzToken(
token.Token,
scopes?.Value.Split(' ') ?? tokenRequestContext.Scopes,
token.ExpiresOn,
claims,
identity,
tenantId?.Value ?? tokenRequestContext.TenantId
);
Expand Down
2 changes: 1 addition & 1 deletion Source/AzAuth.PS/Manifest/AzAuth.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
RootModule = 'AzAuth.PS.dll'

# Version number of this module.
ModuleVersion = '2.2.6'
ModuleVersion = '2.2.7'

# Supported PSEditions
CompatiblePSEditions = 'Core'
Expand Down
Loading