Unable to resolve service for type at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider - asp.net-core

I am attempting to receive data from the server controller, stocks.
I get this error:
"System.InvalidOperationException: Unable to resolve service for type myBackEnd.Models.StockContext' while attempting to activate 'myBackEnd.Controllers.StockController'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService
(IServiceProvider sp, Type type, Type requiredBy, Boolean
isDefaultParameterRequired"
Here is my stocks controller code:
namespace myBackEnd.Controllers
{
[Route("api/stock")]
[Produces("application/json")]
public class StockController : ControllerBase
{
private readonly int fastEmaPeriod = 10;
private readonly IHttpClientFactory _httpClientFactory;
private readonly Models.StockContext _context;
public StockController(Models.StockContext context, IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
_context = context;
}
// POST api/values
[HttpPost]
public async Task<IActionResult> Post([FromBody]Models.Stock stock)
{
_context.Stocks.Add(stock);
await _context.SaveChangesAsync();
return Ok(stock);
}
This is the startup.cs code:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("MyPolicy", corsBuilder =>
{
corsBuilder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
services.AddDbContext<DataContext>(x => x.UseInMemoryDatabase("TestDb"));
services.AddHttpClient();
services.AddAutoMapper();
// configure strongly typed settings objects
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
// configure jwt authentication
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();
var userId = int.Parse(context.Principal.Identity.Name);
var user = userService.GetById(userId);
if (user == null)
{
// return unauthorized if user no longer exists
context.Fail("Unauthorized");
}
return Task.CompletedTask;
}
};
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
// configure DI for application services
services.AddScoped<IUserService, UserService>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
This worked before I added the registration, login and
// configure DI for application services
services.AddScoped();

The problem was the DB context was not registered for dependency injection.
Adding:
services.AddDbContext<Models.StockContext>(opt => opt.UseInMemoryDatabase("item"));
fixed the problem.

Related

How to get the id of the user out of jwt token in .net core or how to return a value from a custom authorization attribute?

I create my token in the following way
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, "tada")
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var encryptedtoken = tokenHandler.WriteToken(token);
And now i would like to simply get the users id from my authorize attribute and put it in the context somehow?
I know i can decode the token like so
[Authorize(Roles = "tada")]
public IActionResult Get()
{
var token = HttpContext.Request.Headers[HeaderNames.Authorization][0];
var tokenArray = token.Split(" ");
var handler = new JwtSecurityTokenHandler();
var tokenS = handler.ReadToken(tokenArray[1]) as JwtSecurityToken;
return Ok(tokenS.Payload.SingleOrDefault(t => t.Key == "unique_name").Value);
}
But how do i reuse this code in a more clever way can i create my own authorization attribute that will store it in the context if there is no way, how do i create a singleton/scoped/transient service?
here's how i configure jwt
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<CatstagramDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddIdentity<User, IdentityRole>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequiredLength = 6;
})
.AddEntityFrameworkStores<CatstagramDbContext>();
var applicationSettingConfiguration = Configuration.GetSection("ApplicationSettings");
services.Configure<AppSettings>(applicationSettingConfiguration);
var appSettings = applicationSettingConfiguration.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Secret);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseMigrationsEndPoint();
}
app.UseCors(options => options.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.ApplyMigrations();
}
}
I am using this function to get any token claim value
public static string GetClaimValue(HttpContext httpContext, string valueType)
{
if (string.IsNullOrEmpty(valueType)) return null;
var identity = httpContext.User.Identity as ClaimsIdentity;
var valueObj = identity == null ? null : identity.Claims.FirstOrDefault(x => x.Type == valueType);
return valueObj==null? null:valueObj.Value;
}
you can use it like this
var name = GetClaimValue(HttpContext, "unique_name");
When the authentication middleware authenticates the request, it populates HttpContext.User property with a ClaimsPrincipal that holds the claims for the current user.
ClaimsPrincipal class has an extension method in System.Security.Claims in namespace called FindFirstValue.
User.FindFirstValue("unique_name");
gives you the value for the first unique_name claim.
Source: https://github.com/dotnet/aspnetcore/blob/2be49d930a5fb53e781abd175c3b2a8f8b7827d4/src/Identity/Extensions.Core/src/PrincipalExtensions.cs

Role based Authentication: Bearer Token to Cookie using Microsoft .NetCore 3.1

I'm trying to transform.NetCore 3.1 Code from Bearer Token implementation to Cookie-based implementation Also trying to make Role-based authorization work with existing code. Can you please help me to change this code? The below code shows currently how Bearer Token is retrieved and the next part shows how role-based authorization is implemented in code.
Here is the current Bearer Token implementation.
var key = Encoding.ASCII.GetBytes(Configuration["AppSettings:Secret"]);
var signingKey = new SymmetricSecurityKey(key);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
IssuerSigningKey = signingKey,
ValidateIssuer = false,
ValidateAudience = false
};
});
Following annotation currently used for Role-based Authorization -
[Authorize(Roles = "1")]
[Route("api/[controller]")]
[ApiController]
public class JobLogsController : ControllerBase
{
private readonly EtpRepoContext _context;
private IJobLogsRepository _jobLogsRepository;
private IConfiguration _configuration;
public JobLogsController(EtpRepoContext context, IJobLogsRepository jobLogsRepository, IConfiguration configuration)
{
_context = context;
_jobLogsRepository = jobLogsRepository;
_configuration = configuration;
}
// GET: api/JobLogs
[HttpGet]
public async Task<ActionResult<IEnumerable<JobLog>>> GetJobLog()
{
return await _context.JobLog.ToListAsync();
}
// GET: api/JobLogs/5
[HttpGet("{id}")]
[ProducesResponseType(typeof(JobDetail), 200)]
[ProducesResponseType(typeof(string), 400)]
public IActionResult FindById([FromRoute] String id)
{
string contentStr = "";
try
{
if(id.Length >= 10)
{
contentStr = _jobLogsRepository.GetLogById(id);
}
else
{
contentStr = _jobLogsRepository.GetFileById(id);
}
var content = Newtonsoft.Json.JsonConvert.SerializeObject(new { content = contentStr });
return Ok(content);
}
catch (Exception ex)
{
return StatusCode(500, "Internal server error");
}
}
This is how the Microsoft identity model is used to claim the token.
public class ClaimsTransformer : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
ClaimsIdentity claimsIdentity = (ClaimsIdentity)principal.Identity;
// flatten realm_access because Microsoft identity model doesn't support nested claims
// by map it to Microsoft identity model, because automatic JWT bearer token mapping already processed here
if (claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim((claim) => claim.Type == "identity"))
{
var realmAccessClaim = claimsIdentity.FindFirst((claim) => claim.Type == "identity");
dynamic realmAccessAsDict = JsonConvert.DeserializeObject<Object>(realmAccessClaim.Value);
string role = realmAccessAsDict.role.ToString();
claimsIdentity.AddClaim(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", role));
//var role = realmAccessClaim.
//var realmAccessAsDict = JsonConvert.DeserializeObject<Object>(realmAccessClaim.Value);
/*if (realmAccessAsDict["role"] != null)
{
foreach (var role in realmAccessAsDict["role"])
{
claimsIdentity.AddClaim(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", role));
}
}*/
}
return Task.FromResult(principal);
}
}
}

Add To Context Items in SignalR Middleware

So I want to setup a User Middleware which works for SignalR Hubs and Controllers.
It works fine with normal requests but with signalr it gets called but doesnt add to context.
Is it even possible? If so how can i do it?
namespace PortalCore.Middleware
{
public class JwtMiddleware
{
private readonly RequestDelegate _next;
public JwtMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context, AuthService authService)
{
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (token != null)
{
AttachUserToContext(context, authService, token);
}
await _next(context);
}
private async void AttachUserToContext(HttpContext context, AuthService authService, string token)
{
User user = null;
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey =
new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(authService.SecretKey)),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
user = await authService.GetUserByUid(jwtToken.Claims.FirstOrDefault()?.Value);
}
catch (Exception e)
{
}
context.Items["User"] = user;
}
}
}
if you want to check auth of signalR hub then you can do it with query string.you can send token with signalR client url.After take token from query string and set to context.
Hub Code:
[Authorize]
public class ChatHub : Hub
you can add token in Context :
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrWhiteSpace(accessToken) &&
(path.StartsWithSegments("/api/hubs/chatHub")))
{
context.Token = accessToken;
}
return Task.CompletedTask;
},

Identity Server 4 Authorization Flow

Identity server 4 and ASP.Net Core 3 noob here, what I'm trying to do is kinda simple: a client should do an HTTP Get request to a remote controller and retrieve some data after being authorized by the Identity Server.
I'm using a code flow as GrantType.
Identity Server services configuration:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// Identity server database
string connectionString = Config.GetConnectionString("IdentityServerDatabase");
services.AddDbContext<IdentityServerDatabaseContext>(config =>
{
config.UseSqlServer(connectionString);
});
// Easy password for testing
services.AddIdentity<ApplicationUser, IdentityRole>(config =>
{
config.Password.RequiredLength = 4;
config.Password.RequireDigit = false;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireUppercase = false;
config.SignIn.RequireConfirmedAccount = true;
config.User.RequireUniqueEmail = true;
})
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<IdentityServerDatabaseContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.AddIdentityServer()
// Identity User extension
.AddAspNetIdentity<ApplicationUser>()
.AddDeveloperSigningCredential()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
});
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "Server.Cookie";
config.LoginPath = "/Home/Login";
config.LogoutPath = "/Home/Logout";
});
services.Configure<DataProtectionTokenProviderOptions>(opt =>
opt.TokenLifespan = TimeSpan.FromHours(12));
}
//This is the IdentityServer jwt bearer, I'm using this because my IdentityServer is also an API that needs authorization, which I use for retrieving my users data:
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", config =>
{
// Identity Server authority
config.Authority = "https://localhost:44300/";
config.Audience = "IdentityAPI";
});
This is the Identity Server configuration for accepted clients:
public class Configuration
{
public static IEnumerable<IdentityResource> GetIdentityResources() =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
public static IEnumerable<ApiScope> GetApiScopes() =>
new List<ApiScope> {
new ApiScope("IdentityAPI"),
new ApiScope("ClientGateway"),
};
public static IEnumerable<ApiResource> GetApiResources() =>
new List<ApiResource> {
new ApiResource("IdentityAPI")
{
Scopes = { "IdentityAPI" }
},
new ApiResource("ClientGateway")
{
Scopes = { "ClientGateway" }
},
};
public static IEnumerable<Client> GetClients() =>
new List<Client> {
// Client for my IdentityServer
new Client {
ClientId = "IdentityAPI",
ClientSecrets = { new Secret("secret_IdentityAPI".ToSha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = {
"IdentityAPI",
},
};
// My Client configuration, this client is trying to retrieve users data from the IdentityServer
new Client {
ClientId = "ClientGateway",
ClientSecrets = { new Secret("secret_ClientGateway".ToSha256()) },
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
RequirePkce = true,
// AllowedGrantTypes = GrantTypes.ClientCredentials,
// Necessary for authorization code flow type
// where to redirect to after login
RedirectUris = { "https://localhost:44400/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "https://localhost:44400/Home/Index" },
RequireConsent = false,
AllowedScopes = {
"IdentityAPI",
"ClientGateway",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
},
},
}
This is the client Startup:
public class Startup
{
private readonly IConfiguration Config;
private readonly IWebHostEnvironment Env;
public Startup(IConfiguration config, IWebHostEnvironment env)
{
Config = config;
Env = env;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(config =>
{
config.DefaultScheme = "Cookie";
config.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookie")
.AddOpenIdConnect("oidc", config =>
{
config.SignInScheme = "Cookie";
config.ClientId = "ClientGateway";
config.ClientSecret = "secret_ClientGateway";
config.SaveTokens = true;
config.Authority = "https://localhost:44300/";
config.ResponseType = "code";
config.SignedOutCallbackPath = "/Home/Index";
});
services.AddHttpClient();
services.AddControllersWithViews();
}
}
This is the Client Controller that is trying to authenticate and retrieve the data:
[Route("api/[controller]")]
[ApiController]
public class IdentityController : ControllerBase
{
private static readonly string IdentityAPIUrl = "https://localhost:44300";
private readonly IHttpClientFactory _httpClientFactory;
private readonly IHttpContextAccessor _httpContextAccessor;
public IdentityController(IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor)
{
_httpClientFactory = httpClientFactory;
_httpContextAccessor = httpContextAccessor;
}
public static async Task<HttpClient> NewClientGatewayHttpClient(IHttpClientFactory _httpClientFactory)
{
var serverClient = _httpClientFactory.CreateClient();
var discoveryDocument = await serverClient.GetDiscoveryDocumentAsync(IdentityAPIUrl);
var tokenResponse = await serverClient.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = discoveryDocument.TokenEndpoint,
ClientId = "ClientGateway",
ClientSecret = "secret_ClientGateway",
Scope = "IdentityAPI",
});
var apiClient = _httpClientFactory.CreateClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
return apiClient;
}
// I'm calling this function to retrieve users data from my IdentityServer
[HttpGet]
[Route("IDUsers")]
public async Task<List<ApplicationUser>> GetIDUsers()
{
HttpClient apiClient = ModisIDController.NewClientGatewayHttpClient(_httpClientFactory).Result;
// This response return a StatusCode: 200
var response = await apiClient.GetAsync(IdentityAPIUrl + "/api/get/users");
// In jsonResult I'm expecting my users data, but instead I'm receiving my view Login.cshtml as a string
var jsonResult = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<ApplicationUser>>(jsonResult);
}
This is the IdentityServer function that the Client Controller is trying to call:
[Authorize]
[Route("api/[controller]")]
[ApiController]
// Use this controller for Read API functions
public class GetController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IdentityServerDatabaseContext _context;
public GetController(UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager,
IdentityServerDatabaseContext context)
{
_userManager = userManager;
_roleManager = roleManager;
_context = context;
}
[HttpGet]
[Route("Users")]
public IActionResult GetUsers()
{
return Ok(_context.Users.ToList());
}
}
When ApiController tries to retrieve the data it gets correctly redirected to my Login view by the Identity Server, after login the user I get this output from my IdentityServer:
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryKeyEndpoint for /.well-known/openid-configuration/jwks
info: IdentityServer4.Hosting.IdentityServerMiddleware[0]
Invoking IdentityServer endpoint: IdentityServer4.Endpoints.TokenEndpoint for /connect/token
info: IdentityServer4.Validation.TokenRequestValidator[0]
Token request validation success, {
"ClientId": "ClientGateway",
"GrantType": "client_credentials",
"Scopes": "IdentityAPI",
"Raw": {
"grant_type": "client_credentials",
"scope": "IdentityAPI",
"client_id": "ClientGateway",
"client_secret": "***REDACTED***"
}
}
But the response that I retrieve in var content is HTML of the Login page and not the expected data. It seems like that the Identity Server is trying to redirect me again. I don't undestard why this happens because I'm using client credentials flow.

Identity.IsAuthenticated returning false after SignInAsync() in HTTPGET controllers

This application should automatically sign-in users using their Environment.Username, but I'm struggling to do it.
In the following HomeController, the variable "ThisGivesNegative" remains false even after the "HttpContext.SignInAsync" is invoked.
When I put this code in an HTTPPost action, the sign in is correct so I guess there has to be something with the configuration but after navigating in the web none of the StackOverflow posts worked.
Could any of you give me a hand? Thanks!
public class HomeController : Controller
{
private readonly IAppUserService _appUserService;
private readonly ILogger _logger;
private readonly ApplicationDbContext _context;
public HomeController(
ApplicationDbContext context,
IAppUserService appUserService,
ILoggerFactory loggerFactory
)
{
_context = context;
_appUserService = appUserService;
_logger = loggerFactory.CreateLogger<AccountController>();
}
public async Task<IActionResult> Index()
{
string WindowsUsername = Environment.UserName;
if (WindowsUsername != null)
{
List<AppRole> RolesForThisUser = new List<AppRole>();
RolesForThisUser = _context.AppUserAppRoles.Where(x => x.AppUser.ApexID == WindowsUsername).Select(x => x.AppRole).ToList();
var properties = new AuthenticationProperties
{
//AllowRefresh = false,
IsPersistent = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddHours(1)
};
List<Claim> MyClaims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, WindowsUsername),
};
foreach (AppRole ThisRole in RolesForThisUser)
{
MyClaims.Add(new Claim(ClaimTypes.Role, ThisRole.RoleName.ToString()));
}
var identity = new ClaimsIdentity(MyClaims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(principal, properties);
bool ThisGivesNegative = HttpContext.User.Identity.IsAuthenticated;
}
return View();
}
}
Here my ConfigureServices code:
public void ConfigureServices(IServiceCollection services)
{
services
.Configure<API_IP21_CurrentValues>(ConfigAppSettings.GetSection("API_IP21_CurrentValues"))
.Configure<API_IP21_HistoricValues>(ConfigAppSettings.GetSection("API_IP21_HistoricValues"))
.Configure<API_PPM_DailyValues>(ConfigAppSettings.GetSection("API_PPM_DailyValues"))
.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
})
.AddDbContextPool<ApplicationDbContext>(options =>
{
options.UseSqlServer(ConfigAppSettings.GetSection("ConnectionStrings").GetSection("DefaultConnection").Value);
})
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/Views/Home/Index.cshtml";
options.LogoutPath = "/Views/Home/Index.cshtml";
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
.AddTransient<IAppUserService, AppUserService>()
.AddTransient<IEquipmentRepository, EquipmentRepository>()
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
I found the issue, here some help for those in need!
Esentially, cookies are read before the Home Controller is fired so when the view is rendered, the program doesn't know this user has those cookies. We need to reload.
I solve this by adding the following code just before "return view()" in the Home Controller.
if (FirstPostback == false)
{
RedirectToAction("Index", "Home", new { FirstPostback = true});
}
return View(new LoginViewModel { ReturnUrl = returnUrl });