Everytime I try to set the session cookies for a Chrome session, the cookies are not saved.
The session cookies work in Firefox though.
I think it either has something to do with allowing SameSite cookies or that secure cookies don't persist over HTTP.
Here is the code I use to add them:
services.AddDistributedMemoryCache();
services.AddSessions(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
options.Cookie.Domain = "localhost";
});
services.AddHttpContextAccessor();
I only use the code above for dev purposes.
Related
I am trying to set the session timeout to 30 mins in .NET 6.
I added the following code for it.
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession(options =>
options.IdleTimeout = TimeSpan.FromMinutes(30));
It is not working and the session is expiring in a few minutes.
When session is expired, the server will delete all session variables set on login and there is no way to see if it has been expired from client side (one of the many reasons on why I switched from Sessions to JsonWebTokens).
To use session, add following code in your Program.cs
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
// make the session cookie Essential
// so that session variable is not null
// check this StackOverflow answer: https://stackoverflow.com/a/64984796/19112855
options.Cookie.IsEssential = true;
});
app.UseSession(); // before app.UseAuthentication(); and after app.UseRouting();
To manually delete all session variables, call this in your controller HttpContext.Session.Clear();
Say I have a setup like this:
MVCApp1
MVCApp2
Identity Server
Therefore there are three projects inside my solution. Identity Server is now working for all of them. However, I am finding that I have to login to each one individually. Is that correct? i.e. if I login to MVCApp1, then does that mean I should also be implicitly logged in to MVCApp2?
Say I wanted to login to all three web apps, then would I have to browse to each web app and login or should I only have to do this once (I thought this is what single sign on was for).
Here is some code:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = identityUrl;
options.RequireHttpsMetadata = false;
options.ClientId = "mvc2";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("API1");
options.Scope.Add("API2");
options.Scope.Add("offline_access");
});
SSO is designed to handle this case, and no, you shouldn't need to login to each application individually.
If a user is not logged in, you should redirect them to the login page, when they can authenticate with the Identity Server. Once authenticated, the user should be able to access (without login) to both applications MVCApp1 and MVCApp2.
I would recommend storing your JWT's in a cookie, which can then be shared by your applications IF they live under the same domain. Then when any of your applications require authorization, get the JWT from the cookie in the request header and use that for authentications.
I am hosting my ASP.NET Core Razor application on CentOS using Apache as a reverse proxy. I am able to visit the website using my domain however the application is unable to set cookies in my browser no matter what I do.
This is the configuration for headers in my startup.cs:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.KnownProxies.Add(IPAddress.Parse("x.x.x.x"));
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});
app.UseAuthentication();
And this is virtual host configuration in apache httpd.conf file:
<VirtualHost *:80>
ServerName mysite.com
ServerAlias subdomain.mysite.com
ServerAdmin webmaster#mysite.com
ProxyPreserveHost On
ProxyPass / http://localhost:5001/ retry=0
ProxyPassReverse / http://localhost:5001/ retry=0
</VirtualHost>
I use this code for setting cookies and is not working:
public IActionResult OnPost()
{
Response.Cookies.Append("mycookie", "cookie-value");
return RedirectToPage("/Index");
}
I am not sure if I am doing everything correctly, perhaps I am going wrong somewhere but the fact is my application works fine on localhost and is able set cookies as well.
Ok I found the answer and I can't believe it was that simple. In my Startup.cs file I had set cookie policy:
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
Because during the development mode I was consistently using the application and in the initial stages I had given permission for setting cookie but soon after that I removed code need to set the permission true by user as it was the development stage.
I just changed above into this:
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
And now cookies are being set without any issue.
I am creating a sample application to just to understand how identity server 4 authentication works with Asp.net core 2. I have noticed some cookies are generated for different levels as it can be seen in the attached screenshot. My problems is why these cookies are generated?
Below statement, I take it from the Identity Server document. When identity server is configuring
IdentityServer internally calls both AddAuthentication and AddCookie with a custom scheme (via the constant IdentityServerConstants.DefaultCookieAuthenticationScheme),
Here why it calls AddCookies method on identity server itself?
Also when I configure Asp.net core web client to use Identity server authentication it also call AddCookie() method. When I try to comment it It will give me an error. I am bit of unclear what is happening here.
Identity Server Configurations
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddToDoUserStore()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
services.AddAuthentication("MyCookie")
.AddCookie("MyCookie", options =>
{
options.ExpireTimeSpan = new System.TimeSpan(0, 0, 15);
});
Web Client Configuration
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.Authority = "https://localhost:44377/";
options.RequireHttpsMetadata = true;
options.ClientId = "ToDoTaskManagmentClient";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("address");
options.Scope.Add("roles");
options.Scope.Add("usertodoapi");
options.Scope.Add("countries");
options.Scope.Add("subscriptionlevel");
options.Scope.Add("offline_access");
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.ClientSecret = "secret";
options.GetClaimsFromUserInfoEndpoint = true;
options.ClaimActions.Clear();
options.ClaimActions.MapJsonKey("given_name", "given_name");
options.ClaimActions.MapJsonKey("family_name", "family_name");
options.ClaimActions.MapJsonKey("role", "role");
options.ClaimActions.MapJsonKey("country", "country");
options.ClaimActions.MapJsonKey("subscriptionlevel", "subscriptionlevel");
options.Events = new OpenIdConnectEvents()
{
OnTokenValidated = e =>
{
var identity = e.Principal;
var subjectClaim = identity.Claims.FirstOrDefault(z => z.Type == "sub");
var expClaims = identity.Claims.FirstOrDefault(z => z.Type == "exp");
var newClaimsIdentity = new ClaimsIdentity(e.Scheme.Name);
newClaimsIdentity.AddClaim(subjectClaim);
newClaimsIdentity.AddClaim(expClaims);
e.Principal = new ClaimsPrincipal(newClaimsIdentity);
return Task.FromResult(0);
},
OnUserInformationReceived = e =>
{
e.User.Remove("address");
return Task.FromResult(0);
}
};
});
Your Identity Server application needs an authentication cookie (and session ID cookie) so that the front channel endpoints (authorize, consent, check_session_iframe and possibly others) know if the user is authenticated or not and the current state of the session. Without this it would have no idea who was calling it. IDS4 will automatically redirect to the login URL of the default scheme if it detects that the incoming request is not authenticated - you are then free to implement any authentication flow you like.
Your client applications may or may not need cookies depending on the architecture. A traditional server side WebForms or MVC-style app will need one but a pure JS client using a library like oidc-client-js will not and can talk to the back-end purely using the access token obtained from your identity server.
IdentityServer doesn't do any of this. All it does is handle the low-level authentication/authorization and return a claims principal. Your application that's using IdentityServer is the one that would set the cookie.
What you're doing here is essentially having the same app host both IdentityServer and a cookie auth-based frontend. The cookie portion is for the traditional login flow UI, so that the app can recognize whether the user is authenticated and redirect to a login form or to an account page or back to the originating app, if or when they are authenticated.
That piece could be completely spun-off into a totally different app, and then your IdentityServer app would no longer need the cookie auth config.
So I need to AddOpenIdConnect in order to declare my SignInScheme and Scopes.
Any idea how to do this in a WPF App? And where should this method be called?
services.AddOpenIdConnect(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; // cookie middle setup above
options.Authority = "http://localhost:5000"; // Auth Server
options.RequireHttpsMetadata = false; // only for development
options.ClientId = "native.code"; // client setup in Auth Server
options.ResponseType = "token";
options.Scope.Add("fiver_auth_api");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
});
It`s my first time working with Desktops Apps.
Check out this library and associated samples. Should give you everything you need:
https://github.com/IdentityModel/IdentityModel.OidcClient2
The recommended way to handle OIDC sign ins in a desktop app is to use the user's default browser and either a custom URL scheme or local HTTP listener to receive the response.