.net core MSAL-应用程序可以请求许可,即使它';未在';API权限';

.net core MSAL-应用程序可以请求许可,即使它';未在';API权限';,.net-core,azure-active-directory,identityserver3,msal,.net Core,Azure Active Directory,Identityserver3,Msal,我已经使用MSAL库创建了一个小型的.NET Core 3.1控制台应用程序,它请求scopeapi://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2 自定义API公开了两个作用域 api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope1 api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2 我还在Azure Active Directo

我已经使用MSAL库创建了一个小型的.NET Core 3.1控制台应用程序,它请求scope
api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2

自定义API公开了两个作用域

  • api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope1
  • api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2

我还在Azure Active Directory中配置了另一个名为
test app
的应用程序,它代表了我的控制台应用程序

我只配置了一个API权限(
api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope1
)用于此应用程序。我的理解是,使用此配置,客户端应用程序将只能请求作用域
test1
,而不允许
test应用程序
请求
scope2

下面是截图

这是我的代码:

//<PackageReference Include="Microsoft.Identity.Client" Version="4.13.0" />
namespace console_client
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Azure AD parameters
            var clientId = "dddeefa5-d95c-4931-a53d-2382deee27c3";
            var tenant = "-- MY TENANT ID--";
            var instance = "https://login.microsoftonline.com/";
            #endregion

            var client = PublicClientApplicationBuilder
                .Create(clientId)
                .WithDefaultRedirectUri()
                .WithAuthority($"{instance}{tenant}")
                .Build();

            List<string> scopes = new List<string>();

            try
            {
                // I was under impression that this call will throw as exception as
                // this app is requesting 'testscope2' which is not included in API Permissions
                // while configuring test-app in Azure Active Directory (dddeefa5-d95c-4931-a53d-2382deee27c3 )
                // But I was able to retrieve token back with testscope2 in it.
                scopes.Add("api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2");
                var authenticationResult = client.AcquireTokenInteractive(scopes).ExecuteAsync().Result;
                Console.WriteLine($"Interactive Access token is : {authenticationResult.AccessToken}");
            }
            catch (Exception ex)
            { 
                System.Console.WriteLine($"******* {ex.Message}");
            }
        }
    }
}
//
命名空间控制台客户端
{
班级计划
{
静态void Main(字符串[]参数)
{
#区域Azure AD参数
var clientId=“dddeefa5-d95c-4931-a53d-2382deee27c3”;
var tenant=“--我的租户ID-”;
变量实例=”https://login.microsoftonline.com/";
#端区
var client=PublicClientApplicationBuilder
.Create(clientId)
.WithDefaultRedirectUri()
.WithAuthority($“{instance}{tenant}”)
.Build();
列表范围=新列表();
尝试
{
//我的印象是,这个调用将作为异常抛出
//此应用程序正在请求API权限中未包含的“testscope2”
//在Azure Active Directory(dddeefa5-d95c-4931-a53d-2382DEEEE27C3)中配置测试应用程序时
//但我能够检索回包含testscope2的令牌。
作用域。添加(“api://55a047a1-a0d1-4b6b-9896-751a848e1e06/testscope2");
var authenticationResult=client.AcquireTokenInteractive(scopes.ExecuteAsync().Result;
WriteLine($“交互式访问令牌为:{authenticationResult.AccessToken}”);
}
捕获(例外情况除外)
{ 
System.Console.WriteLine($“*********{ex.Message}”);
}
}
}
}
问题

我遗漏了什么吗?为什么即使应用程序没有配置权限,我也要取回访问令牌

谢谢

TL;博士,这是一个特点

使用v2端点/MSAL,您可以请求应用程序清单中未定义的范围。 应用程序注册中的权限是应用程序所需的静态权限。 但您的应用程序也可以在登录时请求动态权限。 用户/管理员仍需对此表示同意。当然,未经同意,应用程序将无法获得许可

你的应用程序似乎是一个单一租户的应用程序,所以这对你来说并没有什么影响。 它主要适用于多租户SaaS应用程序,这些应用程序可以在应用程序注册/清单中要求所需的最低权限,然后根据需要为选择加入功能请求更多权限

顺便说一下,如果您想使用应用程序注册中定义的权限,您可以请求一个特殊范围:
api://55a047a1-a0d1-4b6b-9896-751a848e1e06/.default
(您的应用程序ID URI或客户端ID+“/.default”)。 这将使AAD查看您的应用程序注册,以决定检查许可的权限