1

I am creating one web app in asp.net MVC with identity (OWIN) framework. Now it will be hosted in one domain lets say domain.com

Now i want to host servicestack on sub domain lets say service.domain.com

Now any user who login in domain.com with username and password and if it success then i want to authenticate servicestack too so that all services with [Authenticate] attribute will work.

The primary objective of hosting servicestack on subdomain is to make code independent for database side.

And i can easily call this REST api in my future Android and iOS app.

Is it something wrong i am doing?

I have tried with code provided by mythz but now i get this error AuthKey required to use: HS256

My MVC code is (running on: localhost:51055)

    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);

    switch (result)
    {
           case SignInStatus.Success:
           {
                var jwtProvider = new JwtAuthProvider();

                        var header = JwtAuthProvider.CreateJwtHeader(jwtProvider.HashAlgorithm);
                        var body = JwtAuthProvider.CreateJwtPayload(new AuthUserSession
                        {
                            UserAuthId = user.Id,
                            DisplayName = user.NameSurname,
                            Email = user.Email,
                            IsAuthenticated = true,
                        },
                            issuer: jwtProvider.Issuer,
                            expireIn: jwtProvider.ExpireTokensIn,
                            audience: jwtProvider.Audience,
                            roles: new[] { "TheRole" },
                            permissions: new[] { "ThePermission" });

                        var jwtToken = JwtAuthProvider.CreateJwt(header, body, jwtProvider.GetHashAlgorithm());

                        var client = new JsonServiceClient("http://localhost:52893/");
                        client.SetTokenCookie(jwtToken);

          }
    }

error occured on this statement jwtProvider.GetHashAlgorithm()

Any my servicestack code is (running on: localhost:52893)

public class AppHost : AppHostBase
    {
        public AppHost() : base("MVC 4", typeof(HelloService).Assembly) { }

        public override void Configure(Funq.Container container)
        {
            SetConfig(new HostConfig
            {
                RestrictAllCookiesToDomain = "localhost",
                HandlerFactoryPath = "api",
                DebugMode = true
            });

Plugins.Add(new AuthFeature(() => new AuthUserSession(),
                new IAuthProvider[] {
                    new JwtAuthProviderReader(AppSettings) {
                        AuthKey = AesUtils.CreateKey(),
                        HashAlgorithm = "RS256"
                    },
                }));

            Plugins.Add(new CorsFeature(
                    allowOriginWhitelist: new[] {
                        "http://localhost",
                        "http://localhost:51055"
                    },
                    allowCredentials: true,
                    allowedMethods: "GET, POST, PUT, DELETE, OPTIONS",
                    allowedHeaders: "Content-Type, Allow, Authorization, Wait, Accept, X-Requested-With, Put-Default-Position, Put-Before, If-Match, If-None-Match, Content-Range",
                    exposeHeaders: "Content-Range"
                ));

        }
}

Is something wrong i am doing?

1 Answers1

0

You're looking to integrate 2 different frameworks together by using Authentication from MVC (OWIN) with ServiceStack - an isolated framework that doesn't have any coupling or knowledge of OWIN or MVC's Authentication. This is further conflated by trying to transfer Authentication from one domain into a different framework on a different sub domain. Usually trying to try integrate Authentication between completely different frameworks is a difficult endeavor and requiring it to work across sub-domains adds even more complexity.

Storing an Authenticate User Session

With that said the 2 easiest solutions that can work is to store an authenticated UserSession in ServiceStack by serializing an AuthUserSession into the location which ServiceStack expects by using the same distributed Caching Provider configured on both MVC and ServiceStack Apps.

So you can configure ServiceStack to use a Redis CacheClient you can create and store a UserSession in MVC:

var session = new AuthUserSession {
    UserAuthId = userId,
    DisplayName = userName,
    Email = userEmail,
    IsAuthenticated = true,
};

Then save it using the configured Redis Manager in MVC:

var sessionId = SessionExtensions.CreateRandomSessionId();
using (var redis = redisManager.GetClient())
{
    redis.Set($"urn:iauthsession:{sessionId}", session);
}

To get ServiceStack to use this Authenticated UserSession you need to configure the ss-id Session Cookie Id with sessionId and since you want the client to send the same Cookie to sub-domain you need to configure the Cookie to use a wildcard domain.

Using JWT

The alternative (and my preferred solution) that doesn't require sharing any infrastructure dependencies is to use a stateless JWT Token which encapsulates the Users Session in a JWT Token. To do this in MVC you would create a JWT Token from an Authenticated User Session which you can send to a ServiceStack AppHost configured with the same JwtAuthProvider.

Clients can then make Authenticated Requests by sending JWT Tokens in the JWT Cookie, i.e. sending the JWT Token in the ss-tok cookie which to work across sub-domains needs to be configured to use the same wildcard domain as above.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • As you may know the primary objective to use servicestack is that my database side code resides in servicestack (hosted in sub domain). So that i can easily call this in my web, android, ios and window app. Currently i used servicestack.MVC in my asp.net mvc project. So when user signin and if success then it will authenticate servicestack too. and when user logout then i will logout too from servicestack. – Soheb Rapati Aug 14 '17 at 02:59
  • @SohebRapati please read the [JWT documentation](http://docs.servicestack.net/jwt-authprovider) carefully, your JwtAuthProvider is not properly configured and you need to use the **exact configuration** on both MVC and ServiceStack, i.e. you can't use an in memory `AesUtils.CreateKey()` as per the first paragraph in the JWT docs. – mythz Aug 14 '17 at 15:43
  • @SohebRapati If you're still unsure check out the [JwtAuthProviderTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/UseCases/JwtAuthProviderTests.cs) and [StatelessAuthTests.cs](https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.Server.Tests/Auth/StatelessAuthTests.cs) for working examples. – mythz Aug 14 '17 at 15:44