我的 Web 应用程序无法使用 OpenIdConnect 进行身份验证。目前我在
OnRemoteFailure
上看到“关联失败”错误。
背景:
启动:
public void ConfigureServices(IServiceCollection services)
{
(...)
services.AddMvc();
(...)
services.AddAuthorization();
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(o =>
{
o.ClientId = clientId;
o.Authority = $"https://login.microsoftonline.com/{tenantId}/{signinPolicy}/v2.0";
o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.SaveTokens = true;
o.Events = new OpenIdConnectEvents
{
OnTokenValidated = async context =>
{
(...)
},
OnRedirectToIdentityProvider = async context =>
{
if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count > 0 &&
context.Request.Headers.TryGetValue("X-Forwarded-Host", out var hostValues) && hostValues.Count > 0 &&
context.Request.Headers.TryGetValue("X-Forwarded-Proto", out var protoValues) && protoValues.Count > 0)
{
// Use external URL and path
string redirectUri = $"{protoValues.First()}://{hostValues.First()}{prefix.First()}{context.Options.CallbackPath}";
context.ProtocolMessage.RedirectUri = redirectUri;
}
},
OnTokenResponseReceived = async context =>
{
},
OnAuthenticationFailed = async context =>
{
},
OnRemoteFailure = async context =>
{
}
};
o.ConfigurationManager = new PolicyConfigurationManager($"https://login.microsoftonline.com/{tenantId}/{signinPolicy}/v2.0",
new[] { signinPolicy });
});
(...)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles();
app.UseAuthentication();
app.Use(async (context, next) =>
{
if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
{
context.Request.PathBase = prefix.First();
}
await next.Invoke();
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
控制器:
public class AccountController : Controller
{
[HttpGet]
public IActionResult SignIn()
{
if (Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
{
return Challenge(new AuthenticationProperties { RedirectUri = prefix.First() }, OpenIdConnectDefaults.AuthenticationScheme);
}
else
{
(...)
}
}
(...)
}
事件
OnTokenValidated
永远不会被触发。
关于反向代理,它基本上将 https://internal_url:port/internal_path 映射到 https://external_url/external_path。
我检查了请求,这是访问的 GET:
https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/authorize?p={signinPolicy}&client_id={clientId}&redirect_uri=https%3A%2F%2F{external_host}%2F{external_path}%2Fsignin-oidc&response_type=id_token&scope=openid%20profile&response_mode=form_post&nonce=(...)&x-client-SKU=ID_NET&x-client-ver=2.1.4.0
成功然后POST请求失败:
https://{external_url}/{external_path}/signin-oidc
此帖子包含表单数据
id_token
和 state
。
B2C 中配置的重定向 URL 为
https://{external_url}/{external_path}/signin-oidc
。我也尝试了https://{external_url}/{external_path}
,但效果不佳。
我尝试使用转发标头,但没有帮助。
谁能指出我缺少的东西吗?
提前致谢!
我发现了问题。问题出在中间件的顺序上。身份验证中间件必须在 PathBase 上的更改之后发生。 在我的情况下不需要转发标头。
遵循固定的
Configure
方法。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.Use(async (context, next) =>
{
if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var prefix) && prefix.Count() > 0)
{
context.Request.PathBase = prefix.First();
}
await next.Invoke();
});
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
我发现使用它可以处理上下文中的所有属性。请求:
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
更多信息:
如果代理不在本地主机上,可能需要更多配置,请参阅:
https://stackoverflow.com/a/75987490
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
});