0

I have a problem with the identity server. It sends a few identity server methods to each request after just a few minutes when I sign in with the identity server manager. Actually, it doesn't need those requests, but it sends them. I don't use HttpContext.User things related to the Indentity Server... In every single of my request to any Controllers Action, it's first querying to Identity tables like; AspNetUsers, AspNetUserClaims, AspNetRoles, AspNetRoleClaims.

Example of ProblemController Constructor like;

    private readonly IProblemService _problemService;

    public ProblemsController(IProblemService problemService)
    {
        _problemService = problemService;
    }

Manager;

    public class ProblemManager : ServiceBase<
    IProblemRepository,
    IProblemServiceResource,
    Problem>, IProblemService
{
    private readonly IIdentityRepository _identityRepository;
    private readonly IStringLocalizer<MainResource> _localizer;
    private readonly IServiceResources _genericServiceResources;
    protected IHttpContextAccessor HttpContextAccessor { get; }
    int userID = 0;
    public ProblemManager(
        IUnitOfWorkFactory unitOfWorkFactory,
        IProblemRepository genericRepository,
        IProblemServiceResource problemServiceResource,
        IIdentityRepository identityRepository,
        IRedisServer _caching,
        IMapper _mapper,
        IStringLocalizer<MainResource> localizer,
        IHttpContextAccessor httpContextAccessor,
        IServiceResources genericServiceResources) : base(unitOfWorkFactory, genericRepository, _caching, _mapper, problemServiceResource, problemServiceResource, localizer)
    {
        this.HttpContextAccessor = httpContextAccessor;
        userID = JwtTools.JwtDecodeManager.JwtDecode(HttpContextAccessor);
        _genericServiceResources = genericServiceResources;
    }
    public async Task<IDataResult<IEnumerable<ProblemListResponseDto>>> GetMostViewedProblems(int? pageNumber, int? filter = 3)
    {
        IEnumerable<ProblemListResponseDto> list;
        if (pageNumber.HasValue)
        {
            list = await _caching.LoadExchange(async () => await Repository.GetMostViewedProblems(pageNumber.Value, filter.Value), CacheKeys.GetMostViewedProblems + "" + CacheSubKeys._PageNumber_ + pageNumber.Value);

            if (list != null)
                return new SuccessDataResult<IEnumerable<ProblemListResponseDto>>(list);
            else
                return new ErrorDataResult<IEnumerable<ProblemListResponseDto>>(new List<string> { ServiceResources.ProblemDoesNotExist().Description }, ServiceResources.ProblemDoesNotExist().Code);
        }
    }

Repository;

    private readonly FooContext _context;

    public ProblemRepository(FooContext context) : base(context)
    {
        _context = context;
    }

    public async Task<Problem> GetProblemWithAttachment(int userID, int problemID)
    {
        var query = await _context.Problems.Include(n => n.ProblemAttachments).Where(n => n.ProblemID == problemID && n.AppUser.IsActive).FirstOrDefaultAsync();
        return query;
    }
    public async Task<IEnumerable<ProblemListResponseDto>> GetMostViewedProblems(int? pageNumber, int? filter = 3)
    {
        IEnumerable<ProblemListResponseDto> query;
        if (pageNumber.HasValue)
        {
            query = await _context.Problems.Include(n => n.AppUser).Include(n => n.Brand).Include(n => n.ProblemAttachments).Include(n => n.ProblemFollows).Include(n => n.ProblemSupportCount).Include(n => n.ProblemBookmarks).Include(n => n.ProblemViewCount)
                 .Where(n => (n.ProblemStatus == (int)Enums.Status.Published || n.ProblemStatus == (int)Enums.Status.Solved || n.ProblemStatus == (int)Enums.Status.Answered) && n.ProblemViewCount.ViewCount > 0 && n.AppUser.IsActive)
                 .OrderByDescending(x => x.ProblemViewCount.ViewCount)
                 .Skip(PageSize * (pageNumber.Value - 1)).Take(filter.Value)
                    .Select(x => new ProblemListResponseDto
                    {
                        ProblemID = x.ProblemID,
                        Name = x.Name,
                        Description = x.Description,
                        ViewCount = x.ProblemViewCount.ViewCount > 0 ? x.ProblemViewCount.ViewCount : 0,
                        ProblemSupportCount = x.ProblemSupportCount.SupportCount > 0 ? x.ProblemSupportCount.SupportCount : 0,
                        AppUserName = x.AppUser.Name,
                        AppUserUserName = x.AppUser.UserName,
                        PhotoPath = string.IsNullOrEmpty(x.AppUser.PhotoPath),
                        BrandName = x.Brand.Name,
                        BrandLogo = string.IsNullOrEmpty(x.Brand.Logo),
                        BrandUrl = x.Brand.Url,
                        ProblemAttachments = x.ProblemAttachments.Select(n => new ProblemAttachmentDto
                        {
                            AttachmentTypeID = n.AttachmentTypeID,
                            ProblemAttachmentID = n.ProblemAttachmentID,
                            ProblemID = n.ProblemID,
                            Path = n.Path,
                            CreatedDate = n.CreatedDate,
                            ModifiedDate = n.ModifiedDate,
                        }).ToList()
                    }).AsNoTracking().ToListAsync();
            return query;
        }
        return null;
    }

My Context inherited from IdentityDbContext;

public partial class FooContext : IdentityDbContext<AppUser, AppRole, int>

Startup Configuration About Authentication, JWT and Identity;

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(jwt =>
        {
            jwt.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true, 
                IssuerSigningKey = new SymmetricSecurityKey(new HMACSHA512(Encoding.UTF8.GetBytes(_jwtInfo.SecurityKey)).Key), 
                ValidateIssuer = false,
                ValidateAudience = false,
                RequireExpirationTime = false,
                ValidateLifetime = true,
                ValidIssuer = _jwtInfo.Issuer,
                ValidAudience = _jwtInfo.Audience,
                ClockSkew = TimeSpan.FromMinutes(0)
            };
        });

        services.AddIdentity<AppUser, AppRole>().AddEntityFrameworkStores<FooContext>().AddErrorDescriber<LocalizedIdentityErrorDescriber>()
        .AddDefaultTokenProviders();

Startup Configure Method is like;

        app.UseCookiePolicy();
        app.UseSession();

        var supportedCultures = new[] { "tr-TR", "en", "de", "ru", "ko" };
        var localizationOptions = new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
            .AddSupportedCultures(supportedCultures)
            .AddSupportedUICultures(supportedCultures);
        app.UseRequestLocalization(localizationOptions);

        app.UseHealthChecks("/health", new HealthCheckOptions
        {
            ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse,
        });

        app.UseMiniProfiler();
        loggerFactory.AddNLog();
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "Foo.WebApi v1");
        });

        if (!env.IsDevelopment())
        {
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseMiddleware<ExceptionHandlingMiddleware>();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseStatusCodePages();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });

And Finally JwtDecode method;

    public static int JwtDecode(IHttpContextAccessor httpContextAccessor)
    {
        StringValues values;

        httpContextAccessor.HttpContext.Request.Headers.TryGetValue("Authorization", out values);
        var token = values.ToString().Split(' ');
        if (token.Length > 1)
        {
            var handler = new JwtSecurityTokenHandler();
            try
            {
                var securityToken = handler.ReadToken(token.Last());
                var jwtToken = securityToken as JwtSecurityToken;

                if (!IsValid(token.Last()))
                {
                    return 0;
                }
                else
                    return Convert.ToInt32(jwtToken.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier).Value);
            }
            catch (SecurityTokenExpiredException ex)
            {

                return 0;
            }
        }
        return 0;
    }
/Api/Home/ProductList
{
  //**Querying AspNetUsers, AspNetUserClaims, AspNetRoles, AspNetRoleClaims.**
  //return ProductRepository.ProductList;
}

Maybe it's happenning befor the action call, maybe inside the Dependency Injection, maybe at the action Attribute. The attribute of the action is like;

 [HttpPost("[action]")]
 [Authorize(AuthenticationSchemes = "Bearer", Roles = Role.Member)]

You can look at the below image to see the requests. Mini Profiler Request Detail

I want only the request related tables is going to get from Database.

/Api/Home/ProductList
{
  //**Get ProductList Only**
  //return ProductRepository.ProductList;
}

I can share any other details if you want..

What is the missing point do you think?

EDIT: The problem was because of the cookie integration. I removed cookie integration part, and it doesn't send requests with Identity tables anymore. But I am wondering, I use tokens for authorization control, should I use the cookie integration or how can I use kind of true? My cookie integration code is below:

        services.ConfigureApplicationCookie(options =>
        {
            options.Cookie.Name = "auth_cookie";
            options.Cookie.SameSite = SameSiteMode.Lax;
            options.LoginPath = string.Empty;
            options.AccessDeniedPath = new PathString("/api/contests");
            options.Events.OnRedirectToLogin = context =>
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return Task.CompletedTask;
            };
        });

At the same time, I also removed this configure code line:

app.UseCookiePolicy();
  • Can you provide a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example)? When I tested, only the four tables AspNetUsers, AspNetUserClaims, AspNetRoles, and AspNetRoleClaims were queried when logging in. When calling /Api/Home/ProductList, it only queries the corresponding Product table. – Chen Jul 25 '23 at 06:51
  • Hi @Chen the project is really big, but I've edited the code in detail as possible as minimal reproducible example. If you or anybody needs any more information, I'd like to share.. – Neslihan Akbaba Jul 25 '23 at 16:40
  • These look ok. Under normal circumstances, you will not re-read tables such as AspNetUsers after logging in, unless you force a re-login in some places. – Chen Jul 27 '23 at 07:18
  • After removing cookies from the Startup.cs it didn't request Identity tables again. What should be the configuration for cookies in Startup.cs? – Neslihan Akbaba Jul 27 '23 at 10:54
  • Please check [this link](https://stackoverflow.com/a/44503079/18789859). – Chen Jul 31 '23 at 01:45

0 Answers0