'Unable to cast HttpContext to User
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 1:[1]
The Items["User"] is a Task<TResult> class with the result property having User object.
That's why, you cannot cast directly to the User model. You need to get the Task result property first, which stores your User object.
What you need to do is to cast context.HttpContext.Items["User"]; to Task<User>
You cannot cast it into Task without a known type, it doesn't have a Result property, meaning casting without TResult, the result property would disappear.
This is the code:
var task = (Task<User>)context.HttpContext.Items["User"];
var user = task.Result;
Looking at Kifka's screenshot, the Result object is already an User object, so no further casting is required. var user will be of User type.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | siuramka |
