Using JWT Token in Client API

Viewed 398

I have an API in .NET5 uses JWTBearer to secure the API. Now I wanted to configure my client app to use the token generated from the api/gettoken. It works fine in swagger, but I don't know how to configure my MVC and API(consuming API) to use this token. Can somebody help by providing the configureservices and configure methods in the startup

To Glenn,

I have 3 projects JWT.IDP, JWT.API, JWT.MVC. JWT.IDP issues the token, my intention is to use that token in JWT.API and call the JWT.API function from JWT.MVC. The IDP is working perfectly, I can generate the token and my JWT.MVC Login controller is able to receive it. The last function in the below code (GetWeatherData) is coded according to the idea you have given. If I don't pass the token, I used to get 401 error, now I get 500 Internal Server Error

namespace JWT.MVC.Controllers
{
    public class LoginController : Controller
    {

        public IActionResult DoLogin()
        {

            return View();
        }


        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DoLogin([Bind("EmailOrName,Password")] LoginRequestModel loginRequestModel)
        {
            var apiName = $"https://localhost:44318/api/User/login";

            HttpClient httpClient = new HttpClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, loginRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();

            var data = await JsonSerializer.DeserializeAsync<IEnumerable<AccessibleDb>>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

            foreach (var item in data)
            {
                item.UserName = loginRequestModel.EmailOrName;
            }

            return View("SelectDatabase" , data);
        }

      
        public async Task<IActionResult> PostLogin(string db, string user)
        {
            TokenRequestModel tokenRequestModel = new TokenRequestModel() { Database = db, UserName = user };

            var apiName = $"https://localhost:44318/api/User/tokenonly";

            HttpClient httpClient = new HttpClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, tokenRequestModel);
            var jasonString = await response.Content.ReadAsStreamAsync();

            var data = await JsonSerializer.DeserializeAsync<AuthenticationModel>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

            var stream = data.Token;
            var handler = new JwtSecurityTokenHandler();
            var jsonToken = handler.ReadToken(stream);
            var tokenS = jsonToken as JwtSecurityToken;
            var selectedDb = tokenS.Claims.First(claim => claim.Type == "Database").Value;

            ViewBag.SelectedDb = selectedDb;

            return View(data);
        }

        public async Task<IActionResult> GetWeatherData(string token)
        {

            var apiName = $"https://localhost:44338/weatherforecast";

            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            HttpResponseMessage response = await httpClient.GetAsync(apiName);
            if (!response.IsSuccessStatusCode)
            {
                ViewBag.Error = response.StatusCode;
                return View("Weatherdata");
            }
            var jasonString = await response.Content.ReadAsStreamAsync();
            var data = await JsonSerializer.DeserializeAsync<WeatherForecast>
                    (jasonString, new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });

        
            return View("Weatherdata" , data);
        }
    }
}

Startup class for JWT.MVC is as below


 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            services.AddAuthentication("Bearer")
             .AddJwtBearer("Bearer", options =>
             {

                 options.Audience = "SecureApiUser";
                 options.Authority = "https://localhost:44318";
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ValidateAudience = false
                 };
             });

          
        }


Startup class for JWT.API is as below

  public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            //Copy from IS4
            services.AddAuthentication("Bearer")
              .AddJwtBearer("Bearer", options =>
              {
                  
                  options.Audience = "SecureApiUser";
                  options.Authority = "https://localhost:44318";
                  options.TokenValidationParameters = new TokenValidationParameters
                  {
                      ValidateAudience = false
                  };
              });

          
            //End
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.API", Version = "v1" });
            });
        }

Startup class for JWT.IDP is as below

  public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();

            //Configuration from AppSettings
            services.Configure<JwtSettings>(Configuration.GetSection("JWT"));
            //User Manager Service
            services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>();
            services.AddScoped<IUserService, UserService>();
            //Adding DB Context with MSSQL
            services.AddDbContext<IdentityDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("IdentityDbConnectionString"),
                    b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));

            //Adding Athentication - JWT
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
                .AddJwtBearer(o =>
                {
                    o.RequireHttpsMetadata = false;
                    o.SaveToken = false;
                    o.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuerSigningKey = true,
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.FromMinutes(Convert.ToInt32(Configuration["JWT:DurationInMinutes"])),
                        ValidIssuer = Configuration["JWT:Issuer"],
                        ValidAudience = Configuration["JWT:Audience"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"]))
                    };
                });

           

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "JWT.IDP", Version = "v1" });
            });
        }

And the JWT Setting is as below

 "JWT": {
    "key": "C1CF4B7DC4C4175B6618DE4F55CA4",
    "Issuer": "http://localhost:44318",
    "Audience": "SecureApiUser",
    "DurationInMinutes": 60
  },
1 Answers

The short answer is

httpClient.DefaultRequestHeaders.Authorization =
  new AuthenticationHeaderValue("Bearer", [token])

Keep "Bearer" as it is, it's just a constant. Replace [token], with the base 64 encoded token value returned to us from the OAuth protocol you are using.

Related