Azure / Azure/azure-powershell
[Az.Accounts]: ambiguity in clientfactory.CreateArmClient
- Dominant language
- C#
- Stars
- 4.8k
- Forks
- 4.3k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 51
Description
### Description
To create track1 SDK client, we use method
```
public virtual TClient CreateArmClient(IAzureContext context, string endpoint) where TClient : Microsoft.Rest.ServiceClient
```
the endpoint passed in will be used to
- as endpoint: construct base uri (``` var baseUri = context.Environment.GetEndpointAsUri(endpoint);```)
- as resourceId: retrieve access token (```var creds = AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(context, endpoint);```)
there are two part of authenticate flow:
1. when login as access token:
``` RenewingTokenCredential(new ExternalAccessToken(GetEndpointToken(context.Account, targetEndpoint), () => GetEndpointToken(context.Account, targetEndpoint)));```
```
private string GetEndpointToken(IAzureAccount account, string targetEndpoint)
{
string tokenKey = AzureAccount.Property.AccessToken;
if (string.Equals(targetEndpoint, AzureEnvironment.Endpoint.AzureKeyVaultServiceEndpointResourceId, StringComparison.OrdinalIgnoreCase))
{
tokenKey = AzureAccount.Property.KeyVaultAccessToken;
}
if (string.Equals(targetEndpoint, AzureEnvironment.ExtendedEndpoint.MicrosoftGraphEndpointResourceId, StringComparison.OrdinalIgnoreCase))
{
tokenKey = Constants.MicrosoftGraphAccessToken;
}
if (string.Equals(targetEndpoint, AzureEnvironment.Endpoint.Graph, StringComparison.OrdinalIgnoreCase))
{
tokenKey = AzureAccount.Property.GraphAccessToken;
}
return account.GetProperty(tokenKey);
}
```
2. otherwise
```
public IAccessToken Authenticate(
IAzureAccount account,
IAzureEnvironment environment,
string tenant,
SecureString password,
string promptBehavior,
Action promptAction,
IAzureTokenCache tokenCache,
string resourceId = AzureEnvironment.Endpoint.ActiveDirectoryServiceEndpointResourceId)
```
for flow 1, the targetEndpoint is actually irrelevant to the actual access token (in context.account.extendedproperties, key: Microsoft.Azure.Commands.Common.Authentication.Constants.MicrosoftGraphAccessToken, value: msgraph access token)
When create MSGraph client , as the "CreateArmClient" method suggested, we passed in the endpoint "MicrosoftGraphUrl", however this cannot be matched in flow 1 :
```
if (string.Equals(targetEndpoint, AzureEnvironment.ExtendedEndpoint.MicrosoftGraphEndpointResourceId, StringComparison.OrdinalIgnoreCase))
```
which returned the ARM accesstoken instead.
I made a work around #18414 to let it match both MSGraph ResourceId and MSGraph endpoint. A better fix would be use ResourceId for both flow 1 and 2, separate endpoint and resourceId in:
```
var creds = AzureSession.Instance.AuthenticationFactory.GetServiceClientCredentials(context, context.Environment.GetTokenAudience(endpoint));
var baseUri = context.Environment.GetEndpointAsUri(endpoint);
```
and in flow 1:
```
RenewingTokenCredential(new ExternalAccessToken(GetEndpointToken(context.Account, ResourceId), () => GetEndpointToken(context.Account, ResourceId)));
```
Contributor guide
Assessment
This issue has not been assessed yet.