angularasp.net-corehttpasp.net-core-webapiasp.net-core-identity

After Get succeeds, why does first Angular 9 Put request succeed on MVC Core 2.2 API Controller, but fails on next PUT with http err 302 and/or 503?


I'm fairly new to ASP.NET Core, Angular HttpClient and Observables, so this question was legitimate a year ago, but no longer necessary.

I was not using the [Authorize] attribute properly - it should come before the [Http] verb attributes on all Action methods in the controller - where Authorization is needed for data access.

I was also not properly formatting my logic to perform the JWT token evaluation and Model State verification - so that my action methods would return Status Code 400 (BadRequest) for invalid model state and Status Code 401 (Not Authorized) for invalid JWT or for a session timeout based on the JWT generated at login.

Learning how to use the dbo.Session database was crucial. I had to include the JWT header in its http requests and to perform the JWT token validation and Authorization in the Session controller, too. Here is how I setup the client and server code for the dbo.Session table:

 // Angular 9 Client-side model, repository and datasource combination

 import { Injectable } from "@angular/core";
 import { HttpClient, HttpHeaders } from "@angular/common/http";
 import { Member } from "./member.model";
 import { DatasourcesService } from "./datasources.service";

 const sessionUrl = "/api/session";
 // Note:  this code is based on a "Cart" model
 export class ContactInfo {
    selections: MembersInfoSelection[] = [];
    itemCount: number = 0;

    constructor(private http: HttpClient, private authBearer: DatasourcesService) {
    this.selections = []; 
}

storeSessionData<T>(dataType: string, data: T) {
  let myHeaders = new HttpHeaders();
  if (this.authBearer.JWTauthcookie == null) {
      myHeaders = myHeaders.set("Access-Key", "<secret>");
  } else {
      myHeaders = myHeaders.set("Authorization", "Bearer<" + this.authBearer.JWTauthcookie + ">");
  }
    myHeaders = myHeaders.set("Application-Names", ["ClientApp", "My-App"]);

    return this.http.post(`${sessionUrl}/${dataType}`, data, {
      headers: myHeaders
    }).subscribe(response => {  }); 
}

addMemberInfo(member: Member) {  
  let selection = this.selections
  .find(mis => mis.memberid == member.memberID);
  if (selection) {
    selection.quantity++;
  } else {
    this.selections.push(new MembersInfoSelection(this, member.memberID,
    member.last_Name, member.first_Name, member.midInit,
    member.cell_Phone, member.email_Address));
  }
  this.update(); 
}

update(storeData: boolean = true) {  
  if (storeData) {
    this.storeSessionData("contactinfo", this.selections.map(s => {
      return {
        memberid: s.memberid, lastname: s.lastname, firstname: s.firstname, midinit: s.midinit,
        cellphone: s.cellphone, emailaddress: s.emailaddress, quantity: s.quantity
      }
    }));
   }
  }
} 

 // a separate class for data model
 export class MembersInfoSelection {
   constructor(public contactinfo: ContactInfo,
  public memberid?: number,
  public lastname?: string,
  public firstname?: string,
  public midinit?: string,
  public cellphone?: string,
  public emailaddress?: string,
  public quantityValue?: number) { }
 }


 // Server-Side: AspNetCore 2.2 MVC Controller (C#)

 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Newtonsoft.Json;
 using ServerApp.Models;
 using ServerApp.Infrastructure;
 using Microsoft.AspNetCore.Authorization;

 namespace ServerApp.Controllers
 {
     [Route("/api/session")]
     [AllowAnonymous]
     [ApiController]
     public class SessionValuesController : Controller
     {

         private string bearerToken;
         private readonly Jwt_GenerateToken valToken = new Jwt_GenerateToken();

         [HttpGet("contactinfo")]
         public IActionResult GetContactInfo()
         {
             return Ok(HttpContext.Session.GetString("contactinfo"));
         }

         [Authorize(Roles = "Admin,Super,User")]
         [HttpPost("contactinfo")]
         public object StoreContactInfo([FromBody] SessionInfo[] contacts) 
         {
             object returnObject = new object();
             // get the content/value of the Authorization header in the Http Request
             bearerToken = Request.Headers["Authorization"];
             var bearer = bearerToken.Substring(7, bearerToken.Length - 8);
             if (valToken.ValidateCurrentToken(bearer) == true)
             {
                 if (ModelState.IsValid)
                 {
                     var jsonData = JsonConvert.SerializeObject(contacts); 
                     HttpContext.Session.SetString("contactinfo", jsonData);
                     return true;
                 }
                  return BadRequest();
              }
              return StatusCode(401);
         }
     }
 }

 

Solution

  • Change your services.AddAuthentication(); to services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme);