MVC5 应用程序使用 Azure Active Directory + REST API -- 为 PowerBI / O365 授权

MVC5 app using Azure Active Directory + REST API -- to auth for PowerBI / O365

我正在尝试调整此处显示的 WebAPI 示例,以便在 MVC5 中使用:

https://msdn.microsoft.com/en-US/library/dn931282.aspx#Configure

我有一个基于 AccountController 的常规登录系统,但我还需要用户通过 OAuth 登录到 PowerBI,这样我就可以通过 PowerBI REST API 提取数据集。但是,我将 ClaimsPrincipal.Current.FindFirst(..) 设置为 null

    private static async Task<string> getAccessToken()
    {
        // Create auth context (note: token is not cached)
        AuthenticationContext authContext = new AuthenticationContext(Settings.AzureADAuthority);

        // Create client credential
        var clientCredential = new ClientCredential(Settings.ClientId, Settings.Key);

        // Get user object id
        var userObjectId = ClaimsPrincipal.Current.FindFirst(Settings.ClaimTypeObjectIdentifier).Value;

        // Get access token for Power BI
        // Call Power BI APIs from Web API on behalf of a user
        return authContext.AcquireToken(Settings.PowerBIResourceId, clientCredential, new UserAssertion(userObjectId, UserIdentifierType.UniqueId.ToString())).AccessToken;
    }

在示例应用程序(WebAPI 项目)中一切正常。我还在 Startup.Auth.cs.

中配置了 OWIN app.UseOpenIdConnectAuthentication 东西

似乎问题是我在 'ClaimsPrincipal.Current' 中拥有的唯一声明类型是 'CookieAuthentication' - 它缺少 http://schemas.microsoft.com/identity/claims/objectidentifier 声明。

另外...Microsoft OAuth window 永远不会在浏览器中打开...但是,错误出在与 ActiveDirectory 相关的代码中...该代码首先不需要 OAuth 令牌地方对吧?

推荐的方法是使用 Open ID Connect 中间件自动为您检索的代码。这里有相关示例:

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet

此示例使用 OAuth 获取 AAD 图的令牌 API。我不了解 PowerBI,但我相信这完全类似于为 PowerBI 获取令牌。

特别注意这个文件:

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/App_Start/Startup.Auth.cs

AuthorizationCodeReceived = (context) =>
{
    var code = context.Code;

    ClientCredential credential = new ClientCredential(clientId, appKey);
    string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
    AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));
    AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential, graphResourceId);

    return Task.FromResult(0);
},

上面的代码在每次成功的身份验证时调用,ADAL 用于检索图形的令牌 API。此时,为 Graph API 获取令牌的唯一原因是将短期授权代码交换为寿命更长的刷新令牌,并将其存储在缓存中。这就是从未使用 'result' 的原因。

稍后,在以下文件中,缓存用于检索令牌并使用它来访问图形:

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Controllers/UserProfileController.cs

string tenantId = ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value;
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
ClientCredential credential = new ClientCredential(clientId, appKey);
result = authContext.AcquireTokenSilent(graphResourceId, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));

这次真的用到了token

用 PowerBI 替换示例中的 Graph API,我认为你应该可以开始了。

请注意,另一件需要注意的事情是缓存实现。该文件包含一个适当的名称 NaiveSessionCache.

https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet/blob/master/TodoListWebApp/Utils/NaiveSessionCache.cs

如果您有多个前端,您将需要实现自己的、不那么天真的会话缓存,以便所有前端可以共享相同的缓存。

至少对我而言,一个潜在的解决方法是在 Azure AD 上使用 "native app" 设置并遵循此工作流程,而不是 Web 应用程序 + oauth 工作流程:

https://msdn.microsoft.com/en-US/library/dn877545.aspx