0

I'm encountering an issue where I can observe an infinite redirect loop. My project is based on the official MS example - active-directory-b2c-dotnet-webapp-and-webapi

Does "Redirect URI" (defined in Azure Portal) have to be publicly accessible endpoint?

What would happen if in my controller I decorated it with an [Authorize] attribute?

So basically in this example Redirect Uri (set as website root, i.e. localhost:1234/) would also be a route for an action in the controller, which requires authorization.

[Authorize]
public class ControllerA : Controller
{
    [Route("~/")]
    public ActionResult Index()
    {
    }
}

Could it cause an infinite redirect loop?

Removing the route attribute fixes the problem, but at the same time, I feel like it's not a real cause of the issue.

I imagine that OWIN authorization is higher in the application stack compared to the controller's authorization, so I think that OWIN authorization middle-ware would parse the response from Azure Ad in a first place, instead of enforcing [Authorize] attribute policy and rejecting it upfront.

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
Chris
  • 36
  • 1
  • 5
  • The redirect uri registered in the portal usually refers to a path handled directly by the auth middleware, not an MVC controller. – Tratcher Mar 27 '18 at 17:19

2 Answers2

1

You can certainly create an infinite loop scenario this way but it will end up short-circuited by Azure AD. After a few loops, it will stop redirecting back and surface an error.

The redirect_uri needn't be a publicly accessible URI, it will work with http://localhost for example. It need only be accessible by the client. After all, a "redirect" is simply an HTTP response issued by the server. It is actually executed by the client.

In general, the controller you're using for authorization (i.e. receiving the redirect) shouldn't be decorated by an [Authorize] at the class level. Typically you would only decorate the handful of methods that require a signed in user. That said, you could certainly decorate the class with [Authorize] so long as you decorate your callback endpoint with [AllowAnonymous].

Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • After more debugging it turns out that after every application restart first log in attempt always work (even with current set up), only following requests start to trigger infinite loop. This behavior doesn't seem to be caused by leftover cookies, as I tested it across multiple browsers always in incognito mode. At this point it must be another issue in my code - I'm going to spend more time debugging. – Chris Mar 28 '18 at 09:21
  • Apparently just adding `protected void Session_Start()` method in Global.asax suggested in this [answer](https://stackoverflow.com/a/47599064/9558470) seems to resolve the problem, which makes me believe it must be some obscure issue with cookies handling inside OWIN Authentication middle-ware. This seems to be quite an old issue, but upgrading whole OWIN stack from 3.0.0 to 4.0.0 doesn't fix it. – Chris Mar 28 '18 at 09:48
0

The core of the problem and solutions are described in following document - System.Web response cookie integration issues. I've implemented 3rd solution (reconfigure the CookieAuthenticationMiddleware to write directly to System.Web's cookie collection) and it has resolved the issue. What lead me to discover that the cookies were the issue is another StackOverflow's question, which describes a really similar symptoms to the one I was observing.

A fact that the default route [Route("~/")] was mapped to one of the controller's methods which required authorization, and that it was also matching a redirect_uri that I've set up in Azure Portal was not a culprit. In my opinion this is a proof that redirect_uri call will be handled directly by OWIN auth middleware and it won't even reach a controller's method.

Chris
  • 36
  • 1
  • 5