public async Task <string> CreateCustomTokenAsync(
            string uid,
            IDictionary <string, object> developerClaims = null,
            CancellationToken cancellationToken          = default(CancellationToken))
        {
            if (string.IsNullOrEmpty(uid))
            {
                throw new ArgumentException("uid must not be null or empty");
            }
            else if (uid.Length > 128)
            {
                throw new ArgumentException("uid must not be longer than 128 characters");
            }
            if (developerClaims != null)
            {
                foreach (var entry in developerClaims)
                {
                    if (ReservedClaims.Contains(entry.Key))
                    {
                        throw new ArgumentException(
                                  $"reserved claim {entry.Key} not allowed in developerClaims");
                    }
                }
            }

            var header = new JsonWebSignature.Header()
            {
                Algorithm = "RS256",
                Type      = "JWT"
            };

            var issued = (int)(_clock.UtcNow - UnixEpoch).TotalSeconds;
            var keyId  = await _signer.GetKeyIdAsync(cancellationToken).ConfigureAwait(false);

            var payload = new CustomTokenPayload()
            {
                Uid                   = uid,
                Issuer                = keyId,
                Subject               = keyId,
                Audience              = FirebaseAudience,
                IssuedAtTimeSeconds   = issued,
                ExpirationTimeSeconds = issued + TokenDurationSeconds,
            };

            if (developerClaims != null && developerClaims.Count > 0)
            {
                payload.Claims = developerClaims;
            }
            return(await JwtUtils.CreateSignedJwtAsync(
                       header, payload, _signer, cancellationToken).ConfigureAwait(false));
        }