admin管理员组

文章数量:1397125

I am trying to return an altered header if the token a user sends up is expired so that I can resend up my refresh token if it is expired.

I am using .NET Core 2.2 with "In-Process" hosting incase that matters.

Here is my ConfigureServices method from my Startup.cs.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "bearer";
    options.DefaultChallengeScheme = "bearer";
}).AddJwtBearer("bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["serverSigningPassword"])),
        ValidateLifetime = true,
        ClockSkew = System.TimeSpan.Zero //the default for this setting is 5 minutes
    };
    options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return System.Threading.Tasks.Task.CompletedTask;
        }
    };
});

And then when I try to fetch on an "authorize" endpoint from javascript with the following.

async function fetchWithCredentials(url, options) {    
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);
    if (response.ok) { //all is good, return the response
        return response;
    }

    console.log(response.headers) //nothing in this array

    // it will never do this "if" statement because there are no headers
    if (response.status === 401 && response.headers.has('Token-Expired')) {
        // refresh the token
        return await fetchWithCredentials(url, options); //repeat the original request
    } else { //status is not 401 and/or there's no Token-Expired header
        return response; 
    }
}

This image is from hovering over the header. It certainly hits my breakpoint (for the context.Response.Headers.Add() and I can see the count = 1 (which is the "Token-Expired" when I examine it).

Finally, here is a screenshot from Postman after a failed request so the response is sending, but not being received in my JS.

Any ideas as to why my header is not sticking to my response in the javascript?

I am trying to return an altered header if the token a user sends up is expired so that I can resend up my refresh token if it is expired.

I am using .NET Core 2.2 with "In-Process" hosting incase that matters.

Here is my ConfigureServices method from my Startup.cs.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "bearer";
    options.DefaultChallengeScheme = "bearer";
}).AddJwtBearer("bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["serverSigningPassword"])),
        ValidateLifetime = true,
        ClockSkew = System.TimeSpan.Zero //the default for this setting is 5 minutes
    };
    options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return System.Threading.Tasks.Task.CompletedTask;
        }
    };
});

And then when I try to fetch on an "authorize" endpoint from javascript with the following.

async function fetchWithCredentials(url, options) {    
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);
    if (response.ok) { //all is good, return the response
        return response;
    }

    console.log(response.headers) //nothing in this array

    // it will never do this "if" statement because there are no headers
    if (response.status === 401 && response.headers.has('Token-Expired')) {
        // refresh the token
        return await fetchWithCredentials(url, options); //repeat the original request
    } else { //status is not 401 and/or there's no Token-Expired header
        return response; 
    }
}

This image is from hovering over the header. It certainly hits my breakpoint (for the context.Response.Headers.Add() and I can see the count = 1 (which is the "Token-Expired" when I examine it).

Finally, here is a screenshot from Postman after a failed request so the response is sending, but not being received in my JS.

Any ideas as to why my header is not sticking to my response in the javascript?

Share Improve this question edited May 29, 2019 at 14:18 thalacker asked Apr 29, 2019 at 18:34 thalackerthalacker 2,8474 gold badges25 silver badges45 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 6

There is a restriction to access response headers when you are using Fetch API over CORS. Due to this restriction, you can access only following standard headers:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

Reference : https://stackoverflow./a/44816592/5751404

So one way to access your custom header in client is to add the header access-control-expose-headers to response, with the ma-separated headers:

services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{
    builder.AllowAnyOrigin()
          .AllowAnyMethod()
          .AllowAnyHeader()
          .WithExposedHeaders("Token-Expired"); ;
}));

In Configure:

app.UseCors("MyPolicy");

So that you can access the custom header from client using Fetch API over CORS .

Here I describe for both - 1. Token expire and get refresh token 2. Only for unauthorized request.

async function fetchWithCredentials(url, options) {    
    options.headers['Authorization'] = 'Bearer ' + jwtToken;
    var response = await fetch(url, options);//this is a function for get a response. I didn't explain it here. Hope you understand. 
    if (response.ok) {
        return response;
    }

    let flag:boolean=false; //set flag for executing one if statement at a time.

if (response.status == 401 && response.headers.has('Token-Expired')) {
        // refresh the token
        flag=true;  //set flag true.
        //write something as per your requirement.
    } 

if (response.status == 401 && flag==false) {
        **// Only for unauthorized request. You can use this for your problem.**
        //write something as per your requirement.
    } 
}

And most important thing is, You have to use below code in startup.cs.

services.AddCors(context => context.AddPolicy("CustomPolicy", builder =>
{
    builder.AllowAnyOrigin()
          .AllowAnyMethod()
          .AllowAnyHeader()
          .WithExposedHeaders("Token-Expired"); ;
}));

In Configure:

app.UseCors("CustomPolicy");

and use below code as it is.

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = "bearer";
    options.DefaultChallengeScheme = "bearer";
}).AddJwtBearer("bearer", options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(Configuration["serverSigningPassword"])),
        ValidateLifetime = true,
        ClockSkew = System.TimeSpan.Zero //the default for this setting is 5 minutes
    };
    options.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return System.Threading.Tasks.Task.CompletedTask;
        }
    };
});

Now, you'll get response on client side. Hope you'll find your solution. Please let me know for any doubt.

本文标签: javascriptReturning response header OnAuthenticationFailedStack Overflow