Changing Host-Only Value of the Identity Cookie - c#

It is a pretty simple Task, I want to change the Host-Only value of my Cookie Authentication Cookie. I know that you can change a lot of the Auth-Cookie Settings in this method services.ConfigureApplicationCookie(options =>{...}), but I couldn't find a property which would change the Host-Only value.
I already tried to find something online, but I couldn't find anything to it.
Note:
I am using ASP.Net Core 3 pre-release 9.

There's no option for this because it's not a configurable thing; it just is or is not. Cookies are domain-bound to begin with. By default, the cookie will be set on the exact host, i.e. foo.example.com, which then makes it "host only" by default. It will only ever be available to foo.example.com, no matter what.
You could set the cookie domain to a wildcard .example.com, in which case it would be available to all subdomains (example.com, www.example.com, foo.example.com, bar.example.com, etc.). That would no longer be "host only" in the sense that there's technically multiple hosts the cookie will apply to (though all for the same base domain). However, if you didn't want that, then you would simply not use this type of cookie domain; there's still no need for some sort of additional configuration option, i.e. if you want "host only" then just use the exact host as the cookie domain.

Related

OpenIdConnectProtocolValidationContext.Nonce was null

HI can someone please help imgetting below error when calling outlook rest api
IDX21323: RequireNonce is '[PII is hidden by default. Set the 'ShowPII' flag in IdentityModelEventSource.cs to true to reveal it.]'. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.
aka IDX21323 points towards losing the nonce cookie (set by the initial Challenge call). Inspect your initial SignIn call (or WebForms postback SignIn) and confirm that you have a OpenIdConnect.nonce cookie actually set (Chrome network tab).
If not, I suspect that you have the same issue we had, which is that the OWIN Middleware sets the cookie, but its content gets accidentally overwritten by some other cookie modifications of your legacy application.
This is very likely a bug of the OWIN middleware (see ASP.NET_SessionId + OWIN Cookies do not send to browser), as it handles cookies through its own OwinContext and Cookie representation implementation, which is not in sync with the standard HttpContext.
How to fix when you have the initial nonce cookie missing:
We avoided any cookie changes during the SignIn request -> therefore the OWIN middleware can read/write its cookies with no interference.
When setting the nonce cookie running on localhost (non-secure) in a Chromium based browser, it's blocked because of SameSite=none and it not being secure. The fix for this case is to change localhost to use SSL (use https on asp.net application running on localhost) and update the Azure AD redirect URL to match.
In a WebForms app I got the same error when I used my machine name in the project url, but used "localhost" as my login redirect url. When I set them both to localhost the problem went away.
If your tenant was created on or after October 22nd, 2019, it’s possible you are experiencing the new secure-by-default behavior and already have security defaults enabled in your tenant.
How to Fix :- goto your Azure AD account => properties => on tab Access management for Azure resources => enable this tab to Yes.

Asp.Net Identity with 2FA: List of Trusted Browsers

I'm working on a project with Asp.Net MVC 5 and Asp.Net Identity and I'm using two factor authentication. For the login I use:
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
which is the default code that came with the new project. However, I also need the ability for a user to "trust" or "remember" a browser, similar to how banks can indicate if this was the first time you have signed in from a particular browser/pc.
My question is around the RememberBrowser property on the sign in method and what .NET Identity does with this data. I want the list of saved browsers and the ability to revoke access to one/and-or all of them. Is that possible within the Identity framework? Also, can I tell if a browser has been "trusted" before by some type of lookup?
Edit:
Maybe it's a good idea to save the browser info in the database and check on login instead of the cookie? That way it can be shown as a list with the ability to delete it. What I'm looking for is what to save and how to integrate it with the Asp.Net Identity without having a security risk.
Edit 2
Here's an example from a website that is already using this:
Edit 3
Maybe this can be implemented as another step for authentication. So basically we'll have a 3 factor authentication:
First user logs in with user/pass
Then we'll check if the 2FA is enabled and get the code if necessary
We get the user's aser agent and IP and check the database if it's new. Then notify if necessary.
So I'm guessing an new cookie should be added to save browser's info. However, we should be able to invalidate this cookie along with the 2FA cookie.
RememberBrowser sets a cookie that allows the 2FA step to be skipped. There is no central way to track this though it would be easy enough to log, however the results may not be accurate because people can delete cookies manually. There's no way to invalidate it I believe but it doesn't really matter as you can invalidate their session and the user is will be required to login with their password again.
Not sure whether saving browser info adds value as browser info is gonna be same for different users (using same browser and version) unless you save requestor IP as well; and saving requestor IP has too many complications.
How about adding a custom claim to the token if user has set RememberBrowser and then do your logic based on this custom claim? For eg, set a custom claim your_claim_name and set a Guid.NewGuid() to it if RememberBrowser is true. Also save the username, this guid and status flag in database . When a request comes, check whether your custom claim is present, if yes query the table with the custom claim value and username to check whether the entry is still active.
You can either delete the entry or soft delete (set the status) the entry for an user so that when next request comes you can perform your required logic.

invalidate aspx authentication cookie

I have an asp.net web form. when a user authenticate, it create a Secured cookie called .aspxauth
uppon logout, I call these 2 methods
FormsAuthentication.SignOut();
Session.Abandon()
Problem is that we had penetration test and if I steal the cookie, logout and manually reinsert the cookie, I become loggued in again. So the .aspauth isn't invalidated server side.
I've googled it and I can't find the answer to that security breach.
Microsoft has acknowledged this issue here: https://support.microsoft.com/en-us/kb/900111
They offer several ideas for mitigating this vulnerability:
protect the application by using SSL
Enforce TTL and absolute expiration
Use HttpOnly cookies and forms authentication in ASP.NET 2.0
Use the Membership class in ASP.NET 2.0
Regarding the last one, I'll paste the contents from the site for convenience/preservation:
When you implement forms authentication in ASP.NET 2.0, you have the option of storing user information in a Membership provider. This option is a new feature that is introduced in ASP.NET 2.0. The MembershipUser object contains specific users.
If the user is logged in, you can store this information in the Comment property of the MembershipUser object. If you use this property, you can develop a mechanism to reduce cookie replay issues in ASP.NET 2.0. This mechanism would follow these steps:
You create an HttpModule that hooks the PostAuthenticateRequest event.
If a FormsIdentity object is in the HttpContext.User property, the FormsAuthenticationModule class recognizes the forms authentication ticket as valid.
Then, the custom HttpModule class obtains a reference to the MembershipUser instance that is associated with the authenticated user.
You examine the Comment property to determine whether the user is currently logged in.
Important: You must store information in the Comment property that indicates when the user explicitly signed out. Also, you must clear the information that is in the Comment property when the customer eventually signs in again.
If the user is not currently logged in as indicated by the Comment property, you must take the following actions:
Clear the cookie.
Set the Response.Status property to 401.
Make a call to the Response.End method that will implicitly redirect the request to the logon page.
By using this method, the forms authentication cookie will only be accepted if the user has not been explicitly signed out and the forms authentication ticket has not yet expired.
Read this article about Session fixation and how to get rid of it once and for all:
http://www.dotnetfunda.com/articles/show/1395/how-to-avoid-the-session-fixation-vulnerability-in-aspnet
This remains an issue in .NET Framework. Everyone seems to think Session.Abandon() is the answer, but the sad truth is that command does not invalidate the session on the server's side. Anyone with the right token value can still resurrect a dead session, until the session expires based on the Web.config settings (default = 20minutes).
A similar questioner posed this question a long time ago here:
Session Fixation in ASP.NET
Most of those links are dead, and Microsoft has no new news on the topic.
https://forums.asp.net/t/2154458.aspx?Preventing+Cookie+Replay+Attacks+MS+support+article+is+now+a+dead+link
Worse still, you're still vulnerable to this cookie replay attack even if you're implementing a completely stateless MVC application and don't use the Session object to store data between views. You can even turn off session state in the web.config settings and still replay cookies to gain access to a logged-out session.
The true solution is hack-y and described here, and you need to have session data enabled InProc to use it.
When the user logs in, set a boolean value in the session data, like Session["LoggedIn"] = true;, which is stored on the server side.
When the user logs out, set that value to false.
Check the session value on every request--an attacker trying to replay a session isn't going to be nice to you and come in through the Login page only. It's probably easiest to do this using a custom filter and registering it globally in the global.asax file (so you don't have to duplicate the code everywhere, or attribute every controller/method).
Even if the attacker has all the cookie values, they won't be able to re-use that same session ID, and the server will automatically delete it once it reaches the specified timeout.
if you are using the FormsAuthentication, you can use this code. By using this code you can destroy the created cookies by setting the Expire property of HttpCookie. It will help you:
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
// clear authentication cookie
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
httpCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(httpCookie);

DotNetOpenAuth ClaimedIdentifier changes? What should I store in database to identify users

There are quite a few questions like this and this which all claims that ClaimedIdentifier should be used to uniquely identify each user.
After successful login I am storing ClaimedIndentifier in database. Whenever a user logs in, I traverse through my records looking for the ClaimedIdentifier. However I noticed that ClaimedIdentifiers are changing. What should I store in database to identify my users. I am using Google account.
This is how I am retrieving storing it into database
OpenIdRelyingParty rp = new OpenIdRelyingParty();
IAuthenticationResponse r = rp.GetResponse();
UserController.addUser(new UserController.User(r.ClaimedIdentifier.ToString(), 0));
This isn't a DotNetOpenAuth unique issue. This is a Google behavior. Google's OpenID Provider issues what are called pairwise-unique identifiers. They will always be the same for a given user so long as your OpenID realm is constant.
If you log users in without explicitly supplying a realm to DotNetOpenAuth's OpenIdRelyingParty.CreateRequest method, DotNetOpenAuth simply uses the current web application root URL. This is a reasonable default, except that if your site is accessible in more than one way (e.g. http and https, or with and without the www. host name) than the default realm will vary based on the URL the user happened to use to reach your login page. And when the realm varies, so do Google's generated claimed identifier.
The fix then, is for you to pick one realm (preferably one with an https scheme if that's an option) and explicitly supply it to the CreateRequest method. You must also ensure that your return_to argument to the same method shares a common root with the realm you've chosen. For example, if the realm you choose is:
https://www.mysite.com/
Then you must ensure that your return_to is based on that. Something like:
https://www.mysite.com/login.aspx
If the user has browsed to http://mysite.com/login.aspx, that would be the default URL for the return_to, which would not match the realm you've chosen.
So altogether, it may look like this:
var request = relyingParty.CreateRequest(
"https://www.google.com/accounts/o8/id",
"https://www.mysite.com/",
new Uri("https://www.mysite.com/login.aspx"));
Note that your return_to does not need to be exactly the same with each request as the realm does. So you could have several login page URLs and each one specify its own URL as the return_to parameter. But all return_to URLs must be based on the realm URL.
With that change consistently applied to everywhere you allow users to log in, you should see consistent claimed identifiers from google. Unfortunately, the claimed identifiers you have already obtained using other realms won't match the ones you'll get after this fix. If you need to merge these user accounts, and if you have email addresses for the users you might try merging based on that. But be very wary of this step. It can only be safely done if you're sure the email addresses you have on file belong to those users. If you obtained those email addresses via OpenID when the users logged in, and double checked that it was from an OpenID Provider you trust and that verifies emails, then you're probably OK. Note that just hard-coding Google OP Identifier into CreateRequest does not guarantee that only Google users log in. To make sure of that, you'd have had to be checking that the IAuthenticationResponse.Provider.Uri property matches https://www.google.com/accounts/o8/ud when the positive assertion comes in.

Setting up OpenID Provider with SubDomains Identifiers using DotNetOpenAuth

I am currently trying to implement an OpenID Provider on my own domain name.
Thus, I would like the OpenID Identifier of a user to be user.example.com instead of the default example.com/user.aspx/user..
Is it possible for DotNetOpenAuthto do that? If so, roughly what changes do i need to make?
Yes, it's absolutely possible.
Configure your DNS and web site(s) and IIS to actually respond to user.example.com.
Place a default.aspx file such that it responds to requests for that domain, and make that URL an OpenID Claimed Identifier by placing the tags in it that you find in the user.aspx sample. Be sure in those tags that point to your OP Endpoint that it uses the absolute URL (which may be http://www.example.com/provider.ashx)
Modify your provider.ashx (or server.aspx, or MVC action, whatever you're using for your OP Endpoint) to be willing to send assertions for user.example.com
And you're done. I haven't gone into great detail on these steps because it's the same steps you take when you customize the URL of your claimed identifiers in any way -- special host name or not. The only really special step is #1: Configuring IIS. To accept any random host name requires special DNS configuration, but since it's just your own user name you can just hard-code your username into DNS.

Categories