如何在iframe中使用Azure AD与OpenID Connect实现SSO
在iframe中嵌入受OpenID Connect SSO保护的Web应用问题
我花了好几个小时寻找在iframe里调用受OpenID Connect SSO保护的Web应用的方法,当前状态:
- 通过iframe访问时,要么跳转到
https://localhost:5001/signin-oidc,要么出现指向https://localhost:5001的错误 - 直接用浏览器访问该应用能正常显示Azure登录界面,但就算先登录再通过iframe访问仍无法正常工作
应用B的配置详情
- 基于Rider默认模板创建
- csproj配置片段:
... <UserSecretsId>SomeGuideWithName</UserSecretsId> <WebProject_DirectoryAccessLevelKey>0</WebProject_DirectoryAccessLevelKey> ...
- App.razor配置:
<CascadingAuthenticationState> <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/> <FocusOnNavigate RouteData="@routeData" Selector="h1"/> </Found> <NotFound> <PageTitle>Not found</PageTitle> <LayoutView Layout="@typeof(MainLayout)"> <p role="alert">Sorry, there's nothing at this address.</p> </LayoutView> </NotFound> </Router> </CascadingAuthenticationState>
- appsettings.json配置:
"AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": "xxx.onmicrosoft.com", "TenantId": "xxx", "ClientId": "xxx", "CallbackPath": "/signin-oidc" }
- Program.cs配置:
using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; using MitAuth.Data; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); builder.Services.AddControllersWithViews() .AddMicrosoftIdentityUI(); builder.Services.AddAuthorization( options => { // By default, all incoming requests will be authorized according to the default policy options.FallbackPolicy = options.DefaultPolicy; } ); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor() .AddMicrosoftIdentityConsentHandler(); builder.Services.AddSingleton<WeatherForecastService>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.Run();
- 生成的Cookies如图所示
咨询问题
- 是否需要重新配置应用B?
- 应用A是否需要进行额外操作?
- 是否需要传递令牌或类似内容?
解决方案
1. 应用B的必要配置调整
(1)修改认证Cookie的SameSite属性
默认情况下ASP.NET Core的认证Cookie为SameSite=Lax,这种模式下Cookie不会在跨域iframe请求中发送,导致应用B无法识别已登录状态。需将其设置为None(必须配合HTTPS使用,因为SameSite=None要求Cookie带Secure属性):
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")) .AddCookie(options => { options.Cookie.SameSite = SameSiteMode.None; options.Cookie.SecurePolicy = CookieSecurePolicy.Always; options.Cookie.IsEssential = true; });
(2)配置CORS允许应用A域名
应用B需要允许来自应用A的跨域请求,在Program.cs中添加CORS配置:
builder.Services.AddCors(options => { options.AddPolicy("AllowAppA", policy => { policy.WithOrigins("https://app-a-domain.com") // 替换为应用A的实际域名 .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); // 在app.UseRouting()之后添加 app.UseCors("AllowAppA");
(3)配置iframe嵌入权限
默认HSTS会添加X-Frame-Options: DENY头阻止嵌入,推荐用Content-Security-Policy精确控制允许嵌入的域名:
app.Use(async (context, next) => { context.Response.Headers.Add("Content-Security-Policy", "frame-ancestors 'self' https://app-a-domain.com"); await next(); });
2. 应用A的操作
应用A只需确保:
- 嵌入iframe的URL为应用B的正确地址
- 自身运行在HTTPS环境下(因为
SameSite=None要求Cookie通过HTTPS传输,跨域iframe请求必须用HTTPS)
无需额外复杂操作。
3. 令牌传递相关
不需要手动传递令牌。应用B基于Cookie认证,只要Cookie配置正确,浏览器会自动在iframe请求中携带认证Cookie,应用B即可识别登录状态。如果后续需要跨应用共享身份,可考虑OAuth2令牌交换,但当前场景无需此操作。
内容的提问来源于stack exchange,提问作者rutim
相关产品推荐
相关产品推荐

