views:

367

answers:

1

I have the following route:

{language}/{controller}.mvc/{action}/{id}

Once a user has choosen the language it is then maintained in the route-value language.

http://localhost%3A4000/de/Account.mvc/Register

I have a problem if a user hits a page that needs auhtorization. He ist then redirected to http://localhost%3A4000/Account.mvc/Login?ReturnUrl=%2fde%2fAccount.mvc%2fProfileData

The login page is configured in web.config and does not allow for a parameter from the route. The page after login is ok (http://localhost%3A4000/de/Account.mvc/ProfileData) but the login-page itself has no route-value language.

How can I fix this?

EDIT

I used the answer of Darin, but had to include all the code from the original Authorize filter (AuthorizeAttribute.cs). The reason is documented in that file. It handles the case where an unauthorized user might get a secured page from the cache.

Here is the comment in the code:

            // ** IMPORTANT **
            // Since we're performing authorization at the action level, the authorization code runs
            // after the output caching module. In the worst case this could allow an authorized user
            // to cause the page to be cached, then an unauthorized user would later be served the
            // cached page. We work around this by telling proxies not to cache the sensitive page,
            // then we hook our custom authorization code into the caching mechanism so that we have
            // the final say on whether a page should be served from the cache.
+5  A: 

The problem with forms authentication is that you cannot have a dynamically configured login url. That's just the way ASP.NET team designed the framework. At some moment FormsAuthentication.RedirectToLoginPage method will be called which will just redirect to the hardcoded url in web.config.

I can see two possible workarounds:

  1. Don't store language in the url but in a cookie
  2. Write a custom ActionFilter that redirects to a dynamically constructed login page if user is not authenticated

Here's an example using a custom attribute:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class RequiresAuthenticationAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        IPrincipal user = filterContext.HttpContext.User;
        if (!user.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectResult("CALCULATE YOUR LOGIN URL HERE FROM ROUTES");
        }
    }
}
Darin Dimitrov
Darin, this works like a charm. I only had to include some extra code from the original Authorize filter.
Malcolm Frexner