How do I implement custom Principal and Identity in ASP.NET MVC?

Kenji Kina picture Kenji Kina · Jul 18, 2010 · Viewed 22.1k times · Source

I want to store extra information in the authenticated user so that I can have it easily accessible (like User.Identity.Id, for example), instead of just the name, since I'm planning on having that non-unique.

So far I've gathered that I should look to implement custom Principal and/or Identity, but I'm not sure how to go about it. I've been looking for documentation and tutorials on the matter, but I've found related stuff in different places and I've found it a bit confusing.

I have seen how to add custom info to the authentication cookie in the user data property, but I'd like to have the benefit of dependency injection for unit testing, which I can have with the principal and identity.

What are the exact steps I need to consider if I want to implement my own Principal or Identity?

What would be the simplest I could do in this scenario (just add the ID and keep all the defaults in place)? "Defaults" would include the default providers (membership, roles, etc.).

I have seen the other question, but I'd appreciate answers that do not leave any holes in between, such as the roles magic strings in the AuthenticateRequest event in the examples. Instead I need to know how to add the roles from the default SqlRoleProvider to the current user: when and where to do it, and if I need to do anything else to connect my new classes with the other default providers.

It'd be awesome to be able to go to a sample ASP.NET MVC 2 application (from the visual studio 2010 template, for example), make the edits and have it work.


EDIT: I have edited the question to better show that I'm pretty much lost here, so I can't make do with too high level answers.

P.S.: It seems to me that it makes more sense to have the ID in the Identity instead of the principal, although I have, in a way, stated this before.

Answer

Seth Reno picture Seth Reno · Jul 30, 2010

This question has been asked and answered before: ASP.NET MVC - Set custom IIdentity or IPrincipal

But to summarize...

Crate a custom principal class with the additional properites you want to store:

Public Class CustomPrincipal
    Inherits System.Security.Principal.GenericPrincipal

    Private _eyeColor As String
    Public ReadOnly Property EyeColor As String
        Get
            Return _eyeColor
        End Get
    End Property

    Public Sub New(id As System.Security.Principal.IIdentity, roles As String(), eyeColor As String)
        MyBase.New(id, roles)
        _eyeColor = eyeColor            
    End Sub

End Class

Modify global.asax Global.Application_AuthenticateRequest to use your custom principal:

Protected Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As System.EventArgs)
    ...
    Dim roles() As String = {"examplerole"}         
    Context.User = new CustomPrincipal(Context.User.Identity, roles, "green")
End Sub

Then elsewhere in your code when you want to refer to one of these properties do this:

CType(My.User.CurrentPrincipal, CustomPrincipal).EyeColor