OWIN and Azure AD HTTPS to HTTP Redirect Loop

扶醉桌前 提交于 2020-01-11 06:01:07

问题


I am very new to OWIN :). I am trying to have a page with an open public area which will allow anonymous over HTTP, and then a restricted section which will require authentication. I'd like not to force the entire site to be HTTPS for general users.

The issue I have is that I receive the following loop:

  1. http://example.com/authenticatedPage -> 302 Redirect to AD login
  2. Login to AD page HTTP 200. Triggers open of the Azure AD link to site.
  3. Link to site identifies that this is an OWIN redirect and does a 302 redirect to http://example.com/authenticatedPage
  4. Go to 1.

I have tried 3 ways of intercepting the redirect in OWIN but nothing seems to work.

If I begin the session by browsing to https://example.com/ then click on the link to authenticatedPage, then the login works as I expect. i.e.

  1. Load https://example.com/authenticatedPage -> 302 redirect to AD
  2. Login to AD -> loads https://example.com/
  3. 302 redirect to https://example.com/authenticatedPage

Is there anyway to fix this without marking my whole site as requiring SSL?


回答1:


The problem is the referrer set by the OIDC middleware in your application. What happens is this:

  1. Enter your application on http://foo.bar and redirect to Identity provider
  2. The IDP/AD redirects to https://foo.bar as configured return URI
  3. Cookie is set by OIDC middleware with Secure flag so for HTTPS only
  4. Middleware redirects to referrer URL which was HTTP
  5. Cookie is not set on HTTP, so back to step 1.

There are multiple solutions to this such as enforcing SSL only, overloading the Authorize attribute and setting the CookieSecure flag to CookieSecureOption.Never (don't do this).

The option I prefer is to fix the Referrer in the middleware itself as such:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = ...
    ClientId = ...
    RedirectUri = "https://foo.bar"
    ResponseType = "id_token",
    Scope = "openid profile",      
    SignInAsAuthenticationType = "Cookies",

    // Deal with the returning tokens
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        AuthorizationCodeReceived = async n =>
        {
            // Enforce the reference/redirect to be HTTPS
            var builder = new UriBuilder(n.AuthenticationTicket.Properties.RedirectUri);
            builder.Scheme = "https";
            builder.Port = 443;
            n.AuthenticationTicket.Properties.RedirectUri = builder.ToString();
        }
    }
});

What this does is rewrite the HTTP on the Referrer URL to HTTPS. This way if the user enters the app on HTTP, he'll be automatically redirected to a HTTPS version after using it.




回答2:


Is there a specific reason for which you don't want to mark the entire site as requiring SSL? There might be ways around the above, but they might be risky. If you expect to have a session cookie for your domain at some point, you want to make sure that it is never sent around without a proper secure channel... and handling the switching between the two is tricky. If you can share the reasons for which you are reluctant in using SSL for the entire app, that would be super useful for us... our current assumption is that it is viable, and so far it seemed to pan out, but there might be something we are overlooking.




回答3:


Assuming I haven't introduced a gaping security hole, this actually worked. Override the authorize attribute and apply this to your controller. If you try to authorise from an insecure page, it will redirect you to the HTTPS:// of the page first, prior to attempting authentication. THis means the redirect from Azure will then redirect back to HTTPS and it works like a charm. Cookies stay secure and everyone's a winner!

using System.Web.Mvc;

namespace Spenceee.Attributes
{
    public class AuthorizeFromHTTPAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (!filterContext.HttpContext.Request.IsSecureConnection)
            {
                UriBuilder redirectUrl = new UriBuilder(
                   filterContext.HttpContext.Request.Url);
                redirectUrl.Scheme = "HTTPS";
                redirectUrl.Port = 443;
                filterContext.HttpContext.Response.Redirect(redirectUrl.ToString());
                return;
            }
            else
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
} 



回答4:


As Vittorio suggests, forcing the entire site to use SSL fixes the issue. Assuming that is a viable scenario for you, just add a global filter in the Application_Start method of Global.asax.cs:

protected void Application_Start()
    {
        GlobalFilters.Filters.Add(new RequireHttpsAttribute());
        ...

Users can now walk up to your app using either HTTP or HTTPS and will be re-routed correctly after authentication without the infinite redirect loop.



来源:https://stackoverflow.com/questions/31588552/owin-and-azure-ad-https-to-http-redirect-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!