You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Framework MVC从Azure AD获取用户令牌用于Power BI嵌入

我来帮你搞定这个问题——你当前的OIDC配置没有请求Power BI资源的访问令牌,也没开启刷新令牌的获取逻辑,所以服务器端拿不到这些关键令牌。下面是一步步的调整方案:

1. 调整OpenIdConnectAuthenticationOptions核心配置

你需要修改Start.Auth.cs中的OIDC设置,明确指定要访问的Power BI API资源、请求令牌的类型,以及添加令牌交换和存储的逻辑。

首先确保你已经安装了Microsoft.IdentityModel.Clients.ActiveDirectory NuGet包,这个包提供了Azure AD令牌交换的核心方法。

修改后的配置代码如下:

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    ClientId = clientId,
    Authority = authority,
    RedirectUri = redirectUri,
    // 指定响应类型为授权码+ID令牌,用于交换访问令牌
    ResponseType = OpenIdConnectResponseType.CodeIdToken,
    // 目标资源:Power BI API的标识符
    Resource = "https://analysis.windows.net/powerbi/api",
    // 请求的权限范围:openid用于身份验证,offline_access用于获取刷新令牌
    Scope = "openid profile offline_access",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthorizationCodeReceived = async (context) =>
        {
            // 使用客户端凭证交换授权码,获取访问令牌和刷新令牌
            var credential = new ClientCredential(clientId, clientSecret); // 这里需要你的应用Client Secret
            var authContext = new AuthenticationContext(authority);
            
            var tokenResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
                context.Code,
                new Uri(context.RedirectUri),
                credential,
                context.Options.Resource);
            
            // 将令牌存储到用户Claims中(加密存储,安全可靠)
            context.AuthenticationTicket.Identity.AddClaim(new Claim("access_token", tokenResult.AccessToken));
            context.AuthenticationTicket.Identity.AddClaim(new Claim("refresh_token", tokenResult.RefreshToken));
            
            // 也可以同步存储到Session,方便后续快速获取
            context.OwinContext.Session["PowerBI_AccessToken"] = tokenResult.AccessToken;
        },
        AuthenticationFailed = (context) =>
        {
            context.HandleResponse();
            context.Response.Redirect("/Home/Error?message=" + context.Exception.Message);
            return Task.FromResult(0);
        }
    },
    TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false // 测试环境可关闭,生产环境建议开启并验证Issuer
    }
});
2. 从服务器端取出令牌并传递给前端

在你的MVC控制器中,你可以从用户的Claims或Session中获取令牌,然后传递给View,供Power BI JavaScript嵌入使用:

public ActionResult EmbedReport()
{
    // 从Claims中获取访问令牌(推荐,因为Claims是加密的)
    var accessToken = User.Claims.FirstOrDefault(c => c.Type == "access_token")?.Value;
    
    // 备选:从Session中获取
    // var accessToken = Session["PowerBI_AccessToken"] as string;
    
    if (string.IsNullOrEmpty(accessToken))
    {
        return RedirectToAction("Login", "Account");
    }
    
    // 将令牌传递给View
    ViewBag.PowerBIUserToken = accessToken;
    return View();
}

然后在View的Power BI嵌入代码中使用这个令牌:

<script src="https://microsoft.github.io/PowerBI-JavaScript/dist/powerbi.min.js"></script>
<script>
    var embedConfig = {
        type: 'report',
        id: '你的报表ID',
        embedUrl: '你的报表嵌入URL',
        accessToken: '@ViewBag.PowerBIUserToken',
        tokenType: window.powerbi.models.TokenType.Aad // 指定为Azure AD用户令牌
    };

    // 初始化嵌入组件
    var reportContainer = document.getElementById('reportContainer');
    var report = powerbi.embed(reportContainer, embedConfig);
</script>
3. 处理令牌过期(可选但重要)

访问令牌默认有效期为1小时,你可以用刷新令牌在服务器端获取新的访问令牌,避免用户重复登录:

public async Task<JsonResult> RefreshPowerBIToken()
{
    var refreshToken = User.Claims.FirstOrDefault(c => c.Type == "refresh_token")?.Value;
    if (string.IsNullOrEmpty(refreshToken))
    {
        return Json(new { success = false, message = "无可用刷新令牌" }, JsonRequestBehavior.AllowGet);
    }

    var credential = new ClientCredential(clientId, clientSecret);
    var authContext = new AuthenticationContext(authority);
    
    var tokenResult = await authContext.AcquireTokenByRefreshTokenAsync(
        refreshToken,
        credential,
        "https://analysis.windows.net/powerbi/api");

    // 更新Claims中的访问令牌
    var identity = (ClaimsIdentity)User.Identity;
    var oldAccessTokenClaim = identity.Claims.FirstOrDefault(c => c.Type == "access_token");
    if (oldAccessTokenClaim != null)
    {
        identity.RemoveClaim(oldAccessTokenClaim);
    }
    identity.AddClaim(new Claim("access_token", tokenResult.AccessToken));

    // 更新Session
    Session["PowerBI_AccessToken"] = tokenResult.AccessToken;

    return Json(new { success = true, accessToken = tokenResult.AccessToken }, JsonRequestBehavior.AllowGet);
}
额外注意事项
  • 确保你的Azure AD应用注册已经添加了Power BI API的权限(比如Report.Read.All),并且已经完成管理员同意
  • Client Secret不要硬编码,建议存储在Web.config的appSettings中,生产环境可使用Azure Key Vault托管
  • 刷新令牌不要暴露给前端,所有刷新逻辑都在服务器端处理,前端只需要获取新的访问令牌

内容的提问来源于stack exchange,提问作者topher-j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:35:51