[SOLVED] Unable to cast HttpContext to User

Issue

I’m using Web API. I have followed a tutorial on implementing JWT Auth. When I use Postman and when I get the token and try to do authentication it works but I’m unable to cast the HttpContext to User class.

Error:

"Unable to cast object of type
‘AsyncStateMachineBox1[TechStore.Api.Data.Enteties.User,TechStore.Api.Data.Repositories.GenericRepository1+d__5[TechStore.Api.Data.Enteties.User]]’
to type ‘TechStore.Api.Data.Enteties.User’."

On authorise method:

public void OnAuthorization(AuthorizationFilterContext context)
        {
            var user = (User)context.HttpContext.Items["User"]; //Here it throws error
 
            if (user == null)
            {
                context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
            }
        }

The data is correct in the httpcontext but I can’t cast it to user object.

User Class:

public class User
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string Username { get; set; }

        public string Email { get; set; }

        public string Password { get; set; }

        public string LastName { get; set; }

        public string Adress { get; set; }

        public string PhoneNumber { get; set; }

        public int Age { get; set; }

        public Cart Cart { get; set; }

        public int CartId { get; set; }
    }

JWTAuthntictor class:

namespace TechStore.Api.Helpers
{
    public class JWTAuthenticator
    {
        private readonly RequestDelegate _next;

        public JWTAuthenticator
            (
                RequestDelegate next
            )
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context, IRepository<User> userService)
        {
            var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

            if (token != null)
                attachUserToContext(context, userService, token);

            await _next(context);
        }

        private void attachUserToContext(HttpContext context, IRepository<User> userService, string token)
        {
            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.ASCII.GetBytes("acdc11434jjkk34311acdasdwjkdnovjfnbcacacasdadc11434jjkk314311acdc");
                tokenHandler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    // set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
                    ClockSkew = TimeSpan.Zero
                }, out SecurityToken validatedToken);

                var jwtToken = (JwtSecurityToken)validatedToken;
                var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "id").Value);

                // attach user to context on successful jwt validation
                context.Items["User"] = userService.GetByProperty(u => u.Id == userId);
            }
            catch
            {
                // do nothing if jwt validation fails
                // user is not attached to context so request won't have access to secure routes
            }
        }

    }
}

Athorize attribute:

public class AuthorizeAttribute : Attribute, IAuthorizationFilter
    {
        public AuthorizeAttribute()
        {
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var user = (User)context.HttpContext.Items["User"];
 
            if (user == null)
            {
                context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
            }
        }
    }

Solution

I had the exact same situation.
for me this line:

var user = (User)context.HttpContext.Items["User"];

did work on a NET Core 3.1 project,
but in a different project with NET Core 5 I got this exact exception.

if you just need to check that the user is not null, than you do not need to cast the
context items to a User object.

instead you could do this and your if check will work:

        //var user = (User)context.HttpContext.Items["User"];
        var user = context.HttpContext.Items["User"];//remove casting
        if (user == null)
        {
            context.Result = new JsonResult(new { message = "Unauthorized" }) { StatusCode = StatusCodes.Status401Unauthorized };
        }

what i could not figure out is how to access the result (which is the actual object you might want) in the attached image.
enter image description here

maybe some one else could clarify that.

Answered By – kifka

Answer Checked By – Timothy Miller (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *