Question

Where do I get information about the currently connected user? That is, how does shibboleth pass the information?

Can I set some restrictions on actions using [Authorize] attribute based on data acquired from shibboleth?

Was it helpful?

Solution

Shibboleth publishes user attributes associated with sessions into HTTP request headers, based on header names defined in Attribute Acceptance Policy (1.3.x) or Attribute Mapping (2.x) files. These headers are transformed into CGI variables based on mapping rules defined by the CGI specification.

You should be aware of this security advisory: http://shibboleth.net/community/advisories/secadv_20090615.txt

OTHER TIPS

I have never user shibboleth, but you can get information about the user from Controller.User property. It will return a generic principal of current thread. Using this principal you can check whether the user is authenticated and get a login name of the user. This is due to the reason that after logon an authentication cookie is set and this cookie contains limited amount of information. And on each request after logon only this cookie is checked (if it exists and valid - user is authenticated).
So if you need in some specific information you can manually load a user (it's better to use cache here) and check whatever you want.
Also you can create and attach your own principal with necessary information to the thread on start of a request (e.g. on start of a request load the user from db/cache using user name from base principal, create and set your own principal to thread). After this you can check all properties of the user you need.

Where would you attach your own principal? You say on the start of the request but what if you don't want every request authorizing?

You'll want to create a method in Global.asax.cs that has the following signature

protected void Application_PostAuthenticateRequest()
{
    //Your code here.
}

This will be called automatically before almost anything else is done (MVC will call this method if it exists, you don't have to "turn it on" anywhere), and this is where you need to set the Principal. For instance, let's assume you have a header called RolesHeader that has a comma separated value of roles and another header called UserId that has (duh) the user ID.

Your code, without any error handling, might look something like:

protected void Application_PostAuthenticateRequest()
{
    var rolesheader = Context.Request.Headers["RolesHeader"];
    var userId = Context.Request.Headers["UserId"];
    var roles = rolesheader.Split(',');
    var principal = new GenericPrincipal(new GenericIdentity(userId), roles);
    Context.User = principal;
}

It's the Principal/Identity that the [Authorize] attribute uses, so setting it here at the beginning of the request lifecycle means the [Authorize] attribute will work correctly.

The rest of this is optional, but I recommend it:

I like to create my own custom classes that implement IPrincipal and IIdentity instead of using the GenericPrincipal and GenericIdentity, so I can stuff more user information in it. My custom Principal and Identity objects then have much more rich information, such as branch numbers or email addresses or whatever.

Then, I create a Controller called BaseController that has the following

protected new CustomPrincipal User
{
    get
    {
        return (base.User as CustomPrincipal) ?? CustomPrincipal.GetUnauthorizedPrincipal();
    }
}

This allows me to access all my rich, custom Principal data instead of just what's defined in IPrincipal. All of my real controllers then inherit from BaseController instead of directly from Controller.

Obviously, when using a custom Principal like this, in the Application_PostAuthenticateRequest() method, you'd set the Context.User to be your CustomPrincipal instead of a GenericPrincipal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top