IdentityServer4 too many calls cause performance i

2019-01-29 00:12发布

I am implementing a custom user store where my users provider lives in a separate service which I am reaching out using messaging.

The thing is GetProfileDataAsync and IsActiveAsync are getting called too many times (about 3 times each) causing messaging process to be launched each time.

Here is a simple implementation of IProfileService.

public class IdentityProfileService : IProfileService
{
    private readonly UserManager<ApplicationUser> _userManager;

    public IdentityProfileService (UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {

        var user = await _userManager.FindBySubjectIdAsync(context.Subject.GetSubjectId());
        if (user != null)
        {
            context.IssuedClaims = user.Claims;
        }
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var sub = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(sub);
        context.IsActive = user != null;
    }
}

My question is:

Is there a way to minimize the number of these calls? or can I check for some info that's existence means that there is no need to call _userManager.FindBySubjectIdAsync again?

1条回答
啃猪蹄的小仙女
2楼-- · 2019-01-29 01:09

The Profile Service is not called too many times, but it is called multiple times with a different context:

  • For the access token Context.Caller = ClaimsProviderAccessToken.
  • For the identity token Context.Caller = UserInfoEndpoint.

Each caller expects a different result. That is why you should filter the claims by the requested claim types:

public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
    var sub = context.Subject.GetSubjectId();
    var user = await _userManager.FindByIdAsync(sub);
    var principal = await _claimsFactory.CreateAsync(user);

    var claims = principal.Claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();

    context.IssuedClaims = claims;
}

That is why the access_token contains different claims than the identity_token.

You could minimize the calls by not requesting info from other endpoints than the access endpoint. But you can also check the caller and act differently for each caller. You can also give the token a longer lifetime so you won't need to refresh the token that ofter.

查看更多
登录 后发表回答