Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get claims included in my AuthTicket in a Web API Auth Service?

I have a Web API with an auth service, for a WPF client, set up like this:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        ...
    }
}

and

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        ...
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            ApplicationCanDisplayErrors = true,
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true, // TODO Make false to deploy
        };
        app.UseOAuthAuthorizationServer(OAuthOptions);
    }
}

I only ever use the /Token endpoint so far, because it at least grants me the bearer token. The ticket I receive on a successful authentication has issue and expiry dates, a bearer token, and my username.

How do I get the user's claims (and maybe roles)? Is there something I can do here, or I do I plod along and request them via the API, after auth, and aggregate them and the Auth Ticket in something like a Principal object for the WPF client?

Could I perhaps include some Identity components in the WPF app to help with extracting the claims from the token, and any suggestions on how I should do this?

like image 879
ProfK Avatar asked Nov 15 '16 15:11

ProfK


People also ask

What is claim in HTTP request?

The claims element contains all the HTTP request information received at the SPS that causes the call to the Security Token Service. To avoid XML parsing problems, the values from the request are XML encoded before they are included as values to the claims element structure.

How to handle authentication in Web API?

Web API assumes that authentication happens in the host. For web-hosting, the host is IIS, which uses HTTP modules for authentication. You can configure your project to use any of the authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform custom authentication.

How to add authentication in Web API?

In IIS Manager, go to Features View, select Authentication, and enable Basic authentication. In your Web API project, add the [Authorize] attribute for any controller actions that need authentication. A client authenticates itself by setting the Authorization header in the request.

How does Authorize Attribute work in Web API?

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking the action. We can apply the filter globally, at the controller level, or at the level of individual actions.


Video Answer


1 Answers

I think it is quite dangerous to allow the client to decrypt the token. If they can do that, a malicious actor can modify the token and the claims inside. If you don't check the validity of the claims (perhaps because they are provided by a third party) then that could lead to privilege escalation and compromise of your application.

If the client application requires the claims - perhaps for UI layout, then you can supply them separately to the token. One way to do this would be via an ActionFilterAttribute to write the claims to a custom http header. If the claims are tampered with here, it only affects the client, as you will check the secure claims inside the token before processing any request.

public AddClaimsAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
     var principal = actionExecutedContext.ActionContext.RequestContext.Principal as ClaimsPrincipal;

    if (principal != null)
    {
        var claims = principal.Claims.Select(x => x.Type + ":" + x.Value).ToList();

        actionExecutedContext.Response.Content.Headers.Add("Claims",
           String.Join(",", claims));
    }

}

Your client then just needs to check for this header and parse it.

This is a basic example, you could format it as JSON or add a series of custom headers "IsAdmin", "IsEditingUser" etc.

Because it is a filter, you could apply this globally to every request, to every action on a controller or to a specific action as you need it.

like image 64
ste-fu Avatar answered Nov 09 '22 23:11

ste-fu