当前位置: 首页 > 知识库问答 >
问题:

如何通过MSAL库在AADV2endpoint中使用户同意Web API访问MS Graph用户配置文件

阎阎宝
2023-03-14

我试图构建一个客户端应用程序通过WebAPI层检索图资源的特性。该方案具有以下应用程序:

  1. Angular5客户端应用程序
  2. ASP.NET Core Web API

Angular5客户端应用程序使用MSAL对应用程序进行身份验证(通过apps.dev.microsoft.com注册应用程序作为聚合应用程序进行抵制;AAD v2endpoint)。身份验证流在登录或获取访问令牌时将Web API定义为作用域

constructor() {
   var logger = new Msal.Logger((logLevel, message, piiEnabled) =>
   {
     console.log(message);
   },
   { level: Msal.LogLevel.Verbose, correlationId: '12345' });
   this.app = new Msal.UserAgentApplication(
      CONFIGSETTINGS.clientId,
      null,
      this.authCallback,
      {
        redirectUri: window.location.origin,
        cacheLocation: 'localStorage', 
        logger: logger 
      }
   );
}

public getAPIAccessToken() {
return this.app.acquireTokenSilent(CONFIGSETTINGS.scopes).then(
    accessToken => {
      return accessToken;
    },
    error => {
      return this.app.acquireTokenSilent(CONFIGSETTINGS.scopes).then(
        accessToken => {
          return accessToken;
        },
        err => {
          console.error(err);
        }
      );
    }
  );

        public async Task<string> GetAccesToken(string resourceName)
        {
            var userAssertion = this.GetUserAssertion();
            string upn = GetLoggedInUpn();
            var userTokenCache = new SessionTokenCache(upn, new Microsoft.Extensions.Caching.Memory.MemoryCache(new MemoryCacheOptions())).GetCacheInstance();
            string msGraphScope = "https://graph.microsoft.com/User.Read";
            string authority = string.Format("https://login.microsoftonline.com/{0}/v2.0", this.authConfig.TenantId);
            ConfidentialClientApplication clientApplication = new ConfidentialClientApplication(this.authConfig.ClientId, authority, new ClientCredential(this.authConfig.AppKey), userTokenCache, null);

            var result = await clientApplication.AcquireTokenOnBehalfOfAsync(new string[] { msGraphScope }, userAssertion);
            return result != null ? result.AccessToken : null;
        }



        private UserAssertion GetUserAssertion()
        {
             string token = this.httpContextAccessor.HttpContext.Request.Headers["Authorization"];
            string upn = GetLoggedInUpn();
            if (token.StartsWith("Bearer", true, CultureInfo.InvariantCulture))
            {
                 token = token.Trim().Substring("Bearer".Length).Trim();
                return new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer");
            }
            else
            {
               throw new Exception($"ApiAuthService.GetUserAssertion() failed: Invalid Authorization token");
             }
         }

共有1个答案

钱运浩
2023-03-14

我已经想了好几个星期了!我的解决方案不是很好(它要求用户再次通过Web API的同意过程),但我不确定这是完全出乎意料的。毕竟,要么管理员必须同意Web API为用户访问图形,要么用户必须同意。

无论如何,关键是获得用户的同意,当然,Web API不能这样做,因为它没有UI。但是,ConfidentialClientApplication将告诉您用户必须使用GetAuthorizationRequestURLASync访问的URL。

下面是我用来使其工作的代码片段(我省略了将url传播回webapp的所有细节,但您可以查看https://github.com/rlittletht/msal-S2s-ref获得一个工作示例)

async Task<string> GetAuthenticationUrlForConsent(ConfidentialClientApplication cca, string []graphScopes)
{
    // if this throws, just let it throw
    Uri uri = await cca.GetAuthorizationRequestUrlAsync(graphScopes, "", null);
    return uri.AbsoluteUri;
}

async Task<string> GetAccessTokenForGraph()
{
    // (be sure to use the redirectUri here that matches the Web platform
    // that you added to your WebApi
    ConfidentialClientApplication cca =
        new ConfidentialClientApplication(Startup.clientId,
            "http://localhost/webapisvc/auth.aspx",
            new ClientCredential(Startup.appKey), null, null);

    string[] graphScopes = {"https://graph.microsoft.com/.default"};

    UserAssertion userAssertion = GetUserAssertion();

    AuthenticationResult authResult = null;
    try
    {
        authResult = await cca.AcquireTokenOnBehalfOfAsync(graphScopes, userAssertion);
    }
    catch (Exception exc)
    {
        if (exc is Microsoft.Identity.Client.MsalUiRequiredException
            || exc.InnerException is Microsoft.Identity.Client.MsalUiRequiredException)
        {
            // We failed because we don't have consent from the user -- even
            // though they consented for the WebApp application to access
            // the graph, they also need to consent to this WebApi to grant permission
            string sUrl = await GetAuthenticationUrlForConsent(cca, graphScopes);

            // you will need to implement this exception and handle it in the callers
            throw new WebApiExceptionNeedConsent(sUrl, "WebApi does not have consent from the user to access the graph on behalf of the user", exc);
        }
        // otherwise, just rethrow
        throw;
    }
    return authResult.AccessToken;
}
 类似资料:
  • 我有一个Web应用程序(Angular 7),它使用MSAL Angular对Azure AD用户进行身份验证,并获取访问我的Web API(.NET 4.6)的访问令牌。这两个应用都已在Azure门户中注册,并具有以下权限,如下所述: Web应用程序:for Web API(委派) Web API:<代码>用户。阅读邮政发送MS图表(委派) 现在,我想使用ADAL for从Web API调用Mi

  • 我正在尝试将AWS Cognito(用户池)和AWS DynamoDB用于我的移动应用程序。 我做了以下工作: 在AWS Cognito上创建用户池。 在AWS Cognito上创建身份池,并将用户池ID、应用客户端ID设置为身份验证提供商上的Cognito。 在AWS DynamoDB上创建SampleTable. 设置权限验证角色以访问AWS IAM上的SampleTable。 我创建了以下代

  • 我正在使用Chrome编写一些Selenium WebDriver和AutoIt Java测试。当我在Chrome中下载一个文件时,它会自动下载到我电脑上的downloads文件夹中。我正在一个存储库上与多个其他用户共享这个代码项目,因此我不想将我的下载文件夹与我的特定用户名硬编码在其中。 我的意思是假设我电脑上的用户名是“Eamon”。我的机器上的下载文件夹是“C:\Users\Eamon\do

  • 创建用户时,我需要在KeyClope user中添加用户同意。我正在使用API http://localhost:8080/auth/admin/realms/master/users 打开并尝试创建用户,但我得到的错误如下: 客户端需要用户同意 我不知道需要传递哪个参数来修复此错误。

  • 问题内容: 在创建用户个人资料系统时,我需要一些帮助。我希望它像Facebook或Myspace,在地址后仅包含用户名,没有问号,例如。我已经完成了所有注册,日志记录脚本等工作,但是如何使用上面的URL示例“ / username”转到配置文件? 问题答案: 您将需要创建一个mod重写,它采用第一个目录并将其作为$ _GET参数传递。 尝试这个: 那应该将’/’之后的内容重写为index.php?

  • 问题内容: 应用程式 我需要实现一个可供不同用户使用的Web应用程序。每个用户在各种表上都有不同的特权,例如 用户A可以从表中看到字段“名称”和“地址” 用户B可以在表格中看到字段“名称”和“电话号码”,但看不到“地址” 用户C可以查看和修改上述所有字段 我将在UI级别上进行一些操作以限制某些访问,例如,为无权修改条目的用户隐藏“编辑”按钮。但是,我认为我应该在较低级别上(也许在数据库级别上)来确