<commit_before>﻿/*
 * Copyright (c) <NAME>, <NAME>.  All rights reserved.
 * see license
 */

using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Claims;
using System.ServiceModel.Security;
using System.Threading.Tasks;
using Thinktecture.IdentityModel.Extensions;
using Thinktecture.IdentityServer.Core.Configuration;
using Thinktecture.IdentityServer.Core.Connect.Models;
using Thinktecture.IdentityServer.Core.Extensions;
using Thinktecture.IdentityServer.Core.Logging;
using Thinktecture.IdentityServer.Core.Services;

namespace Thinktecture.IdentityServer.Core.Connect
{
    public class TokenValidator
    {
        private readonly static ILog Logger = LogProvider.GetCurrentClassLogger();
        private readonly IdentityServerOptions _options;
        private readonly IUserService _users;
        private readonly ITokenHandleStore _tokenHandles;
        private readonly ICustomTokenValidator _customValidator;
        private readonly IClientStore _clients;

        public TokenValidator(IdentityServerOptions options, IUserService users, IClientStore clients, ITokenHandleStore tokenHandles, ICustomTokenValidator customValidator)
        {
            _options = options;
            _users = users;
            _clients = clients;
            _tokenHandles = tokenHandles;
            _customValidator = customValidator;
        }

        public virtual Task<TokenValidationResult> ValidateIdentityTokenAsync(string token)
        {
            throw new NotImplementedException();
        }

        public virtual async Task<TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            Logger.Info("Start access token validation");
            Logger.Debug("Token: " + token);

            TokenValidationResult result;

            if (token.Contains("."))
            {
                Logger.InfoFormat("Validating a JWT access token");
                result = await ValidateJwtAccessTokenAsync(token);
            }
            else
            {
                Logger.InfoFormat("Validating a reference access token");
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    Logger.InfoFormat("Checking for expected scope {0} failed", expectedScope);
                    return Invalid(Constants.ProtectedResourceErrors.InsufficientScope);
                }

                Logger.InfoFormat("Checking for expected scope {0} succeeded", expectedScope);
            }

            Logger.Debug("Calling custom token validator");
            var customResult = await _customValidator.ValidateAccessTokenAsync(result);
<commit_msg>Fixes #319<commit_after>﻿/*
 * Copyright (c) <NAME>, <NAME>.  All rights reserved.
 * see license
 */

using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Linq;
using System.Security.Claims;
using System.ServiceModel.Security;
using System.Threading.Tasks;
using Thinktecture.IdentityModel.Extensions;
using Thinktecture.IdentityServer.Core.Configuration;
using Thinktecture.IdentityServer.Core.Connect.Models;
using Thinktecture.IdentityServer.Core.Extensions;
using Thinktecture.IdentityServer.Core.Logging;
using Thinktecture.IdentityServer.Core.Services;

namespace Thinktecture.IdentityServer.Core.Connect
{
    public class TokenValidator
    {
        private readonly static ILog Logger = LogProvider.GetCurrentClassLogger();
        private readonly IdentityServerOptions _options;
        private readonly IUserService _users;
        private readonly ITokenHandleStore _tokenHandles;
        private readonly ICustomTokenValidator _customValidator;
        private readonly IClientStore _clients;

        public TokenValidator(IdentityServerOptions options, IUserService users, IClientStore clients, ITokenHandleStore tokenHandles, ICustomTokenValidator customValidator)
        {
            _options = options;
            _users = users;
            _clients = clients;
            _tokenHandles = tokenHandles;
            _customValidator = customValidator;
        }

        public virtual Task<TokenValidationResult> ValidateIdentityTokenAsync(string token)
        {
            throw new NotImplementedException();
        }

        public virtual async Task<TokenValidationResult> ValidateAccessTokenAsync(string token, string expectedScope = null)
        {
            Logger.Info("Start access token validation");
            Logger.Debug("Token: " + token);

            TokenValidationResult result;

            if (token.Contains("."))
            {
                Logger.InfoFormat("Validating a JWT access token");
                result = await ValidateJwtAccessTokenAsync(token);
            }
            else
            {
                Logger.InfoFormat("Validating a reference access token");
                result = await ValidateReferenceAccessTokenAsync(token);
            }

            if (result.IsError)
            {
                return result;
            }

            if (expectedScope.IsPresent())
            {
                var scope = result.Claims.FirstOrDefault(c => c.Type == Constants.ClaimTypes.Scope && c.Value == expectedScope);
                if (scope == null)
                {
                    Logger.InfoFormat("Checking for expected scope {0} failed", expectedScope);
                    return Invalid(Constants.ProtectedResourceErrors.InsufficientScope);
                }

                Logger.InfoFormat("Checking for expected scope {0} succeeded", expectedScope);
            }

            Logger.Debug("Calling custom token validator");
            var customResult = await _customValidator.ValidateAccessTokenAsync(result);

{'fraction_non_alphanumeric': 0.07483215981660389, 'fraction_numerical': 0.0011462256427050926, 'mean_word_length': 2.5803048065650644, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5318305', 'n_tokens_mistral': 1444, 'n_tokens_neox': 1417, 'n_words': 345}