Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceStack with forms authentication across applications fails...why?

I have a ServiceStack project running an API at api.mydomain.com. An admin project in the same solution is hosted at admin.mydomain.com. Login/Logout is already handled by the admin application, but I want to make sure the user is authenticated (and sometimes check permissions as well) on my api calls. I'm using forms authentication across projects so the auth cookie is available to my api project.

Here's my web.config authentication tag in the api project:

<authentication mode="Forms">
  <forms protection="All" loginUrl="home/denied" slidingExpiration="true" timeout="60" defaultUrl="home/denied" path="/" domain="mydomain.com" name=".myAuth"></forms>
</authentication>

Based on this Authentication and authorization post, I added an [Authenticate] attribute to a service method, expecting it to pass/fail based on the value of IsAuthenticated. However, it redirects to 'home/denied' everytime, regardless of whether the auth cookie is present. (I confirmed this by subclassing AuthenticateAttribute and examining the OriginalRequest... The cookie set when I logged in using the admin app is present and req.OriginalRequest.IsAuthenticated is true.)

Why is my request being redirected, and how do I properly utilize the existing auth credential set in the admin app?

EDIT: Here's the solution I came up with. It simply requires an IPrincipal Identity to pass authentication.

public class AuthenticateAspNetAttribute : RequestFilterAttribute
{
    public override void Execute(IHttpRequest req, IHttpResponse res, object requestDto)
    {
        SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId()

        using (var cache = req.GetCacheClient())
        {
            var sessionId = req.GetSessionId();
            var session = sessionId != null ? cache.GetSession(sessionId) : null;
            var originalRequest = (System.Web.HttpRequest) req.OriginalRequest;
            var identity = originalRequest.RequestContext.HttpContext.User.Identity;
            if (!identity.IsAuthenticated)
                AuthProvider.HandleFailedAuth(new BasicAuthProvider(), session, req, res);

        }
    }
}
like image 724
John Mathis Avatar asked Oct 07 '22 22:10

John Mathis


1 Answers

On the Authentication and autorization post you reference it reads:

ServiceStack's Authentication, Caching and Session providers are completely new, clean, dependency-free testable APIs that doesn't rely on and is devoid of ASP.NET's existing membership, caching or session provider models.

Meaning it's completely separate and has nothing to do with the ASP.NET's existing Authentication providers. i.e. The client needs to make an explicit call to the /auth service to authenticate with ServiceStack web services.

See the SocialBootstrapApi example demo project for an example of an MVC Website that uses and shares ServiceStack's Authentication providers between MVC Controllers and ServiceStack web services.

like image 147
mythz Avatar answered Oct 10 '22 04:10

mythz