Search code examples
identityserver4bearer-token

IdentityServer4 - Calling API from IProfileService implementation


I'm working on an MVC web project which is using IdentityServer4 to authenticate users, the web app then uses an access token provided to a user by IdentityServer (authorization code flow) to call an API. The IdentityServer has been configured to use Azure AD as an external identity provider, which is the primary mechanism for users to login. That's all working great.

Once authenticated, I need to query the web app's database to determine:

  • If the user account is authorised to login
  • Retrieve claims about the user specific to the application

The IdentityServer docs (http://docs.identityserver.io/en/latest/reference/profileservice.html) suggest implementing the IProfileService interface for this, which I've done. I want the ProfileService to call the web app's API to retrieve the information about the user to avoid forcing the IdentityServer to need to know about/directly access the database. My problem however, is that calling the API though needs an access token.

Is it possible to retrieve the token for the current user inside the ProfileService's IsActiveAsync / GetProfileDataAsync methods? I can't find solid documentation that identifies if the token is even generated at that point. I'm also a total noob when it comes to authentication/authorization, it's a massive topic!

I had the idea of using the client credentials flow inside the ProfileService to call the API, just to populate that initial token. However, I don't know whether or not that's an absolutely terrible idea... or if there are any better concepts someone could refer me to that I could investigate.

Can anyone point me in the right direction?


Solution

  • Have a look at ITokenCreationService that is part of identityserver4. You can inject that service into your IProfileService implementation and then create a new bearer token with any claims you like.

    For example:

    protected readonly ITokenCreationService _tokenCreationService;
    
    ...
    
    var token = new Token
    {
        AccessTokenType = AccessTokenType.Jwt,
        Issuer = "https://my.identityserver.com",
        Lifetime = (int)TimeSpan.FromMinutes(5).TotalSeconds,
        Claims = GetClaimsNeededForApiCall()
    };
    
    string myToken = await _tokenCreationService.CreateTokenAsync(token);
    
    ...