public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var success = new SecretValidationResult {
                Success = true
            };
            var fail = new SecretValidationResult {
                Success = false
            };

            var issuer = GetIssuer(parsedSecret);

            if (string.IsNullOrEmpty(issuer) || issuer == "NULL")
            {
                _logger.LogInformation("Issuer is not present");
                return(fail);
            }

            var isValid = await _partiesValidation.IsValidParty(issuer);

            if (!isValid)
            {
                _logger.LogInformation("{Issuer} is not a valid party", issuer);
                return(fail);
            }

            return(success);
        }
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            if (secrets.Any())
            {
                if (secrets.First().Type == "confirmation.test")
                {
                    var cnf = new Dictionary <string, string>
                    {
                        { "x5t#S256", "foo" }
                    };

                    var result = new SecretValidationResult
                    {
                        Success      = true,
                        Confirmation = JsonConvert.SerializeObject(cnf)
                    };

                    return(Task.FromResult(result));
                }
            }

            return(Task.FromResult(new SecretValidationResult {
                Success = false
            }));
        }
示例#3
0
        /// <summary>
        /// Validate api secrets
        /// </summary>
        /// <param name="secrets"></param>
        /// <param name="parsedSecret"></param>
        /// <returns></returns>
        public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            SecretValidationResult validationResult;

            // Impersonation. If the current user is an admin, we allow any password to be used for the token
            if (_contextAccessor.HttpContext.User.Identity.IsAuthenticated)
            {
                if (_contextAccessor.HttpContext.User.HasClaim(tbl => tbl.Type == ClaimTypes.Role && (tbl.Value.ToLower() == "root" || tbl.Value.ToLower() == "moderator")))
                {
                    validationResult = new SecretValidationResult()
                    {
                        IsError = false,
                        Success = true
                    };

                    return(await Task.FromResult(validationResult));
                }
            }

            // Owner's credentials
            var result = _passwordHasher.VerifyHashedPassword(
                parsedSecret.Id,
                secrets?.FirstOrDefault()?.Value,
                parsedSecret.Credential.ToString());

            validationResult = new SecretValidationResult
            {
                IsError = result == PasswordVerificationResult.Failed,
                Success = result == PasswordVerificationResult.Success
            };

            return(await Task.FromResult(validationResult));
        }
示例#4
0
        /// <summary>
        /// 设置秘钥类型后会触发该实现进行验证秘钥
        /// ClientSecrets = new[] {
        ///      new Secret()
        ///      {
        ///          Value = client.ClientSecrets,
        ///          Type = IdentityServerConstants.SecretTypes.SharedSecret
        ///      }
        ///  }
        /// </summary>
        /// <param name="secrets"></param>
        /// <param name="parsedSecret"></param>
        /// <returns></returns>
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            SecretValidationResult secretValidationResult = new SecretValidationResult();

            secretValidationResult.Success = true;
            secretValidationResult.IsError = false;
            return(Task.FromResult(secretValidationResult));
        }
示例#5
0
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var result = new SecretValidationResult {
                Success = true
            };

            return(Task.FromResult(result));
        }
示例#6
0
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            //parsedSecret.
            //IdentityServer4.Validation.ClientSecretValidator
            var result = new SecretValidationResult {
                Success = false
            };

            return(Task.FromResult(result));
        }
        public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            // this is just for demo
            var success = new SecretValidationResult
            {
                IsError = false,
                Success = true
            };

            return(Task.FromResult(success));
        }
示例#8
0
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            var fail = new ClientSecretValidationResult {
                IsError = true
            };

            var parsedSecret = await ParseAsync(context);

            if (parsedSecret == null)
            {
                await RaiseFailureEventAsync("unknown", "No client id found");

                return(fail);
            }

            var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id);

            if (client == null)
            {
                await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client");

                return(fail);
            }

            SecretValidationResult secretValidationResult = null;

            if (client.RequireClientSecret || !client.IsImplicitOnly())
            {
                secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret);

                if (secretValidationResult.Success == false)
                {
                    await RaiseFailureEventAsync(client.ClientId, "Invalid client secret");

                    return(fail);
                }
            }

            var success = new ClientSecretValidationResult
            {
                IsError      = false,
                Client       = client,
                Secret       = parsedSecret,
                Confirmation = secretValidationResult?.Confirmation
            };

            await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type);

            return(success);
        }
示例#9
0
    /// <inheritdoc/>
    public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
    {
        var fail = Task.FromResult(new SecretValidationResult {
            Success = false
        });

        if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.X509Certificate)
        {
            _logger.LogDebug("X509 name secret validator cannot process {type}", parsedSecret.Type ?? "null");
            return(fail);
        }

        if (!(parsedSecret.Credential is X509Certificate2 cert))
        {
            throw new InvalidOperationException("Credential is not a x509 certificate.");
        }

        var name = cert.Subject;

        if (name == null)
        {
            _logger.LogWarning("No subject/name found in X509 certificate.");
            return(fail);
        }

        var nameSecrets = secrets.Where(s => s.Type == IdentityServerConstants.SecretTypes.X509CertificateName);

        if (!nameSecrets.Any())
        {
            _logger.LogDebug("No x509 name secrets configured for client.");
            return(fail);
        }

        foreach (var nameSecret in nameSecrets)
        {
            if (name.Equals(nameSecret.Value, StringComparison.Ordinal))
            {
                var result = new SecretValidationResult
                {
                    Success      = true,
                    Confirmation = cert.CreateThumbprintCnf()
                };

                return(Task.FromResult(result));
            }
        }

        _logger.LogDebug("No matching x509 name secret found.");
        return(fail);
    }
        public async Task <SecretValidationResult> ValidateAsync(AssertionModel assertion)
        {
            var fail = new SecretValidationResult {
                Success = false
            };

            if (assertion == null)
            {
                _logger.LogInformation("The client assertion is not provided.");
                return(fail);
            }

            if (assertion.Typ == null || !assertion.Typ.Equals("jwt", StringComparison.InvariantCultureIgnoreCase))
            {
                _logger.LogError("Client assertion \"typ\" header is not \"JWT\".");
                return(fail);
            }

            if (assertion.Exp - assertion.Iat != 30)
            {
                _logger.LogError("Client assertion validity should be exactly 30 seconds.");
                return(fail);
            }

            if (!assertion.Certificates.Any())
            {
                _logger.LogInformation("The x5c certificates chain is not provided.");
                return(fail);
            }

            try
            {
                if (!await _certificateValidator.IsValid(DateTime.UtcNow, assertion.Certificates.ToArray()))
                {
                    _logger.LogInformation("Certificate chain is not valid");
                    return(fail);
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Could not load certificate from x5C header.");
                return(fail);
            }

            return(await Task.FromResult(new SecretValidationResult { Success = true }));
        }
示例#11
0
        public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            _logger.LogDebug("Validate client assertion started");
            var fail = new SecretValidationResult {
                Success = false
            };

            if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer)
            {
                _logger.LogDebug($"Secret type is not a JwtBearer, instead it was {parsedSecret.Type}");
                return(fail);
            }
            if (!(parsedSecret.Credential is string jwtTokenString))
            {
                _logger.LogDebug("Secret is not like a JWT string");
                return(fail);
            }
            return(await _assertionManager.ValidateAsync(jwtTokenString));
        }
示例#12
0
        public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var fail = new SecretValidationResult {
                Success = false
            };

            var assertion = parsedSecret.Credential as string;

            if (assertion == null)
            {
                _logger.LogInformation("The client assertion is not provided.");
                return(fail);
            }

            var certificates = _assertionParser.GetCertificatesData(assertion);

            if (!certificates.Any())
            {
                _logger.LogInformation("The x5c certificates chain is not provided.");
                return(fail);
            }

            var validateCertificateResult = await _schemeOwnerClient.ValidateCertificate(new ClientAssertion(), certificates.ToArray()).ConfigureAwait(false);

            if (!validateCertificateResult.Validity)
            {
                _logger.LogError("Scheme Owner didn't validate the certificates.");
                return(fail);
            }

            var secretsIncludingCertificates = secrets.ToList();

            secretsIncludingCertificates.AddRange(certificates.Select(c => new Secret
            {
                Type  = IdentityServerConstants.SecretTypes.X509CertificateBase64,
                Value = c
            }));

            var result = await _innerValidator.Instance.ValidateAsync(secretsIncludingCertificates, parsedSecret);

            return(result);
        }
示例#13
0
        async public Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            foreach (var secret in secrets
                     .Where(s => "SecretsVault-Secret".Equals(s.Type, StringComparison.CurrentCultureIgnoreCase)))
            {
                var secretsVersion = await _secretsVaultManager.GetSecretVersion(secret.Value);

                if (parsedSecret.Credential?.ToString() == secretsVersion.Secret)
                {
                    return(new SecretValidationResult()
                    {
                        Success = true
                    });
                }
            }

            var result = new SecretValidationResult()
            {
                Success = false
            };

            return(result);
        }
        public virtual Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var fail = Task.FromResult(new SecretValidationResult {
                Success = false
            });

            if (parsedSecret == null || parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.X509Certificate)
            {
                this.Logger.LogDebugIfEnabled($"{this.SecretType} secret validator cannot process {parsedSecret?.Type ?? "null"}.");

                return(fail);
            }

            if (!(parsedSecret.Credential is X509Certificate2 certificate))
            {
                throw new InvalidOperationException("Credential is not a x509 certificate.");
            }

            var issuer = certificate.Issuer;

            if (issuer == null)
            {
                this.Logger.LogWarningIfEnabled("The certificate-issuer is null.");

                return(fail);
            }

            var issuerSecrets = secrets.Where(secret => string.Equals(secret.Type, this.SecretType, StringComparison.Ordinal)).ToArray();

            if (!issuerSecrets.Any())
            {
                this.Logger.LogDebugIfEnabled($"No {this.SecretType} secrets configured for client.");

                return(fail);
            }

            // ReSharper disable All
            foreach (var secret in issuerSecrets)
            {
                var secretDescription = string.IsNullOrEmpty(secret.Description) ? "no description" : secret.Description;

                if (issuer.Equals(secret.Value, StringComparison.OrdinalIgnoreCase))
                {
                    var values = new Dictionary <string, string>
                    {
                        { "x5t#S256", certificate.Thumbprint }
                    };

                    var confirmation = JsonConvert.SerializeObject(values);

                    var result = new SecretValidationResult
                    {
                        Success      = true,
                        Confirmation = confirmation
                    };

                    return(Task.FromResult(result));
                }
            }
            // ReSharper restore All

            this.Logger.LogDebugIfEnabled($"No matching {this.SecretType} secret found.");

            return(fail);
        }
        /// <summary>
        /// Validates the current request.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            _logger.LogDebug("Start client validation");

            var fail = new ClientSecretValidationResult
            {
                IsError = true
            };

            var parsedSecret = await _parser.ParseAsync(context);

            if (parsedSecret == null)
            {
                await RaiseFailureEventAsync("unknown", "No client id found");

                _logger.LogError("No client identifier found");
                return(fail);
            }

            // load client
            var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id) as ClientExtra;

            if (client == null)
            {
                await RaiseFailureEventAsync(parsedSecret.Id, $"Unknown client for tenant: '{_scopedTenantRequestContext.Context.TenantName}'");

                _logger.LogError($"No client with id '{parsedSecret.Id}' for tenant: '{_scopedTenantRequestContext.Context.TenantName}' found. aborting");
                return(fail);
            }


            SecretValidationResult secretValidationResult = null;

            if (!client.RequireClientSecret || client.IsImplicitOnly())
            {
                _logger.LogDebug("Public Client - skipping secret validation success");
            }
            else
            {
                ////////////////////////////////////////
                // Check if this is a refresh_token
                ////////////////////////////////////////
                bool continueValidation = true;
                if (!client.RequireRefreshClientSecret)
                {
                    try
                    {
                        var parameters = (await context.Request.ReadFormAsync()).AsNameValueCollection();
                        var grantType  = parameters.Get(OidcConstants.TokenRequest.GrantType);
                        if (!string.IsNullOrWhiteSpace(grantType) && grantType == OidcConstants.GrantTypes.RefreshToken)
                        {
                            // let it through
                            _logger.LogDebug("RequireRefreshClientSecret == false - skipping secret validation success");
                            continueValidation = false;
                        }
                    }
                    catch (Exception ex)
                    {
                        // let it through
                        _logger.LogDebug("RequireRefreshClientSecret == false - skipping secret validation success");
                        continueValidation = false;
                    }
                }
                if (continueValidation)
                {
                    secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret);

                    if (secretValidationResult.Success == false)
                    {
                        await RaiseFailureEventAsync(client.ClientId, "Invalid client secret");

                        _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId);

                        return(fail);
                    }
                }
            }

            _logger.LogDebug("Client validation success");

            var success = new ClientSecretValidationResult
            {
                IsError      = false,
                Client       = client,
                Secret       = parsedSecret,
                Confirmation = secretValidationResult?.Confirmation
            };

            await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type);

            return(success);
        }
示例#16
0
    /// <summary>
    /// Validates a secret
    /// </summary>
    /// <param name="secrets">The stored secrets.</param>
    /// <param name="parsedSecret">The received secret.</param>
    /// <returns>
    /// A validation result
    /// </returns>
    /// <exception cref="System.ArgumentException">ParsedSecret.Credential is not a JWT token</exception>
    public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
    {
        var fail = new SecretValidationResult {
            Success = false
        };
        var success = new SecretValidationResult {
            Success = true
        };

        if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer)
        {
            return(fail);
        }

        if (!(parsedSecret.Credential is string jwtTokenString))
        {
            _logger.LogError("ParsedSecret.Credential is not a string.");
            return(fail);
        }

        List <SecurityKey> trustedKeys;

        try
        {
            trustedKeys = await secrets.GetKeysAsync();
        }
        catch (Exception e)
        {
            _logger.LogError(e, "Could not parse secrets");
            return(fail);
        }

        if (!trustedKeys.Any())
        {
            _logger.LogError("There are no keys available to validate client assertion.");
            return(fail);
        }

        var validAudiences = new[]
        {
            // token endpoint URL
            string.Concat(_urls.BaseUrl.EnsureTrailingSlash(), Constants.ProtocolRoutePaths.Token),
            // TODO: remove the issuer URL in a future major release?
            // issuer URL
            string.Concat((await _issuerNameService.GetCurrentAsync()).EnsureTrailingSlash(), Constants.ProtocolRoutePaths.Token)
        }.Distinct();

        var tokenValidationParameters = new TokenValidationParameters
        {
            IssuerSigningKeys        = trustedKeys,
            ValidateIssuerSigningKey = true,

            ValidIssuer    = parsedSecret.Id,
            ValidateIssuer = true,

            ValidAudiences   = validAudiences,
            ValidateAudience = true,

            RequireSignedTokens   = true,
            RequireExpirationTime = true,

            ClockSkew = TimeSpan.FromMinutes(5)
        };

        var handler = new JsonWebTokenHandler()
        {
            MaximumTokenSizeInBytes = _options.InputLengthRestrictions.Jwt
        };
        var result = handler.ValidateToken(jwtTokenString, tokenValidationParameters);

        if (!result.IsValid)
        {
            _logger.LogError(result.Exception, "JWT token validation error");
            return(fail);
        }

        var jwtToken = (JsonWebToken)result.SecurityToken;

        if (jwtToken.Subject != jwtToken.Issuer)
        {
            _logger.LogError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id.");
            return(fail);
        }

        var exp = jwtToken.ValidTo;

        if (exp == DateTime.MinValue)
        {
            _logger.LogError("exp is missing.");
            return(fail);
        }

        var jti = jwtToken.Id;

        if (jti.IsMissing())
        {
            _logger.LogError("jti is missing.");
            return(fail);
        }

        if (await _replayCache.ExistsAsync(Purpose, jti))
        {
            _logger.LogError("jti is found in replay cache. Possible replay attack.");
            return(fail);
        }
        else
        {
            await _replayCache.AddAsync(Purpose, jti, exp.AddMinutes(5));
        }

        return(success);
    }
        /// <summary>
        /// 登录校验密钥
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            var _signInManager = (SignInManager <ApplicationUser>)context.RequestServices.GetService(typeof(SignInManager <ApplicationUser>));

            _logger.LogDebug("Start client validation");
            //错误返回
            var fail = new ClientSecretValidationResult
            {
                IsError = true
            };
            //根据上下文查找密钥
            var parsedSecret = await _parser.ParseAsync(context);

            if (parsedSecret == null)
            {
                await RaiseFailureEventAsync("unknown", "No client id found");

                _logger.LogError("No client identifier found");
                return(fail);
            }

            // 加载客户端配置
            var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id);

            if (client == null)
            {
                await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client");

                _logger.LogError("No client with id '{clientId}' found. aborting", parsedSecret.Id);
                return(fail);
            }

            SecretValidationResult secretValidationResult = null;

            if (!client.RequireClientSecret || client.IsImplicitOnly())
            {
                _logger.LogDebug("Public Client - skipping secret validation success");
            }
            else
            {
                //验证客户端密钥
                secretValidationResult = await _validator.ValidateAsync(parsedSecret, client.ClientSecrets);

                if (secretValidationResult.Success == false)
                {
                    await RaiseFailureEventAsync(client.ClientId, "Invalid client secret");

                    _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId);

                    return(fail);
                }
            }

            _logger.LogDebug("Client validation success");
            //var user = await _signInManager.UserManager.FindByNameAsync(context.User.Identity.Name);
            //var  claimsPrincipal = await _signInManager.ClaimsFactory.CreateAsync(user);
            var success = new ClientSecretValidationResult
            {
                IsError      = false,
                Client       = client,
                Secret       = parsedSecret,
                Confirmation = secretValidationResult?.Confirmation
            };

            await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type);

            return(success);
        }
示例#18
0
    /// <summary>
    /// Validates the current request.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <returns></returns>
    public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
    {
        using var activity = Tracing.ValidationActivitySource.StartActivity("ClientSecretValidator.Validate");

        _logger.LogDebug("Start client validation");

        var fail = new ClientSecretValidationResult
        {
            IsError = true
        };

        var parsedSecret = await _parser.ParseAsync(context);

        if (parsedSecret == null)
        {
            await RaiseFailureEventAsync("unknown", "No client id found");

            _logger.LogError("No client identifier found");
            return(fail);
        }

        // load client
        var client = await _clients.FindEnabledClientByIdAsync(parsedSecret.Id);

        if (client == null)
        {
            await RaiseFailureEventAsync(parsedSecret.Id, "Unknown client");

            _logger.LogError("No client with id '{clientId}' found. aborting", parsedSecret.Id);
            return(fail);
        }

        SecretValidationResult secretValidationResult = null;

        if (!client.RequireClientSecret || client.IsImplicitOnly())
        {
            _logger.LogDebug("Public Client - skipping secret validation success");
        }
        else
        {
            secretValidationResult = await _validator.ValidateAsync(client.ClientSecrets, parsedSecret);

            if (secretValidationResult.Success == false)
            {
                await RaiseFailureEventAsync(client.ClientId, "Invalid client secret");

                _logger.LogError("Client secret validation failed for client: {clientId}.", client.ClientId);

                return(fail);
            }
        }

        _logger.LogDebug("Client validation success");

        var success = new ClientSecretValidationResult
        {
            IsError      = false,
            Client       = client,
            Secret       = parsedSecret,
            Confirmation = secretValidationResult?.Confirmation
        };

        await RaiseSuccessEventAsync(client.ClientId, parsedSecret.Type);

        return(success);
    }
        /// <summary>
        /// Validates a secret
        /// </summary>
        /// <param name="secrets">The stored secrets.</param>
        /// <param name="parsedSecret">The received secret.</param>
        /// <returns>
        /// A validation result
        /// </returns>
        /// <exception cref="System.ArgumentException">ParsedSecret.Credential is not a JWT token</exception>
        public async Task <SecretValidationResult> ValidateAsync(IEnumerable <Secret> secrets, ParsedSecret parsedSecret)
        {
            var fail = new SecretValidationResult {
                Success = false
            };
            var success = new SecretValidationResult {
                Success = true
            };

            if (parsedSecret.Type != IdentityServerConstants.ParsedSecretTypes.JwtBearer)
            {
                return(fail);
            }

            if (!(parsedSecret.Credential is string jwtTokenString))
            {
                _logger.LogError("ParsedSecret.Credential is not a string.");
                return(fail);
            }

            List <SecurityKey> trustedKeys;

            try
            {
                trustedKeys = await secrets.GetKeysAsync();
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Could not parse secrets");
                return(fail);
            }

            if (!trustedKeys.Any())
            {
                _logger.LogError("There are no keys available to validate client assertion.");
                return(fail);
            }

            var tokenValidationParameters = new TokenValidationParameters
            {
                IssuerSigningKeys        = trustedKeys,
                ValidateIssuerSigningKey = true,

                ValidIssuer    = parsedSecret.Id,
                ValidateIssuer = true,

                ValidAudience    = _audienceUri,
                ValidateAudience = true,

                RequireSignedTokens   = true,
                RequireExpirationTime = true
            };

            try
            {
                var handler = new JwtSecurityTokenHandler();
                handler.ValidateToken(jwtTokenString, tokenValidationParameters, out var token);

                var jwtToken = (JwtSecurityToken)token;
                if (jwtToken.Subject != jwtToken.Issuer)
                {
                    _logger.LogError("Both 'sub' and 'iss' in the client assertion token must have a value of client_id.");
                    return(fail);
                }

                return(success);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "JWT token validation error");
                return(fail);
            }
        }