forked from Azure/azure-sdk-for-net
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Identity] User authentication API for applications (Azure#11285)
* updates for interactive browser authentication * adding authenticate methods to DeviceCodeCredential * adding AuthenticationProfile to options classes * updating api definition * incorperate arch board feedback * updating identity to use msal extensions * adding token cache storage values for Mac and Linux * missed AuthenticationRecord rename * adding tests * adding test recordings * address pr feedback * update api listing * updating changelog * updating changelog * address pr feedback
- Loading branch information
Showing
42 changed files
with
1,691 additions
and
662 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using Microsoft.Identity.Client; | ||
|
||
namespace Azure.Identity | ||
{ internal class AuthenticationAccount : IAccount | ||
{ | ||
private AuthenticationRecord _profile; | ||
|
||
internal AuthenticationAccount(AuthenticationRecord profile) | ||
{ | ||
_profile = profile; | ||
} | ||
|
||
string IAccount.Username => _profile.Username; | ||
|
||
string IAccount.Environment => _profile.Authority; | ||
|
||
AccountId IAccount.HomeAccountId => _profile.AccountId; | ||
|
||
public static explicit operator AuthenticationAccount(AuthenticationRecord profile) => new AuthenticationAccount(profile); | ||
public static explicit operator AuthenticationRecord(AuthenticationAccount account) => account._profile; | ||
} | ||
} |
179 changes: 179 additions & 0 deletions
179
sdk/identity/Azure.Identity/src/AuthenticationRecord.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text.Json; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Azure.Core.Pipeline; | ||
using Microsoft.Identity.Client; | ||
|
||
namespace Azure.Identity | ||
{ | ||
/// <summary> | ||
/// Account information relating to an authentication request. | ||
/// </summary> | ||
public class AuthenticationRecord | ||
{ | ||
private const string UsernamePropertyName = "username"; | ||
private const string AuthorityPropertyName = "authority"; | ||
private const string HomeAccountIdPropertyName = "homeAccountId"; | ||
private const string TenantIdPropertyName = "tenantId"; | ||
|
||
private static readonly JsonEncodedText s_usernamePropertyNameBytes = JsonEncodedText.Encode(UsernamePropertyName); | ||
private static readonly JsonEncodedText s_authorityPropertyNameBytes = JsonEncodedText.Encode(AuthorityPropertyName); | ||
private static readonly JsonEncodedText s_homeAccountIdPropertyNameBytes = JsonEncodedText.Encode(HomeAccountIdPropertyName); | ||
private static readonly JsonEncodedText s_tenantIdPropertyNameBytes = JsonEncodedText.Encode(TenantIdPropertyName); | ||
|
||
internal AuthenticationRecord() | ||
{ | ||
|
||
} | ||
|
||
internal AuthenticationRecord(AuthenticationResult authResult) | ||
{ | ||
Username = authResult.Account.Username; | ||
Authority = authResult.Account.Environment; | ||
AccountId = authResult.Account.HomeAccountId; | ||
TenantId = authResult.TenantId; | ||
} | ||
|
||
internal AuthenticationRecord(string username, string authority, string homeAccountId, string tenantId) | ||
{ | ||
|
||
Username = username; | ||
Authority = authority; | ||
AccountId = new AccountId(homeAccountId); | ||
TenantId = tenantId; | ||
} | ||
|
||
/// <summary> | ||
/// The user principal or service principal name of the account. | ||
/// </summary> | ||
public string Username { get; private set; } | ||
|
||
/// <summary> | ||
/// The authority host used to authenticate the account. | ||
/// </summary> | ||
public string Authority { get; private set; } | ||
|
||
/// <summary> | ||
/// A unique identifier of the account. | ||
/// </summary> | ||
public string HomeAccountId { get => AccountId.Identifier; } | ||
|
||
/// <summary> | ||
/// The tenant the account should authenticate in. | ||
/// </summary> | ||
public string TenantId { get; private set; } | ||
|
||
internal AccountId AccountId { get; private set; } | ||
|
||
/// <summary> | ||
/// Serializes the <see cref="AuthenticationRecord"/> to the specified <see cref="Stream"/>. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> which the serialized <see cref="AuthenticationRecord"/> will be written to.</param> | ||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> | ||
public void Serialize(Stream stream, CancellationToken cancellationToken = default) | ||
{ | ||
if (stream is null) throw new ArgumentNullException(nameof(stream)); | ||
|
||
SerializeAsync(stream, false, cancellationToken).EnsureCompleted(); | ||
} | ||
|
||
/// <summary> | ||
/// Serializes the <see cref="AuthenticationRecord"/> to the specified <see cref="Stream"/>. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> to which the serialized <see cref="AuthenticationRecord"/> will be written.</param> | ||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> | ||
public async Task SerializeAsync(Stream stream, CancellationToken cancellationToken = default) | ||
{ | ||
if (stream is null) throw new ArgumentNullException(nameof(stream)); | ||
|
||
await SerializeAsync(stream, true, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
|
||
/// <summary> | ||
/// Deserializes the <see cref="AuthenticationRecord"/> from the specified <see cref="Stream"/>. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> from which the serialized <see cref="AuthenticationRecord"/> will be read.</param> | ||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> | ||
public static AuthenticationRecord Deserialize(Stream stream, CancellationToken cancellationToken = default) | ||
{ | ||
if (stream is null) throw new ArgumentNullException(nameof(stream)); | ||
|
||
return DeserializeAsync(stream, false, cancellationToken).EnsureCompleted(); | ||
} | ||
|
||
/// <summary> | ||
/// Deserializes the <see cref="AuthenticationRecord"/> from the specified <see cref="Stream"/>. | ||
/// </summary> | ||
/// <param name="stream">The <see cref="Stream"/> from which the serialized <see cref="AuthenticationRecord"/> will be read.</param> | ||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> | ||
public static async Task<AuthenticationRecord> DeserializeAsync(Stream stream, CancellationToken cancellationToken = default) | ||
{ | ||
if (stream is null) throw new ArgumentNullException(nameof(stream)); | ||
|
||
return await DeserializeAsync(stream, true, cancellationToken).ConfigureAwait(false); | ||
} | ||
|
||
private async Task SerializeAsync(Stream stream, bool async, CancellationToken cancellationToken) | ||
{ | ||
using (var json = new Utf8JsonWriter(stream)) | ||
{ | ||
|
||
json.WriteStartObject(); | ||
|
||
json.WriteString(s_usernamePropertyNameBytes, Username); | ||
|
||
json.WriteString(s_authorityPropertyNameBytes, Authority); | ||
|
||
json.WriteString(s_homeAccountIdPropertyNameBytes, HomeAccountId); | ||
|
||
json.WriteString(s_tenantIdPropertyNameBytes, TenantId); | ||
|
||
json.WriteEndObject(); | ||
|
||
if (async) | ||
{ | ||
await json.FlushAsync(cancellationToken).ConfigureAwait(false); | ||
} | ||
else | ||
{ | ||
json.Flush(); | ||
} | ||
} | ||
} | ||
|
||
private static async Task<AuthenticationRecord> DeserializeAsync(Stream stream, bool async, CancellationToken cancellationToken) | ||
{ | ||
var authProfile = new AuthenticationRecord(); | ||
|
||
using JsonDocument doc = async ? await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false) : JsonDocument.Parse(stream); | ||
|
||
foreach (JsonProperty prop in doc.RootElement.EnumerateObject()) | ||
{ | ||
switch (prop.Name) | ||
{ | ||
case UsernamePropertyName: | ||
authProfile.Username = prop.Value.GetString(); | ||
break; | ||
case AuthorityPropertyName: | ||
authProfile.Authority = prop.Value.GetString(); | ||
break; | ||
case HomeAccountIdPropertyName: | ||
authProfile.AccountId = new AccountId(prop.Value.GetString()); | ||
break; | ||
case TenantIdPropertyName: | ||
authProfile.TenantId = prop.Value.GetString(); | ||
break; | ||
} | ||
} | ||
|
||
return authProfile; | ||
} | ||
} | ||
} |
Oops, something went wrong.