Search code examples
c#reactjsasp.net-coreaxiosjwt

reactjs call multiple axios posts in one async function


I have a one reactjs project using axios to post to backend API.

The problem is that I need to wrap 2 axios post in one async function, 1 post is getting bookId and then call another function using the getting bookId to get book details. These 2 functions are in one async function getBookDetails wrapping in useEffect. Both axios Posts will set Authorization token which using Auth0.

After running the project, the first call run successfully, but the 2nd call always get 401 error from backend.

const BookStore = () => {
    useEffect(() => {

     const getBook = async() => {

     const {data: bookId} = await getBookId(name:string)
     const {data: bookDetails} = await getBookDetails(Id:string)
}

getBook()
}
)
}

export function getBookId(name:string) {
return axios.post<string>('url', {name}, {
 headers: {
      "content-type": "application/json",
      Authorization: `Bearer ${token}`
    }
}

export function getBookDetail(id:string) {
return axios.post<string>('url', {id}, {
 headers: {
      "content-type": "application/json",
      Authorization: `Bearer ${token}`
    }
}

There are some problems in the backend JwtMiddleware, backend using .NETCORE.

When I run the code, the second API call will invoke the JwtMiddleware Invoke method, set the HttpContext.User(ClaimPricipal), but it won't go into the controller call, throw internal 500 bad request error.

  1. I added the useMiddleware() after Authorization and before useController()

  2. When I move useMiddleware() before useAuthentication(), the Httpcontext use can't be set when go into controller.

Would anyone help answer what's wrong here? Can we set httpcontext user or we can't do this.

public class JwtMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext context)
    {
        try
        {
            context.Request.Headers.TryGetValue("Authorization", out var headerAuth);
            var jwtToken = headerAuth.First()?.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries)[1];

            // Create JWT handler
            var handler = new JwtSecurityTokenHandler();
            var jwtSecurityToken = handler.ReadJwtToken(jwtToken);
            var userName = jwtSecurityToken.Claims.First(c => c.Type == "userName").Value;
            var userId = sub.Split(new[] {'|'}, StringSplitOptions.RemoveEmptyEntries)[1];

            var claims = new List<Claim>
            {
                new("userName", userName),
                new("userId", userId),
            };

            var userIdentity = new ClaimsIdentity(claims, "AppUser");
            var userPrincipal = new ClaimsPrincipal(userIdentity);
            context.User = userPrincipal;

            await _next(context);
        }
        catch (Exception e)
        {
            Console.WriteLine("JwtMiddleware error: {0}", e);
            throw;
        }
    }
}

Add to Program.cs

app.UseAuthentication();
app.UseAuthorization();

app.UseMiddleware<JwtMiddleware>();
app.MapControllers();

app.Run();

Solution

  •  useEffect(() => {
        const getBook = async () => {
          try {
            const name = "exampleBookName";name
            const token = "token";
    
            const bookIdResponse = await getBookId(name, token);
            const bookId = bookIdResponse.data;
    
            const bookDetailsResponse = await getBookDetails(bookId, token);
            const bookDetails = bookDetailsResponse.data;
    
          } catch (error) {
            console.error('Error fetching book data:', error);
          }
        };
    
        getBook();
      }, []);
    

    And make sure to pass the token to the API functions

    export async function getBookId(name, token) {
      return axios.post('url', { name }, {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`
        }
      });
    }
    
    export async function getBookDetails(id, token) {
      return axios.post('url', { id }, {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`
        }
      });
    }