1

I have a Razor Pages app developed using .NET Core 6. The app works as a client and connects to an API. The API has JWT Access Token/Refresh Token authentication. The login endpoint of the API returns access token and refresh token.Using cookie authentication I store the tokens as claim in authentication cookie.

var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, Login.Email),
            new Claim("Token", loginResponse.Token),
            new Claim("RefreshToken", loginResponse.RefreshToken)
        };

I then get the tokens using extension methods

public static class CommonExtensions
{
    public static string? GetToken(this HttpContext context)
    {
        return context.User.Claims.Single(x => x.Type == "Token").Value.ToString();
    }

    public static string? GetRefreshToken(this HttpContext context)
    {
        return context.User.Claims.Single(x => x.Type == "RefreshToken").Value.ToString();
    }
}

When my access token expires I refresh it, remove existing claims and add new ones with the updated token.

var identity = User.Identity as ClaimsIdentity;
identity.RemoveClaim(identity.FindFirst("Token"));
identity.AddClaim(new Claim("Token", response.Token));

identity.RemoveClaim(identity.FindFirst("RefreshToken"));
identity.AddClaim(new Claim("RefreshToken", response.RefreshToken));

However the subsequent requests keep using the expired token. What is the way to update the claims correctly?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Divyang Vyas
  • 65
  • 1
  • 8
  • When you update Claims in ClaimsIdentity, You need to save change and update the token in cookie. Actually , I didn't find any effective method except to SignIn again. – Xinran Shen Aug 10 '22 at 06:07

2 Answers2

1

In order to save your changes you would need to call SignInAsync according to Microsoft.

await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, User);

If it does not work, maybe you need to call SignOutAsync first.

Mihail
  • 730
  • 4
  • 17
  • 1
    Signing in again works but it invalids the remaining requests for the same page and I have to refresh the page manually. Is there a way to reload the same page after signing in again, Return Page(); doesn't seem to be working. – Divyang Vyas Aug 11 '22 at 02:48
0

Implement the CookieAuthenticationEvents, and you can update the Principal when you validate it.

using Microsoft.AspNetCore.Authentication.Cookies;

public class CustomCookieAuthenticationEvents
    : CookieAuthenticationEvents
{
    ...

    public override Task ValidatePrincipal(CookieValidatePrincipalContext context)
    {
        ...

        if (needToUpdateCookie)
        {
            var identity = User.Identity as ClaimsIdentity;
            identity.RemoveClaim(identity.FindFirst("Token"));
            identity.AddClaim(new Claim("Token", response.Token));

            identity.RemoveClaim(identity.FindFirst("RefreshToken"));
            identity.AddClaim(new Claim("RefreshToken", response.RefreshToken));

            context.ShouldRenew = true;
        }

        ...
    }

    ...
}

In your bootstrap...


// Off course you can inject the dependencies to CostomCookieAuthenticationEvents...
builder.Services.AddScope<CustomCookieAuthenticationEvents>();

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        ...

        options.EventsType = typeof(CustomCookieAuthenticationEvents);

        ...
    });

MASHER
  • 1