OpenIdConnect 认证启用 HTTPS 回调 RedirectUri 不生效问(5)

也就是说在 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 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7b91b1bdf1bdd009dcd8ec23be92c1d1.html