Azure App Service中ASP.NET Core MVC扩展MicrosoftIdentityWebAppAuthentication实现弹窗认证
实现ASP.NET Core MVC应用的弹窗式Azure AD认证
可以通过前端MSAL.js弹窗获取身份令牌 + 后端验证令牌并创建会话的混合方案实现,完全保留现有AddMicrosoftIdentityWebAppAuthentication的后端流程,无需重构整个项目。以下是具体实现步骤:
1. 前端添加MSAL.js弹窗登录逻辑
在你的MVC视图(比如共享布局页_Layout.cshtml或自定义登录页)中引入MSAL.js,并编写弹窗登录的触发代码:
<!-- 引入MSAL.js --> <script src="https://alcdn.msauth.net/browser/2.38.1/js/msal-browser.min.js"></script> <script> // 从后端配置读取Azure AD参数(也可直接填入应用注册信息) const msalConfig = { auth: { clientId: '@Configuration["AzureAd:ClientId"]', authority: '@Configuration["AzureAd:Authority"]', redirectUri: `${window.location.origin}/auth/popup-callback` } }; const msalInstance = new msal.PublicClientApplication(msalConfig); // 弹窗登录触发函数 async function triggerPopupLogin() { try { // 弹窗发起认证,获取id token const loginResult = await msalInstance.loginPopup({ scopes: ["openid", "profile", "user.read"] }); // 将id token传给后端验证并创建会话 const validateResponse = await fetch('/auth/validate-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ idToken: loginResult.idToken.rawIdToken }) }); if (validateResponse.ok) { // 会话创建成功,刷新页面或跳转至目标页 window.location.reload(); } } catch (err) { console.error('弹窗登录失败:', err); alert('登录出错,请重试'); } } </script> <!-- 替换原有的登录按钮 --> <button onclick="triggerPopupLogin()" class="btn btn-primary">弹窗登录</button>
2. 后端添加令牌验证与会话创建接口
新增一个API控制器,用于接收前端传来的id token,验证其有效性后创建ASP.NET Core用户会话:
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; [ApiController] [Route("auth")] public class AuthPopupController : ControllerBase { private readonly IConfiguration _config; private readonly ILogger<AuthPopupController> _logger; public AuthPopupController(IConfiguration config, ILogger<AuthPopupController> logger) { _config = config; _logger = logger; } // 允许匿名访问,接收前端传来的id token [AllowAnonymous] [HttpPost("validate-token")] public async Task<IActionResult> ValidatePopupToken([FromBody] TokenRequest request) { if (string.IsNullOrEmpty(request.IdToken)) return BadRequest("令牌不能为空"); try { // 配置令牌验证参数 var validationParams = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = _config["AzureAd:Authority"], ValidateAudience = true, ValidAudience = _config["AzureAd:ClientId"], ValidateLifetime = true, IssuerSigningKeys = await GetSigningKeysAsync(_config["AzureAd:Authority"]) }; // 验证令牌并生成ClaimsPrincipal var handler = new JwtSecurityTokenHandler(); ClaimsPrincipal userPrincipal = handler.ValidateToken(request.IdToken, validationParams, out _); // 创建Cookie会话,和原有认证流程共享会话机制 await HttpContext.SignInAsync( CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties { IsPersistent = false }); return Ok(); } catch (Exception ex) { _logger.LogError(ex, "令牌验证失败"); return BadRequest("无效的身份令牌"); } } // 弹窗回调页面(MSAL弹窗完成后会跳转至此,可直接关闭) [AllowAnonymous] [Route("popup-callback")] public IActionResult PopupCallback() { return Content("登录完成,请关闭此窗口"); } // 辅助方法:获取Azure AD的签名密钥 private async Task<IEnumerable<SecurityKey>> GetSigningKeysAsync(string authority) { var configManager = new ConfigurationManager<OpenIdConnectConfiguration>( $"{authority}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever()); var config = await configManager.GetConfigurationAsync(CancellationToken.None); return config.SigningKeys; } } // 接收前端令牌的请求模型 public class TokenRequest { public string IdToken { get; set; } }
3. 调整Azure AD应用注册配置
在Azure门户的应用注册中,添加前端配置的redirectUri(比如https://your-app.azurewebsites.net/auth/popup-callback或本地测试地址),并确保应用注册允许公共客户端流(在"身份验证" -> "高级设置"中开启"允许公共客户端流")。
4. 保留原有认证流程的兼容性
你的现有Startup.cs代码无需大幅修改,AddMicrosoftIdentityWebAppAuthentication已经默认配置了Cookie认证,两种登录模式会共享同一个会话机制。如果需要同时保留原有的重定向登录模式,只需保留原有的登录入口即可。
内容的提问来源于stack exchange,提问作者Ken Newman
相关产品推荐
相关产品推荐

