Azure / azure-sdk-for-net

This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.26k stars 4.6k forks source link

[QUERY] Is there a way to specify the scopes for Azure.ResourceManager clients? #21281

Closed ctaggart closed 1 year ago

ctaggart commented 3 years ago

When creating an Azure.ResourceManager client, is there a way to specify the scopes? This worked for me:

using Azure.Identity;
using Azure.ResourceManager.Resources;
using System;
using System.Linq;

var scopes = new[] { "https://management.core.windows.net/.default" };
// other vars

var tokenCredential = new ScopedCredential(new AzureCliCredential(), scopes);

var rmClient = new ResourcesManagementClient(resourceManagerEndpoint, subscriptionId, tokenCredential);
var groups = rmClient.ResourceGroups.List();
Console.WriteLine("# of groups " + groups.Count());

but felt like a hack:

using Azure.Core;
using System.Threading;
using System.Threading.Tasks;

namespace Azure.Identity
{

    public class ScopedCredential : TokenCredential
    {
        readonly TokenCredential _tokenCredential;
        readonly string[] _scopes;

        public ScopedCredential(TokenCredential tokenCredential, string[] scopes)
        {
            _tokenCredential = tokenCredential;
            _scopes = scopes;
        }

        public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            var scopedRequestContext = new TokenRequestContext(_scopes, requestContext.ParentRequestId, requestContext.Claims);
            return _tokenCredential.GetToken(scopedRequestContext, cancellationToken);
        }

        public override ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            var scopedRequestContext = new TokenRequestContext(_scopes, requestContext.ParentRequestId, requestContext.Claims);
            return _tokenCredential.GetTokenAsync(scopedRequestContext, cancellationToken);
        }
    }

}

and I'm wondering if there is a better way.

jsquire commented 3 years ago

Thank you for your feedback. Tagging and routing to the team members best able to assist.

christothes commented 3 years ago

Hi @ctaggart You shouldn't need to supply the scopes at all when using the ResourcesManagementClient. For example, you could change your first example to the following:

var tokenCredential = new AzureCliCredential();

var rmClient = new ResourcesManagementClient(resourceManagerEndpoint, subscriptionId, tokenCredential);
var groups = rmClient.ResourceGroups.List();
Console.WriteLine("# of groups " + groups.Count());
ctaggart commented 3 years ago

Hey @christothes, It is that easy when az cloud set -n AzureCloud, but when using another cloud such as az cloud set -n dogfood, it looks like it fails trying to get a new token.

POST https://login.windows-ppe.net/f686d426-8d16-42db-81b7-ab578e110ccd/oauth2/token

400 Bad Request

{
  "error": "invalid_grant",
  "error_description": "AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 9cd56182-d941-46ae-86c3-77b086b00d00\r\nCorrelation ID: 786c7c60-299c-460b-ba4b-9a28cab52a81\r\nTimestamp: 2021-05-24 14:15:38Z",
  "error_codes": [
    65001
  ],
  "timestamp": "2021-05-24 14:15:38Z",
  "trace_id": "9cd56182-d941-46ae-86c3-77b086b00d00",
  "correlation_id": "786c7c60-299c-460b-ba4b-9a28cab52a81",
  "suberror": "consent_required"
}

If I use the ScopedCredential wrapper, it works.

christothes commented 3 years ago

This seems to be an issue with the ResourcesManagementClient, as the credential should be getting the appropriate scope passed to it based on the resource being targeted.

@allenjzhang, would you mind taking a look at this?

ctaggart commented 3 years ago

@christothes, it is not just ResourcesManagementClient. I can reproduce it with all other clients I've tried.

christothes commented 3 years ago

@ctaggart What scope are you supplying to your ScopedCredential when targeting the dog dogfood cloud?

ctaggart commented 3 years ago

@christothes, as posted above, this works:

var scopes = new[] { "https://management.core.windows.net/.default" };
christothes commented 3 years ago

@ctaggart If you are using the same scope for both public and dogfood clouds, I'm not sure why using ScopedCredential is making a difference, as it is setting the same scope that I'd expect the client would have set.

Would you mind enabling logging for the credential and reproducing with and without your workaround?

ctaggart commented 3 years ago

@christothes, I enabled logging with:


using var logger = Core.Diagnostics.AzureEventSourceListener.CreateConsoleLogger(System.Diagnostics.Tracing.EventLevel.Verbose);

var rmClient = new ResourcesManagementClient(resourceManagerEndpoint, subscriptionId, tokenCredential, new ResourcesManagementClientOptions{
    Diagnostics = {
        IsLoggingContentEnabled = true
    }
});

with workaround

[Informational] Azure-Identity: AzureCliCredential.GetToken invoked. Scopes: [ https://management.core.windows.net/.default ] ParentRequestId: ad99550f-d78a-40f3-b349-dbab58686462
[Informational] Azure-Identity: AzureCliCredential.GetToken succeeded. Scopes: [ https://management.core.windows.net/.default ] ParentRequestId: ad99550f-d78a-40f3-b349-dbab58686462 ExpiresOn: 2021-05-24T17:38:33.2822970+00:00
[Informational] Azure-Core: Request [ad99550f-d78a-40f3-b349-dbab58686462] GET https://api-dogfood.resources.windows-int.net/subscriptions/ba75e79b-dd95-4025-9dbf-3a7ae8dff2b5/resourcegroups?api-version=REDACTED
Accept:application/json
x-ms-client-request-id:ad99550f-d78a-40f3-b349-dbab58686462
x-ms-return-client-request-id:true
User-Agent:azsdk-net-ResourceManager.Resources/1.0.0-preview.2,(.NET 5.0.6; Microsoft Windows 10.0.19042)
Authorization:REDACTED
client assembly: Azure.ResourceManager.Resources
[Informational] Azure-Core: Response [ad99550f-d78a-40f3-b349-dbab58686462] 200 OK (03.2s)
Cache-Control:no-cache
Pragma:no-cache
x-ms-ratelimit-remaining-subscription-reads:REDACTED
x-ms-request-id:76dab26b-4f25-4c13-824d-ce0a355a708c
x-ms-correlation-request-id:REDACTED
x-ms-routing-request-id:REDACTED
Strict-Transport-Security:REDACTED
X-Content-Type-Options:REDACTED
X-Cache:REDACTED
X-MSEdge-Ref:REDACTED
Date:Mon, 24 May 2021 16:38:37 GMT
Content-Length:21075
Content-Type:application/json; charset=utf-8
Expires:-1

[Verbose] Azure-Core: Response [ad99550f-d78a-40f3-b349-dbab58686462] content: REDACTED
[Warning] Azure-Core: Response [ad99550f-d78a-40f3-b349-dbab58686462] took 03.2s
# of groups 76

without workaround

[Informational] Azure-Identity: AzureCliCredential.GetToken invoked. Scopes: [ https://api-dogfood.resources.windows-int.net//.default ] ParentRequestId: 7057c83b-b65d-4ab3-bac4-a96edabb6f48
[Informational] Azure-Identity: AzureCliCredential.GetToken was unable to retrieve an access token. Scopes: [ https://api-dogfood.resources.windows-int.net//.default ] ParentRequestId: 7057c83b-b65d-4ab3-bac4-a96edabb6f48 Exception: Azure.Identity.AuthenticationFailedException (0x80131500): Azure CLI authentication failed due to an unknown error. ERROR: The command failed with an unexpected error. Here is the traceback:
ERROR: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 8e592ea4-bd53-44d0-8b54-91c3024e1000\r\nCorrelation ID: 3d861ad3-0e9d-4be6-84e6-e631e49d0f9a\r\nTimestamp: 2021-05-24 16:37:24Z","error_codes":[65001],"timestamp":"2021-05-24 16:37:24Z","trace_id":"8e592ea4-bd53-44d0-8b54-91c3024e1000","correlation_id":"3d861ad3-0e9d-4be6-84e6-e631e49d0f9a","suberror":"consent_required"}
Traceback (most recent call last):
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-yccaebu4\knack\cli.py", line 233, in invoke
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 664, in execute
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 727, in _run_jobs_serially
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 720, in _run_job
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-rg200gj8\six.py", line 703, in reraise
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 698, in _run_job
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 331, in __call__
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\__init__.py", line 816, in default_command_handler
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-7as_bwui\azure\cli\command_modules\profile\custom.py", line 79, in get_access_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\_profile.py", line 676, in get_raw_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\_profile.py", line 1065, in retrieve_token_for_user
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 145, in acquire_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 128, in _acquire_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 143, in token_func
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 347, in get_token_from_cache_with_refresh
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 127, in _find_token_from_cache
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 199, in find
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 184, in _refresh_entry_if_necessary
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 160, in _acquire_new_token_from_mrrt
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 137, in _get_token_with_token_response
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 339, in _get_token_with_refresh_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 112, in _oauth_get_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\oauth2_client.py", line 289, in get_token
adal.adal_error.AdalError: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 8e592ea4-bd53-44d0-8b54-91c3024e1000\r\nCorrelation ID: 3d861ad3-0e9d-4be6-84e6-e631e49d0f9a\r\nTimestamp: 2021-05-24 16:37:24Z","error_codes":[65001],"timestamp":"2021-05-24 16:37:24Z","trace_id":"8e592ea4-bd53-44d0-8b54-91c3024e1000","correlation_id":"3d861ad3-0e9d-4be6-84e6-e631e49d0f9a","suberror":"consent_required"}
To open an issue, please run: 'az feedback'
Unhandled exception. Azure.Identity.AuthenticationFailedException: Azure CLI authentication failed due to an unknown error. ERROR: The command failed with an unexpected error. Here is the traceback:
ERROR: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 8e592ea4-bd53-44d0-8b54-91c3024e1000\r\nCorrelation ID: 3d861ad3-0e9d-4be6-84e6-e631e49d0f9a\r\nTimestamp: 2021-05-24 16:37:24Z","error_codes":[65001],"timestamp":"2021-05-24 16:37:24Z","trace_id":"8e592ea4-bd53-44d0-8b54-91c3024e1000","correlation_id":"3d861ad3-0e9d-4be6-84e6-e631e49d0f9a","suberror":"consent_required"}
Traceback (most recent call last):
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-yccaebu4\knack\cli.py", line 233, in invoke
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 664, in execute
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 727, in _run_jobs_serially
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 720, in _run_job
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-rg200gj8\six.py", line 703, in reraise
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 698, in _run_job
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\commands\__init__.py", line 331, in __call__
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\__init__.py", line 816, in default_command_handler
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-7as_bwui\azure\cli\command_modules\profile\custom.py", line 79, in get_access_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\_profile.py", line 676, in get_raw_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-8u6uejh7\azure\cli\core\_profile.py", line 1065, in retrieve_token_for_user
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 145, in acquire_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 128, in _acquire_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\authentication_context.py", line 143, in token_func
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 347, in get_token_from_cache_with_refresh
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 127, in _find_token_from_cache
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 199, in find
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 184, in _refresh_entry_if_necessary
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\cache_driver.py", line 160, in _acquire_new_token_from_mrrt
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 137, in _get_token_with_token_response
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 339, in _get_token_with_refresh_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\token_request.py", line 112, in _oauth_get_token
  File "C:\Users\VSSADM~1\AppData\Local\Temp\pip-unpacked-wheel-fnzsbt3h\adal\oauth2_client.py", line 289, in get_token
adal.adal_error.AdalError: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '04b07795-8ddb-461a-bbee-02f9e1bf7b46' named 'Microsoft Azure CLI'. Send an interactive authorization request for this user and resource.\r\nTrace ID: 8e592ea4-bd53-44d0-8b54-91c3024e1000\r\nCorrelation ID: 3d861ad3-0e9d-4be6-84e6-e631e49d0f9a\r\nTimestamp: 2021-05-24 16:37:24Z","error_codes":[65001],"timestamp":"2021-05-24 16:37:24Z","trace_id":"8e592ea4-bd53-44d0-8b54-91c3024e1000","correlation_id":"3d861ad3-0e9d-4be6-84e6-e631e49d0f9a","suberror":"consent_required"}
To open an issue, please run: 'az feedback'
   at Azure.Identity.AzureCliCredential.RequestCliAccessTokenAsync(Boolean async, String[] scopes, CancellationToken cancellationToken)
   at Azure.Identity.AzureCliCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex)
   at Azure.Identity.AzureCliCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.TaskExtensions.EnsureCompleted[T](ValueTask`1 task)
   at Azure.Identity.AzureCliCredential.GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueFromCredentialAsync(TokenRequestContext context, Boolean async, CancellationToken cancellationToken)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AccessTokenCache.GetHeaderValueAsync(HttpMessage message, TokenRequestContext context, Boolean async)
   at Azure.Core.Pipeline.TaskExtensions.EnsureCompleted[T](ValueTask`1 task)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AuthenticateAndAuthorizeRequest(HttpMessage message, TokenRequestContext context)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.AuthorizeRequest(HttpMessage message)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.TaskExtensions.EnsureCompleted(ValueTask task)
   at Azure.Core.Pipeline.BearerTokenAuthenticationPolicy.Process(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelinePolicy.ProcessNext(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
   at Azure.Core.Pipeline.TaskExtensions.EnsureCompleted(ValueTask task)
   at Azure.Core.Pipeline.RetryPolicy.Process(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelinePolicy.ProcessNext(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.Process(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelinePolicy.ProcessNext(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.Process(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelinePolicy.ProcessNext(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipelineSynchronousPolicy.Process(HttpMessage message, ReadOnlyMemory`1 pipeline)
   at Azure.Core.Pipeline.HttpPipeline.Send(HttpMessage message, CancellationToken cancellationToken)
   at Azure.ResourceManager.Resources.ResourceGroupsRestOperations.List(String filter, Nullable`1 top, CancellationToken cancellationToken)
   at Azure.ResourceManager.Resources.ResourceGroupsOperations.<>c__DisplayClass16_0.<List>g__FirstPageFunc|0(Nullable`1 pageSizeHint)
   at Azure.Core.PageableHelpers.<>c__DisplayClass0_0`1.<CreateEnumerable>b__0(String continuationToken, Nullable`1 pageSizeHint)
   at Azure.Core.PageableHelpers.FuncPageable`1.AsPages(String continuationToken, Nullable`1 pageSizeHint)+MoveNext()
   at Azure.Pageable`1.GetEnumerator()+MoveNext()
   at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
   at Azure.ResourceManager.Avs.Example.Program.Main(String[] args) in C:\Users\cataggar\io\avs\src\fct\Azure.ResourceManager.Avs\Example\Program.cs:line 45
allenjzhang commented 3 years ago

Actually Microsoft.Rest.ClientRuntime.Azure.Authentication is an often overlooked package that simplies the auth for current track 1 .NET SDKs (Microsoft.Azure.Management.XXXX). It provides both ApplicationTokenProvider and interactive UserTokenProvider (only for .NET 4.5.2). It also provides a few Azure environments out of box.

BTW, with ApplicationTokenProvider, it not only supports a few types of auth (Cached, ClientId/Secrete, Cert, CustomProvider etc), it also handles the token refresh for you as well.

            // Create a custom AADSetting  or use one of predefined settings
            //    ActiveDirectoryServiceSettings.Azure/AzureChina/AzureUSGovernment (this is Fairfax)
            var aadSetting = new ActiveDirectoryServiceSettings();
            aadSetting.AuthenticationEndpoint = new Uri("https://login.microsoftonline.com/");
            aadSetting.TokenAudience = new Uri("https://management.core.windows.net/");

            var credentials = await ApplicationTokenProvider.LoginSilentAsync(
                "microsoft.com",
                "YOUR CLIENT APP ID",
                "YOUR CLIENT Secret",
                aadSetting);      // or existing ones ActiveDirectoryServiceSettings.Azure.AzureGermany

             var client = new ResourceManagementClient(cred);

Hope this helps and let me know if you have questions.

ctaggart commented 3 years ago

@allenjzhang, true, but this issue is about Azure.ResourceManager.XXXX .NET SDKs.

christothes commented 3 years ago

@allenjzhang - I believe the client bug is that we are inferring the scope from the resource URI, but the resource manager scope is the same across at least the two clouds mentioned in this example.

allenjzhang commented 3 years ago

Sorry, my bad. Track 2 SDKs is currently still being developed. We are to finalize the design on how to expose different environments along with the built-in management endpoint as well. Our hope is to expose them in a unified way so you do not need to do the hack.

akshita31 commented 3 years ago

+1 on this. Facing this issue when trying to use NetworkManagementClient for Dogfood environment. I am able to set the authority host and i think based on that the audience is being inferred which doesnt work for dogfood environment

cataggar commented 2 years ago

@allenjzhang, I need this again. Is there a new way to specify the scopes without this hack?

cataggar commented 2 years ago

If clients allowed setting the HttpPipeline, something like this would work:

            string[] scopes = { "api://44fba2dc-ec80-400b-84d3-4e03cd6de875/.default" };
            _pipeline = HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, scopes));

In a quick search, I saw some clients with internal constructors supporting HttpPipeline, but no public.

ArthurMa1978 commented 1 year ago

@ArcturusZhang please help to follow up with this issue, and evaluate if it worth to build convenient utility to support scope

ArthurMa1978 commented 1 year ago

We confirmed this is an ask for Azure.Identity, assign to @jsquire for further confirm.

jsquire commented 1 year ago

Discussed with Arthur offline; the general responsibility of identifying which environment is being targeted and forming the correct scope belongs with the specific client, it should not fall to developers using the library to provide. We would generally advocate that services use an auth scope that can be inferred from the endpoint across all clouds, including dogfood. If that is not possible, the library would need to understand the needs of that particular service and form the correct auth scope.

In this case, needing a custom scope for the Dogfood environment is an internal Microsoft-only scenario and not one that Azure customers would be faced with. We do not want to introduce internal concerns into the public API for the Azure SDK libraries unless there is no other alternative. In this case, Cameron's approach of creating a custom credential is a valid one, and what I would recommend.