C# – ASP.NET Identity is null even the token is sent

asp.netasp.net-identityauthenticationc

For my thesis Project i have to implement a token-based (Bearer) Authentication in my ASP.NET solution. I implemented it like Taiseer Jouseh (http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity).

The basic part is working correctly. I have a Mobile Client on which i can register a new User. Then i can Login and receive the token. When i then make a request, the token is sent in the Request Header. It all works fine.
My problem is, that I get an 401 Unauthorized error if I call a [Authorize] Method, even if i send the token. So i removed the [Authorize] Annotation to test some things:

var z = User.Identity;
var t = Thread.CurrentPrincipal.Identity;
var y = HttpContext.Current.User.Identity;
var x = Request.GetOwinContext().Authentication.User.Identity;

Here i got alwas the same Identity: AuthenticationType=null; IsAuthenticated=false; Name=null; Claims:empty

var token = Request.Headers.Authorization;

Here i get the right token. So the token is sent by the request.

I hope you can help me. I have the token but no identity.

Here are parts of my code:
OAuthServiceProvider:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{

    public async override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    // POST /token
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        var userManager = DependencyResolver.Current.GetService<UserManager<IdentityUser, int>>();

        IdentityUser user = await userManager.FindAsync(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }

        var identity = await userManager.CreateIdentityAsync(user, context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));
        context.Validated(identity);
    }
}

The Controller Method:

#region GET /user/:id
[HttpGet]
[Route("{id:int:min(1)}")]
[ResponseType(typeof(UserEditDto))]
public async Task<IHttpActionResult> GetUser(int id)
{
    try
    {
        // tests
        var z = User.Identity;
        var t = Thread.CurrentPrincipal.Identity;
        var y = HttpContext.Current.User.Identity;
        var x = Request.GetOwinContext().Authentication.User.Identity;
        var token = Request.Headers.Authorization;

        User user = await _userManager.FindByIdAsync(id);
        if (user == null)
        {
            return NotFound();
        }

        Mapper.CreateMap<User, UserEditDto>();
        return Ok(Mapper.Map<UserEditDto>(user));
    }
    catch (Exception exception)
    {
        throw;
    }

}
#endregion

The WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter("Bearer"));

        config.MapHttpAttributeRoutes();

        var corsAttr = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(corsAttr);

        config.Routes.MapHttpRoute(
             name: "DefaultApi",
             routeTemplate: "api/{controller}/{id}",
             defaults: new { id = RouteParameter.Optional }
        );
    }
}

Startup:

[assembly: OwinStartup(typeof(Startup))]
public class Startup
{

    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        var container = new UnityContainer();
        UnityConfig.RegisterComponents(container);
        config.DependencyResolver = new UnityDependencyResolver(container);
        //config.DependencyResolver = new UnityHierarchicalDependencyResolver(container);
        WebApiConfig.Register(config);
        app.UseWebApi(config);
        ConfigureOAuth(app);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider()
        };

        // Token Generation
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
        app.UseOAuthAuthorizationServer(OAuthServerOptions);

    }

}

Best Answer

Finally I found the problem. It is so simple, that I can't believe I spent more than a week to solve this problem.

The problem was in the startup. I simply had to call ConfigureOAuth(app); before app.UseWebApi(config);

So the correct Startup looks like

[assembly: OwinStartup(typeof(Startup))]
public class Startup
{

    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();
        var container = new UnityContainer();
        UnityConfig.RegisterComponents(container);
        config.DependencyResolver = new UnityDependencyResolver(container);
        //config.DependencyResolver = new UnityHierarchicalDependencyResolver(container);
        WebApiConfig.Register(config);
        ConfigureOAuth(app);
        app.UseWebApi(config);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider()
        };

        // Token Generation
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
        app.UseOAuthAuthorizationServer(OAuthServerOptions);

    }

}
Related Topic