I am attempting to setup access token validation for AWS Cognito within my .NET 7 WebApi project. The problem is that AWS rotates it's keys so you need to grab the new ones frequently. Most solutions I've found call out to the endpoint everytime the validator is called using code like the following:
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
// get JsonWebKeySet from AWS
var json = new WebClient().DownloadString(jwtKeySetUrl);
// serialize the result
var keys = JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
// cast the result to be the type expected by IssuerSigningKeyResolver
return (IEnumerable<SecurityKey>)keys;
},
The issue is that in .NET 7 at least, WebClient is deprecated and you're supposed to use HttpClient instead. So this is what I've come up with:
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
// get JsonWebKeySet from AWS
var json = new HttpClient()
.GetStringAsync($"{builder.Configuration["AWS:Issuer"]}/.well-known/jwks.json")
.ConfigureAwait(false).GetAwaiter().GetResult();
// serialize the result
var keySet = JsonWebKeySet.Create(json); // Ignore this, just cleaned up the Json deserialization code from the above example since JsonWebKeySet can do it directly.
var keys = keySet.Keys;
// cast the result to be the type expected by IssuerSigningKeyResolver
return keys;
},
My concern is in creating HttpClient for each call as I know that can be inefficient and I want to make sure this code is scalable. Would it be better to wrap the code in a "using HttpClient" or is the above okay? I'm sure calling a third-party endpoint everytime isn't great but I don't think there's much I can do about that.
By default, JwtBearer will refresh the configuration and keys every 24h.
You can control this using
.AddJwtBearer(opt =>
{
opt.AutomaticRefreshInterval = new TimeSpan(1, 0, 0, 0);
opt.BackchannelTimeout = new TimeSpan(0, 0, 10); //10 seconds
}