I have dockerized .net core 3.1 app and ngxin running on linode server.
App uses jwt tokens and redirects user (302) to controller Auth/Login, when i access my subdomain app.e-this.net nginx detects hostname and serves correct container but then app redirects to login (when i logout or delete cookies) and it changes host to my linode IP address, here is a log snippet:
nginx_logs
nginx patial conf looks like this
server {
listen 80;
server_name app.e-this.net www.app.e-this.net;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
#proxy_set_header Host $host;
#proxy_set_header Host $proxy_host; #DEFAULT
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-Forwarded-Host $server_name;
#proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
#proxy_set_header X-Forwarded-Path $request_uri;
proxy_cache_bypass $http_upgrade;
#proxy_cookie_domain origin rewrite;
proxy_redirect off;
}
}
my code in startup.cs is like this:
public void ConfigureServices(IServiceCollection services)
{
//Reading parameters from appsettings.json file
byte[] key = Encoding.ASCII.GetBytes(_config["AppSettings:Secret"]);
string domain = _config["AppSettings:Domain"];
//Creates contex for database so it can be used in application
//Sql, MySql, Postgres, Sqlite have different package dependencies (eg. Microsoft.EntityFrameworkCore.Sqlite in "Manage NuGet package")
services.AddDbContext<DataContext>(options => options.UseSqlite(_config.GetConnectionString("SQLiteDB")));
//Dependency injection of repositories and classes to be used in application (eg. controllers)
services.AddScoped<IUserRepository, SqliteUserRepository>();
services.AddScoped<IAuthService, AuthService>();
//Makes AppSettings available in project with IOptions<AppSettings> parameter
services.Configure<AppSettings>(_config.GetSection("AppSettings"));
//Adding session to be used with JWT authentiacation
//services.AddSession();
services.AddSession(options =>
{
//These options are optional
options.IdleTimeout = TimeSpan.FromMinutes(60); //Session will be terminated if user is idle for 1 hour (user needs to login again)
options.Cookie.HttpOnly = true; //Indicates whether a cookie is accessible by client-side script
options.Cookie.IsEssential = true; //Indicates if this cookie is essential for the application to function correctly. If true then consent policy checks may be bypassed.
});
//Adding mvc service
services.AddMvc(options => options.EnableEndpointRouting = false);
//Adding JWT Authentication
//This was copied from online example TOSEARCH: research jwtbearer options
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(token =>
{
token.RequireHttpsMetadata = false;
token.SaveToken = true;
token.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = true,
ValidIssuer = domain,
ValidateAudience = true,
ValidAudience = domain,
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
services
.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//Checking environment type development/production...
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
else
app.UseExceptionHandler("/Home/Error");
//Redirection to login when jwt session expires or when user gets unauthorized response
app.UseStatusCodePages(context =>
{
if (context.HttpContext.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
context.HttpContext.Response.Redirect("/Auth/Login");
return Task.CompletedTask;
});
//app.UseHttpsRedirection();
app.UseDefaultFiles();
//Can use static files (js, css..) in wwwwrooot folder
app.UseStaticFiles();
//Add User session
app.UseSession();
//Add JWToken to all incoming HTTP Request Header
app.Use(async (context, next) =>
{
var JWToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(JWToken))
{
context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
}
await next();
});
//Add JWToken Authentication service
app.UseAuthentication();
app.UseAuthorization();
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}