也就是说在 401 状态码的情况下,会获取 _context.Authentication.AuthenticationResponseChallenge 对象时候为 null ,并不是客户端配置项,最后突然想到可能是 Idsrv 的拦截器里配置的(https://github.com/IdentityServer/IdentityServer3.Extensions.Mvc/blob/master/source/IdentityServer3.Extensions.Mvc/IdentityServer3.Extensions.Mvc/Filters/IdentityServerFullLoginAttribute.cs)
public class IdentityServerFullLoginAttribute : OwinAuthenticationAttribute
{
public IdentityServerFullLoginAttribute()
:base(Constants.PrimaryAuthenticationType)
{
this.Order = 1;
}
public override void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
var statusCodeResult = filterContext.Result as HttpStatusCodeResult;
if (statusCodeResult != null && statusCodeResult.StatusCode == 401)
{
var ctx = filterContext.HttpContext.Request.GetOwinContext();
var url = ctx.Environment.CreateSignInRequest(new SignInMessage
{
ReturnUrl= filterContext.HttpContext.Request.Url.AbsoluteUri
});
filterContext.Result= new RedirectResult(url);
}
}
}
1.) 客户单强制设置返回 302 与 URL 或 强制给 Properties.RedirectUri 赋值
public class Startup
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// 启动类配置
/// </summary>
/// <param></param>
public void Configuration(IAppBuilder app)
{
//忽略SSL证书,安全验证
//ServicePointManager.ServerCertificateValidationCallback += delegate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
//{
// return true;
//};
// configuring Redis
GlobalHost.DependencyResolver.UseRedis(new RedisScaleoutConfiguration(CacheSetting.Redis, "SignalR") { Database = 3 });
//configuring the OpenID Connect authentication middleware
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType= "Cookies",
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
// Set expiration time to 8 hours
ProtocolValidator = new OpenIdConnectProtocolValidator()
{
NonceLifetime= new TimeSpan(0, 8, 0, 0)
},
Authority= IdsvSetting.Authority,
ClientId= IdsvSetting.ClientId,
Scope= "openid profile",
ResponseType= "id_token token",
RedirectUri= IdsvSetting.RedirectUri,
SignInAsAuthenticationType= "Cookies",
UseTokenLifetime= false,
Notifications= new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated= async n =>
{
try
{
var id = n.AuthenticationTicket.Identity;
var nid = new ClaimsIdentity(id.AuthenticationType);
// keep the id_token for logout
nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
// add access token for sample API
nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));
// keep track of access token expiration
nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));
//获得用户信息
// var client = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);
//var userInfo = await client.GetAsync();
//var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8);
var userInfoClient = new UserInfoClient(new Uri(n.Options.Authority + "/connect/userinfo"), n.ProtocolMessage.AccessToken);
var userInfo = await userInfoClient.GetAsync();
var user = userInfo.JsonObject.Last.First.ToString().DeserializeJson<XHotelOAuth2UserInfoResponse>(System.Text.Encoding.UTF8);
...
n.AuthenticationTicket= new AuthenticationTicket(nid, n.AuthenticationTicket.Properties);
////清空 OpenIdConnect 开头的 Cookies
foreach (var item in HttpContext.Current.Request.Cookies.AllKeys)
{
if (item.Contains("OpenIdConnect", StringComparison.OrdinalIgnoreCase))
{
HttpCookie cookie= HttpContext.Current.Request.Cookies[item];
cookie.Expires= DateTime.Now.AddDays(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
}
}
HttpContext.Current.Response.AddHeader("Location", IdsvSetting.RedirectUri);
}
catch (Exception ex)
{
ex.ToExceptionless().MarkAsCritical().Submit();
logger.Error(ex,"UseOpenIdConnectAuthentication:" + ex.Message);
}
},
RedirectToIdentityProvider= n =>
{
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
{
n.ProtocolMessage.IdTokenHint= idTokenHint.Value;
}
}
return Task.FromResult(0);
},
AuthenticationFailed= (context) =>
{
if (context.Exception is OpenIdConnectProtocolInvalidNonceException && context.Exception.Message.ContainsAny(new string[] { "IDX10316", "IDX10311" }))
{
logger.Warn("OpenIdConnectProtocolInvalidNonce expired, reauthenticating...");
context.HandleResponse();
//context.Response.Redirect("/Error.aspx?message=" + context.Exception.Message);
context.Response.Redirect(context.Request.Uri.PathAndQuery);
}
return Task.FromResult(0);
},
}
});
}
}
2.) MVC 拦截器里设置 Properties.RedirectUri