Home > front end >  Authorize using JWT token still returning unauthorized
Authorize using JWT token still returning unauthorized

Time:04-18

my startup.cs (asp.net core 5.0)

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddAuthentication (options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
        })
            .AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.RequireHttpsMetadata = false;
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidAudience = "https://www.yogihosting.com",
                    ValidIssuer = "https://www.yogihosting.com",
                    ClockSkew = TimeSpan.Zero,// It forces tokens to expire exactly at token expiration time instead of 5 minutes later
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"))
                };
            });
    }

I am trying to invoke http://localhost:31254/Reservation which returns the list of flight reservation lists which I am tring to call from CallAPIController.cs

ReservationController.cs

  [Authorize]
    public IEnumerable<Reservation> Index()
    {
        return CreateDummyReservations();
    }

    [HttpGet]
    public IEnumerable<Reservation> Get() => CreateDummyReservations();

    public List<Reservation> CreateDummyReservations()
    {
        List<Reservation> rList = new List<Reservation> {
        new Reservation { Id=1, Name = "Ankit", StartLocation = "New York", EndLocation="Beijing" },
        new Reservation { Id=2, Name = "Bobby", StartLocation = "New Jersey", EndLocation="Boston" },
        new Reservation { Id=3, Name = "Jacky", StartLocation = "London", EndLocation="Paris" }
        };
        return rList;
    }

CallAPIController.cs

  //entry point of the controller
  public async Task<IActionResult> Index(string message)
    {
        ViewBag.Message = message;
        var accessToken = GenerateJSONWebToken(); //generating the token
        SetJWTCookie(accessToken);  //setting the cookie

        List<Reservation>  list = await FlightReservation();

        return RedirectToAction("Home");
    }

     private string GenerateJSONWebToken()
    {
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: "https://www.yogihosting.com",
            audience: "https://www.yogihosting.com",
            expires: DateTime.Now.AddHours(3),
            signingCredentials: credentials
            );

        return new JwtSecurityTokenHandler().WriteToken(token);
    }

    private void SetJWTCookie(string token)
    {
        var cookieOptions = new CookieOptions
        {
            HttpOnly = true,
            Expires = DateTime.UtcNow.AddHours(3),
        };
        Response.Cookies.Append("jwtCookie", token, cookieOptions);
    }

    public  async Task<List<Reservation>> FlightReservation()
    {
        var jwt = Request.Cookies["jwtCookie"];

        List<Reservation> reservationList = new List<Reservation>();

        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwt);
      //calling the reservation controller asynchronously but returning 
            unauthorised.
            using (var response =  await httpClient.GetAsync("http://localhost:31254/Reservation")) // change API URL to yours 
            {
                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string apiResponse =   await response.Content.ReadAsStringAsync();
                    reservationList = JsonConvert.DeserializeObject<List<Reservation>>(apiResponse);
                }

                if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    //return RedirectToAction("Index", new { message = "Please Login again" });
                }
            }
        }

        return reservationList;
    }

When I call the reservation controller I get 401 unauthorised error, though. If i remove authorize attribute it works. The point is it is not recognising the JWT token or validating it properly. Am I missing anything?

CodePudding user response:

Your problem is in this line :

SetJWTCookie(accessToken); 

List<Reservation>  list = await FlightReservation();

When you set the cookie, the response must be received in the browser to set the cookie in the browser to be sent in subsequent requests, but the response has not been sent to the browser yet and you call this method

await FlightReservation();

This method requests a cookie that has not yet been set in the browser and has not been sent to this request, so the received token is empty here

 var jwt = Request.Cookies["jwtCookie"];   //cookie is null

And the unauthorized error returns, but if this request ends, there will be no problem in subsequent requests because the cookie is set in the browser. So with your code it will always return unauthoruzed in first Request.

But if all requests fail, see if you have set up UseAuthentication Middleware or not

app.UseRouting();

app.UseAuthentication();  //here

app.UseAuthorization();

CodePudding user response:

You set the cookie in your SetJWTCookie(string token) method:

Response.Cookies.Append("jwtCookie", token, cookieOptions)

And you try to get the cookie in the FlightReservation() method:

var jwt = Request.Cookies["jwtCookie"];

your Request dosn't contain jwtCookie. so you can't get the value of your jwt token

Just try as below:

[HttpPost]
        public async Task<IActionResult> Authenticate(UserModel someuser)
        {
            
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("MynameisJamesBond007"));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
             issuer: "https://www.yogihosting.com",
             audience: "https://www.yogihosting.com",
             expires: DateTime.Now.AddHours(3),
             signingCredentials: credentials
             );
            

            string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);


            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);

                var response = await httpClient.GetAsync(url); // change API URL to yours 

            }

            return Content(jwtToken);
        }

Result: enter image description here

  • Related