I intend to mostly rely on the users and roles portion of the Management API. I don’t intend to make calls against it all the time, but whenever a new user arrives in the system, I need to assign them a basic role, because my entire .NET API is on lockdown by default. My strategy is to encapsulate only the Management API functionality that I need into a service in my .NET API layer.
As I understand it, I need to fetch production machine-to-machine tokens in order to make calls against the Management API.
I have a private method in my service that looks like this:
async Task<JwtModel> FetchProductionAccessTokenForManagementAPI()
{
var grantType = _Configuration["Auth0Management:GrantType"];
var clientId = _Configuration["Auth0Management:ClientId"];
var clientSecret = _Configuration["Auth0Management:ClientSecret"];
var data = new Dictionary<string, object> {
{"grant_type", $"{grantType}"},
{"client_id", $"%24%7B{clientId}%7D"}, // Ignore this ugly bit. Haven't dealt with encoding yet.
{"client_secret", $"{clientSecret}"},
{"audience", $"{_AuthBaseAddress}/api/v2"},
};
var tokenService = RestService.For<IAuthManagementTokenService>(_AuthBaseAddress);
var token = await tokenService.GetToken(data);
return JsonConvert.DeserializeObject<JwtModel>(token);
}
This is called inside an Initialize()
method:
async Task Initialize()
{
var token = await FetchProductionAccessTokenForManagementAPI();
_ManagementApiClient = new ManagementApiClient(token.AccessToken, new Uri($"{_AuthBaseAddress}/api/v2"));
}
Before any call to the Manage API, I call Initialize()
like this:
public async Task<User> GetUserById(string userId)
{
await Intitialize();
var user = await _ManagementApiClient.Users.GetAsync(userId);
return user;
}
Is calling the Initialize()
method before each API call too verbose? Is it inappropriate to request a new token for each call? I don’t really want to deal with storing the tokens anywhere in my API layer, and my services are transient, so I don’t want to store it as a local property.
I suppose I could make my service a singleton, store the token in memory, re-use it when needed, and then get a new one if a Management API call returns a 401.
Thoughts on my strategy?
(None of that code above is tested yet. Just looking for concept feedback.)