Search code examples
authenticationpostmanidentityserver4abp-framework

Authentication always using an old token value


I have a problem that I don't know how to resolve. I have a microservice model (based on the Volo ABP Microservice Demo) for my project, I have an API with all the methods to retrieve data, an AuthServer that acts as the authority for all my projects, and a gateway that translates the requests.

This is how I have configured my authentication in my Gateway project:

public override void ConfigureServices(ServiceConfigurationContext context)
{
    IdentityModelEventSource.ShowPII = true;
    var configuration = context.Services.GetConfiguration();

    Configure<AbpMultiTenancyOptions>(options =>
    {
        options.IsEnabled = SidesysMicroservicesConsts.IsMultiTenancyEnabled;
    });

    context.Services.AddAuthentication("Bearer")
        .AddIdentityServerAuthentication(options =>
        {
            options.Authority = configuration["AuthServer:Authority"];
            options.ApiName = configuration["AuthServer:ApiName"];
            options.RequireHttpsMetadata = false;
        });

    context.Services.AddSwaggerGen(options =>
    {
        options.SwaggerDoc("v1", new OpenApiInfo { Title = "VirtualSpace Gateway API", Version = "v1" });
        options.DocInclusionPredicate((docName, description) => true);
        options.CustomSchemaIds(type => type.FullName);
    });

    context.Services.AddOcelot(context.Services.GetConfiguration());

    Configure<AbpDbContextOptions>(options =>
    {
        options.UseSqlServer();
    });

    context.Services.AddCors(options =>
    {
        options.AddPolicy(DefaultCorsPolicyName, builder =>
        {
            builder
                .WithOrigins(
                    configuration["App:CorsOrigins"]
                        .Split(",", StringSplitOptions.RemoveEmptyEntries)
                        .Select(o => o.RemovePostFix("/"))
                        .ToArray()
                )
                .WithAbpExposedHeaders()
                .SetIsOriginAllowedToAllowWildcardSubdomains()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials();
        });
    });

    //context.Services.AddStackExchangeRedisCache(options =>
    //{
    //    options.Configuration = configuration["Redis:Configuration"];
    //});

    //var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
    //context.Services.AddDataProtection()
    //    .PersistKeysToStackExchangeRedis(redis, "MsDemo-DataProtection-Keys");
}

I have roles and different users in my Database so to retrieve a token I use the /connect/token URL from the AuthServer with the respective role, for this, I use Postman with the corresponding headers. Once I retrieved the token I need, I would use Postman with the corresponding URL from the Gateway (my gateway runs on port 44377) with the respective "Authorization" header and its token value with a "Bearer" authentication scheme, this request will translate to the URL to their corresponding API (it runs on port 44320) URL request that I need to do, for example, http://localhost:44377/api/virtualspaceattention/GetSourceUsers, it would be translated to http://localhost:44320//api/virtualspaceattention/VirtualSpaceAttention/GetSourceUsers.

Problem here is that no matter what token I use, every time I get the same log error:

Request starting HTTP/1.1 GET http://localhost:44377/api/virtualspaceattention/GetSoruceUsers - -
2022-01-07 17:00:47.928 -03:00 [INF] Failed to validate the token.
Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match key: 
kid: 'C99C917C5E43906FE6A88DDF28E73628'.
Exceptions caught:
 ''. 
token: '{"alg":"RS256","kid":"C99C917C5E43906FE6A88DDF28E73628","typ":"at+jwt"}.{"nbf":1640913147,"exp":1672449147,"iss":"http://localhost/authserver","aud":["VirtualSpace","VirtualSpaceGateway"],"client_id":"virtualSpace","iat":1640913147,"scope":["VirtualSpace","VirtualSpaceGateway"]}'.
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters)
   at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
   at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
2022-01-07 17:00:48.025 -03:00 [INF] Bearer was not authenticated. Failure message: IDX10501: Signature validation failed. Unable to match key: 
kid: 'C99C917C5E43906FE6A88DDF28E73628'.
Exceptions caught:
 ''. 
token: '{"alg":"RS256","kid":"C99C917C5E43906FE6A88DDF28E73628","typ":"at+jwt"}.{"nbf":1640913147,"exp":1672449147,"iss":"http://localhost/authserver","aud":["VirtualSpace","VirtualSpaceGateway"],"client_id":"virtualSpace","iat":1640913147,"scope":["VirtualSpace","VirtualSpaceGateway"]}'.

I've compared the token I retrieved through the /connect/token URL and is not the same as the one that the request is currently using. I've checked its properties using the JWT website and It seems it is using a token that is somewhere cached but I don't know where it is to deal with it.

I will paste here the values from the JWT website for comparison:

{
  "alg": "RS256",
  "kid": "1C700F5BA873DCA75C9CEC6B36118026",
  "typ": "at+jwt"
}
{
  "nbf": 1641586212,
  "exp": 1673122212,
  "iss": "http://localhost:44399",
  "aud": [
    "VirtualSpace",
    "VirtualSpaceGateway"
  ],
  "client_id": "virtualSpace",
  "sub": "87861a01-4486-17b8-c6d6-3a01476f3851",
  "auth_time": 1641586212,
  "idp": "local",
  "tenantid": "0a1ea190-866c-3522-010e-3a014784d83d",
  "operator_description": "Operador 1",
  "role": "operator",
  "email": "[email protected]",
  "email_verified": "False",
  "name": "operatorOne",
  "iat": 1641586212,
  "scope": [
    "VirtualSpace",
    "VirtualSpaceGateway"
  ],
  "amr": [
    "pwd"
  ]
}

Two things I've found comparing the token:

  • The "iss": "http://localhost:44399", and "iss": "http://localhost/authserver", these values are different. I used to run my AuthServer through IIS but I'm not anymore.
  • "kid": "1C700F5BA873DCA75C9CEC6B36118026" and "kid": "C99C917C5E43906FE6A88DDF28E73628". These are definitely not the same. Again, it seems that this old token is stored somewhere.

Any suggestion will be appreciated. TIA.


Solution

  • The problem was in the browser. It seems that Google Chrome stores the token in the Application tab even if you have the Disable cache option selected. And even if you force the page to empty the cache and force the reload, the token will remain there.

    In the Application tab, you need to clean everything under the Storage section in order to fix this issue. Honestly a nightmare, I lost practically the entire day trying to come up with a solution until I realized this.