通过OpenId Connect身份验证传递查询字符串参数

时间:2016-04-27 09:14:01

标签: c# asp.net azure authentication owin

让我用一点结构来解决问题。

上下文

我们使用Web窗体构建Web应用程序并托管在Azure Web App中,该应用程序使用OWIN + OpenId Connect标准针对Azure Active Directory对用户进行身份验证。

身份验证过程就像魅力一样,用户可以毫无问题地访问应用程序。

那么,问题是什么?

经过多天的努力,我无法通过身份验证过程将任何查询字符串参数传递给应用程序。例如,如果我是第一次尝试通过URL访问应用程序:https://myapp.azurewebsites.net/Default.aspx?param=value。我需要传递此参数的原因是它会在主页面中触发一些特定的操作。

问题是,在身份验证重定向到webapp的主页面后,请求的原始查询字符串参数消失了。

代码

启动类看起来像这样:

app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = Constants.ADTenant.ClientId,
                    Authority = Constants.ADTenant.Authority,
                    PostLogoutRedirectUri = Constants.ADTenant.PostLogoutRedirectUri,

                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthorizationCodeReceived = context =>
                        {
                            var code = context.Code;

                            ClientCredential credential = new ClientCredential(Constants.ADTenant.ClientId,
                                Constants.ADTenant.AppKey);
                            string userObjectID = context.AuthenticationTicket.Identity.FindFirst(
                                Constants.ADTenant.ObjectIdClaimType).Value;
                            AuthenticationContext authContext = new AuthenticationContext(Constants.ADTenant.Authority,
                                new NaiveSessionCache(userObjectID));
                            if (HttpContext.Current != null)
                            {
                                AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(
                                    code, new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)), credential,
                                    Constants.ADTenant.GraphResourceId);
                                AuthenticationHelper.token = result.AccessToken;
                                AuthenticationHelper.refreshToken = result.RefreshToken;
                            }
                            return Task.FromResult(0);
                        }
                    }
                });

它运作正常!

我已经尝试了什么

我可以通过添加RedirectToIdentityProvider通知的覆盖来访问原始请求Url:

RedirectToIdentityProvider = (context) =>
                        {
                            // Ensure the URI is picked up dynamically from the request;
                            string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase + context.Request.Uri.PathAndQuery;
                            context.ProtocolMessage.RedirectUri = appBaseUrl;
                            return Task.FromResult(0);
                        }

有了这个,我试图强制重定向到包含原始查询字符串参数的主页面,但是在身份验证中断后重定向并陷入无限循环。

我还试过在没有运气的情况下更改Azure AD中应用程序配置的重定向网址。还尝试将查询字符串参数存储在其他位置,但在此过程的早期无法访问Session。

有谁知道我做错了什么?或者我只是要求一些不可能的事情?任何帮助将不胜感激。

非常感谢你!

1 个答案:

答案 0 :(得分:0)

我最近需要做同样的事情。我的解决方案可能不是最复杂的,但简单也不总是坏。

我有两个身份验证过滤器......

  1. 第一个过滤器应用于所有可能在授权之前使用查询字符串参数命中的控制器。它检查主体是否经过身份验证。如果为false,则将完整的url字符串缓存在cookie中。如果为true,它会查找存在的任何cookie并清除它们,仅用于清理。
  2. public class AuthCheckActionFilter : ActionFilterAttribute, IAuthenticationFilter
        {
            public void OnAuthentication(AuthenticationContext filterContext)
            {
                if (!filterContext.Principal.Identity.IsAuthenticated)
                {
    
                    HttpCookie cookie = new HttpCookie("OnAuthenticateAction");
                    cookie.Value = filterContext.HttpContext.Request.Url.OriginalString;
                    filterContext.HttpContext.Response.Cookies.Add(cookie);
    
                }
                else
                {
                    if (filterContext.HttpContext.Request.Cookies.AllKeys.Contains("OnAuthenticateAction"))
                    {
                        HttpCookie cookie = filterContext.HttpContext.Request.Cookies["OnAuthenticateAction"];
                        cookie.Expires = DateTime.Now.AddDays(-1);
                        filterContext.HttpContext.Response.Cookies.Add(cookie);
                    }
                }
            }
    
            public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
            {
    
            }
    
        }
    
    1. 第二个过滤器仅应用于默认登录页面,或者换言之,身份服务器在登录后重定向。第二个过滤器查找cookie,如果存在,则调用cookie值的response.Redirect。
    2.     public class AutoRedirectFilter : ActionFilterAttribute, IAuthenticationFilter
          {
      
              public void OnAuthentication(AuthenticationContext filterContext)
              {
                  if(filterContext.Principal.Identity.IsAuthenticated)
                  {       
                      if(filterContext.HttpContext.Request.Cookies.AllKeys.Contains("OnAuthenticateAction"))
                      {
                          HttpCookie cookie = filterContext.HttpContext.Request.Cookies["OnAuthenticateAction"];
                          filterContext.HttpContext.Response.Redirect(cookie.Value);
                      }
                  }
              }
      
              public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
              {
              }
      
          }