.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
相关产品推荐
相关产品推荐

