0

I am trying to implement Shibboleth authentication for a website for my university. The University uses Shibboleth authentication and it is enabled by adding the following in the .htaccess file:

AuthType shibboleth
ShibRequestSetting requireSession 1
Require shib-session

When a user authenticates with the university login, the shib-user attribute is updated to reflect the users identity. I would like to use this information to generate a generic principal and assign it roles associated with that user that are stored in the database. I haven't been able to find much information on Middleware out there and I'm not sure how to accomplish this. Thanks!

jmitten
  • 1
  • 1
  • 3

1 Answers1

1

You have to write an AuthenticationHandler and also add the helper methods to wireup the middleware.

Here's the pseudo code for the same

public static class ShibbolethDefaults
{
    public const string AuthenticationType = "Shibboleth";
}

public class ShibbolethAuthenticationOptions : AuthenticationOptions
{
    /// <summary>
    /// Creates an instance of API Key authentication options with default values.
    /// </summary>
    public ShibbolethAuthenticationOptions()
        : base(ShibbolethDefaults.AuthenticationType)
    {
    }
}

public class ShibbolethAuthenticationHandler : AuthenticationHandler<ShibbolethAuthenticationOptions>
{
    private readonly ILogger logger;

    public ShibbolethAuthenticationHandler(ILogger logger)
    {
        this.logger = logger;
    }

    protected override async Task<Microsoft.Owin.Security.AuthenticationTicket> AuthenticateCoreAsync()
    {
        var properties = new AuthenticationProperties();
        // Find Shibboleth in default location
        string Shibboleth = null;
        //am not sure what header is to be checked for Shibboleth
        string authorization = Request.Headers.Get("Authorization");
        if (!string.IsNullOrEmpty(authorization))
        {
            if (authorization.StartsWith("Shibboleth ", StringComparison.OrdinalIgnoreCase))
            {
                Shibboleth = authorization.Substring("Shibboleth ".Length).Trim();
            }
            else
            {
                this.logger.WriteInformation("Authorization skipped.");

                return new AuthenticationTicket(null, properties);
            }
        }
        else
        {
            this.logger.WriteWarning("Authorization header not found");

            return new AuthenticationTicket(null, properties);
        }

        //here you can read from the headers and add each claims

        var nameClaim = new Claim(ClaimTypes.Name, HttpContext.Current.Request.Headers["principalName"]);
        var givenClaim = new Claim(ClaimTypes.GivenName, HttpContext.Current.Request.Headers["givenName"]);
        var surnameClaim = new Claim(ClaimTypes.SurName, HttpContext.Current.Request.Headers["surname"]);
        var emailClaim = new Claim(ClaimTypes.Email, HttpContext.Current.Request.Headers["email"]);
        var allClaims = Enumerable.Concat(new Claim[] { nameClaim,givenClaim,surnameClaim,emailClaim }, Enumerable.Empty<Claim>());

        var identity = new ClaimsIdentity(allClaims, ShibbolethDefaults.AuthenticationType);
        var principal = new ClaimsPrincipal(new ClaimsIdentity[] { identity });

        // resulting identity values go back to caller
        return new AuthenticationTicket(identity, properties);
    }

}

public class ShibbolethAuthenticationMiddleware : AuthenticationMiddleware<ShibbolethAuthenticationOptions>
{
    private readonly ILogger logger;

    public ShibbolethAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, ShibbolethAuthenticationOptions options)
        : base(next, options)
    {
        this.logger = app.CreateLogger<AuthenticationHandler>();
    }

    protected override AuthenticationHandler<ShibbolethAuthenticationOptions> CreateHandler()
    {
        return new ShibbolethAuthenticationHandler(logger);
    }
}

public static class ShibbolethAuthenticationExtensions
{
    public static IAppBuilder UseShibbolethAuthentication(this IAppBuilder app, ShibbolethAuthenticationOptions options = null)
    {
        if (app == null)
        {
            throw new ArgumentNullException("app");
        }

        app.Use(typeof(ShibbolethAuthenticationMiddleware), app, options != null ? options : new ShibbolethAuthenticationOptions());
        app.UseStageMarker(PipelineStage.Authenticate);
        return app;
    }
}

Please refer this SO post where I created the pseudo code.

Rohith
  • 5,527
  • 3
  • 27
  • 31