0

This is a two part issue that resolves around a single objective: Get DynamoDB to work with ServiceStack (particularly, as a Session State Provider, and as an Authentication Provider).

..:: Requirements ::..

What I must do:

  1. Use DynamoDB for Session & Credentials Management (an ASP.NET Identity 2.0 implementation)
  2. Use ServiceStack 4.0.32 Authentication for 3rd party Federation Identity support
  3. Get everything to work on a single web server (either in parallel or co-operatively)

What I have:

  • Amazon Web Services DLL for Session Management (DynamoDBSessionStoreProvider)
  • Custom ASP.NET Identity 2.0 Implementation for DynamoDB
  • ServiceStack 4.0.32 license and working example of 3rd party Federation

..:: Session State ::..

I am using a DynamoDBSessionStoreProvider as per the Amazon Documentation.

This works fine as a web.Config solution until I try to use it with Service Stack, which wires Session Providers up in code:

Plugins.Add(new AuthFeature(() => new CustomUserSession(),
                new IAuthProvider[] {
                    new CredentialsAuthProvider(appSettings),  
                    new BasicAuthProvider(appSettings)
            }));

I understand that CustomUserSession should inherit from AuthUserSession and override methods of interest as indicated in the ServiceStack SocialBootstrapAPI documentation, but first I tried to access the DynamoDBSessionStateStore directly:

Plugins.Add(new AuthFeature(
                () => new DynamoDBSessionStateStore(),
                new IAuthProvider[] { 
                    new CredentialsAuthProvider(appSettings), 
                    new BasicAuthProvider()
            }));

Obviously, this is an issue since DynamoDBSessionStateStore does not implement ServiceStack's IAuthProvider nor inherit from their AuthUserSession concrete implementation. However, this is ultimately what I want.

So, I'm now back to my CustomUserSession, which extends AuthUserSession, but I am having issues getting exposure of DynamoDBSessionStateStore in the way ServiceStack expects.

What is going on is that ServiceStack is creating its own session cookies ss-pid while the custom session provider I've developed is using the .NET Identity session. So, my question is this; given the latest ServiceStack 4.0.32 updates, should I conform my custom provider to use ss-pid or should I somehow get ServiceStack to recognize my custom provider via implementation of AuthUserSession?

..:: Authentication ::..

I am using a custom ASP.NET Identity 2.0 implementation (a full Microsoft.AspNet.Identity implementation) for DynamoDB based strongly on this project found on codeplex. I've made a number of alterations, but the core is basically the same.

The implementation makes use of the IdentityUser, IdentityRole, IdentityUserClaim, and IdentityCloudContext, etc. portions of Identity 2.0 and wraps them into a UserStore and RoleStore.

My question is mostly in regards to the ServiceStack 4.0.32 updates. How should I get these two elements to play together? How can I make the UserStore and RoleStore play nice with ServiceStack Authentication? Implement a series of IAuthProviders?

Perhaps @mythz or someone else in the ServiceStack community will make use of the same DynamoDB ASP.NET Identity 2.0 implementation to start a collective (ServiceStack sanctioned) development project path that we all can agree on and contribute to.

Rick
  • 325
  • 1
  • 7

1 Answers1

1

The DynamoDBSessionStateStore is not compatible with AuthUserSession in functionality or concept.

AuthUserSession is just your typed Custom User Session, i.e. predominantly a POCO that gets stored in your preferred Caching Provider. One of the Caching providers available is ServiceStack.Caching.AwsDynamoDb, but this just takes care of serializing the users Session into AWS DynamoDb, i.e. AuthUserSession doesn't provide authentication itself or even take care of where or how to serialize your Session, just what to serialize, as such it should remain a plain-old Data object (POCO).

The relevant moving parts in ServiceStack Authentication are the Auth Providers which take care of how to Authenticate that by default will access the configured Auth Repository where User Auth Info is typically persisted. Once authenticated an instance of the AuthUserSession is created for the authenticated user which is stored with the registered ICacheClient Caching Provider.

Customizing User Roles and Permissions

The default implementation of User Roles and Permissions on AuthUserSession shows how ServiceStack's [RequiredRole] and [RequiredPermission] Roles and Permission attributes are validated:

public virtual bool HasPermission(string permission)
{
    var managesRoles = HostContext.TryResolve<IAuthRepository>() as IManageRoles;
    if (managesRoles != null)
    {
        return managesRoles.HasPermission(this.UserAuthId, permission);
    }

    return this.Permissions != null && this.Permissions.Contains(permission);
}

public virtual bool HasRole(string role)
{
    var managesRoles = HostContext.TryResolve<IAuthRepository>() as IManageRoles;
    if (managesRoles != null)
    {
        return managesRoles.HasRole(this.UserAuthId, role);
    }

    return this.Roles != null && this.Roles.Contains(role);
}

These APIs are virtual so they can be overridden in both your Custom AuthUserSession but they default to looking at the Roles and Permissions collections stored on the Session. These collections are normally sourced from the AuthUserRepository when persisting the UserAuth and UserAuthDetails POCO's and are used to populate the UserAuthSession on successful Authentication. These collections can be further customized by AuthProviders which is what AspNetWindowsAuthProvider does to add Authenticated WindowsAuth Roles.

As seen above Roles/Permissions can instead be managed by AuthProviders that implement IManageRoles API which is what OrmLiteAuthProvider uses to look at distinct RDBMS tables to validate Roles/Permissions.

AWS Support

The missing piece for an AWS backed Authentication is an DynamoDB-based UserAuthRepository. A ServiceStack.AmazonWebServices placeholder repository has been created to store the necessary functionality. Filling in the missing pieces for AWS is on our TODO list but due to lower demand it's currently a lower priority.

One thing to note is that ServiceStack Authentication only includes functionality and filter attributes for Roles/Permissions. Any additional functionality like User Claims would need to be implemented with Custom logic added to ServiceStack's customizable Request Pipeline.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • So, what I'm reading is that ServiceStack doesn't support ASP.NET Identity 2.0 Implementations. In other words, in order for an ASP.NET Identity Implementation to work it must have a ServerStack flavor. I thought the 4.0.32 updates made you less 'ServiceStack vs. the world'. Looks like my only resort is to disable ServiceStack Session and Authentication altogether as they don't play nice with the ASP.NET standards. – Rick Oct 20 '14 at 13:53
  • @Rick ServiceStack has always had it's own Authentication AuthProvider model. The AspNetWindowsAuthProvider is just another AuthProvider that allows users to be authenticated via Windows Auth. It's an additional AuthProvider, it's not abandoning the existing model. Right, if you wanted to use an alternative authentication model you wouldn't register ServiceStack's `AuthFeature` plugin (i.e. it's not enabled by default) and add your own custom validation instead. – mythz Oct 20 '14 at 18:41
  • So, I have two requirements: (1) Use a DynamoDB for Session & Credentials Management (a username & password model based on Identity 2.0), and (2) Use ServiceStack 4.0.32 Authentication for 3rd party Federation Identity support. Are you saying there is absolutely no pathway to connect these implementations to ServiceStack? I may have to build a MongoDB, CouchDB, or Riak implementation in the near future. I would hope I could add these as CredentialsAuthProviders and then be able to plug them into ServiceStack for management. As you may know, the response 'impossible' is somewhat bothersome. – Rick Oct 21 '14 at 13:50
  • @Rick I've only said a DynamoDB-based AuthRepository doesn't yet exist not that it's impossible. I've also explained the different providers that SS uses for auth, and that each component is pluggable and there are several impls of each. Ideally I'd try add what I need as a new AuthProvider, hopefully the existing [OpenIdOAuthProvider](http://bit.ly/1pycsl3) or [GoogleOAuth2Provider](http://bit.ly/1s4y7B8) can help with the impl. The [IAuthProvider](http://bit.ly/ZN1tgV) API is very liberal that allows freedom within impl, just needs to save a typed Session with `session.IsAuthenticated=true`. – mythz Oct 21 '14 at 21:43
  • My intent was not to be negative or pessimistic. I'm trying to understand what a deeper commitment to ServiceStack might imply in terms of use boundaries and range of extensibility. Also, I have very little experience with authentication outside B2B single sign-on, so I do not quite get your initial phrase 'not compatible in functionality or concept'. It appears that the IAuthProvider API is the avenue I'll need to go to achieve what I need. Half the skill of surgery is knowing how deep to cut. IAuthProvider is a deep incision, but it's doable. Gotcha. – Rick Oct 22 '14 at 15:22
  • @Rick I've only said that the typed `AuthUserSession` (that you're trying to replace) is not functionally equivalent or compatible with a Session or Auth Provider since it's only a data model. But yeah you're on the right track with a custom `IAuthProvider`. – mythz Oct 22 '14 at 20:00