1
votes

I have an IdentityServer4 that when users have about 10 roles the cookie seems to grow exponentially. Everytime I try to log in now I get greeted with a 400 error request too long due to how large the cookie is.

The cookie I receive is split up to 5 chunks of around 4008 in size:

cookies

these cookies seem to be set on the signin-oidc endpoint of the application.

I am using the default cookie settings in identity server - no changes there.

Any ideas what could cause these cookies to grow so quickly? The size of the Id_token and Access_token seem to be substantially smaller than these cookies.

Edit: Each role I assign to the user in addition seems to add 400 size to the last cookie in the chunk which seems very large to me?

Edit 2: I am using a custom profile service would this impact the size of the final cookie:

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var subjectId = context.Subject.GetSubjectId();
        var user = await _userManager.FindByIdAsync(subjectId);

        if (user == null) return;

        var claims = new List<Claim>
        {
            new Claim("username", user.UserName),
            new Claim("email", user.Email),
            new Claim("firstname", user.FirstName),
            new Claim("lastname", user.LastName)
        };

        var roles = await _userManager.GetRolesAsync(user);
        foreach (var role in roles)
        {
            claims.Add(new Claim("role", role));
        }

        var userClaims = await _userManager.GetClaimsAsync(user);
        foreach (var userClaim in userClaims)
        {
            claims.Add(new Claim(userClaim.Type, userClaim.Value));
        }

        context.IssuedClaims = claims;
    }
1

1 Answers

1
votes

It is the application authentication cookie that is growing, not identity server cookie.

And you assumed well, cookie is growing because it encrypts all the claims, including roles in the cookie to persist them between server calls.

Alternative solution would be to configure IdentityServer to pass only minimal amount of user data that is required throughout the application lifetime on initial login. Everything else, that you might need "at certain point", you could retrieve via backend call to user-info endpoint using access_token. Drawback of this approach is that managing access_token lifetime then becomes an issue, because, unlike cookie, it does not have rolling expiration.

Other option would be to enable session for your web app, and to store cookie data into the server-side session storage, instead of the cookie itself.

Update:

Regarding your GetProfileDataAsync, it loads all claims, which is fine, but then you configure in IdentityResources configuration which filters claims you actually want to pass to the client. Configuration of IdentityServer is too big topic to discuss in details in SO question.