19

I'm using ServiceStack Authentication with ServiceStack.OrmLite (SqlServer). I have different User types like Student, Teacher, Principal.. All user types will have relation with other Db Tables. What is the best practise to implement it?

A) Add necessary fields to UserAuth table and make Black Magic.(After creation of UserAuth add necessary extra informations to table Manually)

B) Student:UserAuth (All fields in UserAuth will be cloned)

C) Student.UserAuthId, UserAuth.Meta[UserType.Student,StudentId] mutual-reference

D) Extend XService, XFeature or ??

PS: How about to add Owner and Type fields to ServiceStack UserAuth table.

Oguz Karadenizli
  • 3,449
  • 6
  • 38
  • 73

1 Answers1

26

There are a couple of strategies to append additional metadata to the UserAuth and UserAuthDetails tables,

If you want to extend the schema of UserAuth with your own custom POCO's you need to subclass OrmLiteAuthRepository<T,T> class including your custom POCO's, e.g see the source for OrmLiteAuthRepository:

public class OrmLiteAuthRepository 
    : OrmLiteAuthRepository<UserAuth, UserAuthDetails>, IUserAuthRepository
{
    public OrmLiteAuthRepository(IDbConnectionFactory dbFactory) 
        : base(dbFactory) { }
}

Extend UserAuthSession with your own typed Custom Session

At the same time extending and providing a typed, custom AuthUserSession is the recommended approach as it's supported by ServiceStack's Authentication Feature since the Users Session just gets blobbed in a Caching Provider (i.e. not in an RDBMS) where its schema-less persistance characteristics, easily supports extended types.

Adding additional metadata to the Meta dictionary fields

For minor extensions you can use the Meta string dictionaries fields on each table which were added specifically to support custom-held metadata. They also include useful Get<T> and Set<T> methods which also support blobbing complex types:

userAuth.Set(new Address { ... });
var address = userAuth.Get<Address>();

Linking referential data with RefId and RefIdStr fields

The UserAuth and UserAuthDetails tables also include an int? RefId and a string RefIdStr fields which you can use to reference external data like your own custom tables against each User Auth record or User OAuth registration.

Extracting UserAuth info into your own custom tables

Another option is to do what the SocialBootstrapApi example demo is doing and extract the UserAuth info into your own custom tables by overriding the OnAuthenticated hook in your own custom UserSession which get's called each time a user successfully authenticates.

Here's the SocialBootstrapApi example of copying the session data into a custom user POCO and saving it in a different table.

public class CustomUserSession : AuthUserSession
{
    public string CustomId { get; set; }

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, 
        IAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        base.OnAuthenticated(authService, session, tokens, authInfo);

        //Populate all matching fields from this session to your own custom User table
        var user = session.TranslateTo<User>();
        user.Id = int.Parse(session.UserAuthId);
        user.GravatarImageUrl64 = !session.Email.IsNullOrEmpty()
            ? CreateGravatarUrl(session.Email, 64)
            : null;

        //Resolve the DbFactory from the IOC and persist the user info
        using (var db = authService.TryResolve<IDbConnectionFactory>().Open())
        {
            db.Save(user);
        }
    }
}
Bjarki Heiðar
  • 3,117
  • 6
  • 27
  • 40
mythz
  • 141,670
  • 29
  • 246
  • 390
  • 5
    I've investigated a little deeply.Overriding OrmLiteAuthRepository seems more effective. Because I can create or update both UserAuth and my own tables transactionally. In socialbootstrap, when client registers, UserAuth is created but User not. User is created via "Sign In". What is your suggestion: Do I write my own OrmLiteAuthRepository or Extend ServiceStack's. (If answer is "extend" please make methods Virtual :) ) – Oguz Karadenizli Jun 20 '12 at 13:03
  • I was planning to write my own (SessionFeature, AuthFeature, RegistrationFeature). But it is so expensive. I will use ServiceStack's UserAuth for this project and Meta field of it. – Oguz Karadenizli Jun 26 '12 at 00:03
  • 1
    @mythz I know this is an old answer, but quick question. What's the difference between *UserAuth* and *UserAuthDetails*, if I want to add extend the user table, do I need to add the same extra properties to both? – JMK Jun 10 '15 at 10:18
  • 1
    @JMK It's a 1 to Many relationship where UserAuth = Combined/Summary User Info whilst UserAuthDetails = Login Details for a single OAuth provider (e.g. twitter, facebook, etc). You don't need to extend both tables. – mythz Jun 10 '15 at 16:25