OpenIdConnectProtocolValidationContext.Nonce was null - c#

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.

Related

AWS Cognito built-in sign in redirection issue

I am trying to incorporate Cognito built-in sign in logic into our workflow.
Here is scenario I try put to work:
I need redirect to specific URI after successful signing in through Cognito built-in UI of the user, which has been created in the User Pool. But I do not understand how to do it.
I've created User Pool, app client, configured domain, provided callback url, created a user.
I configured "Allowed OAuth Flows" to useAuthorization code grant "Allowed OAuth Scopes" is set to openid
So far - so good.
Then I came up following URL to conjure up Cognito built-in UI:
https://<my-domain>.amazoncognito.com/authorize?response_type=code&client_id=<my-client-id>&redirect_uri=https://<my-domain>.amazoncognito.com/login?client_id=<my-client-id>
Upon executing it in a browser of my choice I am hitting Cognito built-in sign in page. But upon clicking "Sign in" button I've got an error: Required String parameter 'redirect_uri' is not present
Ok, I thought to myself, let's add redirect_uri attribute at the end of the aforementioned URL and path would be cleared to success, but such optimism has been short lived. I've got dreaded: "redirect_mismatch" error. I've tried to provide multiple callback urls, but with no success. redirect_mismatch error blocking my way.
And now I have no idea how to instruct Cognito to redirect to desired url. Any ideas are welcome.
You shouldn't set the 'redirect_uri' to Cognito's Login Endpoint. It makes no sense. The 'redirect_uri' is a parameter to tell Cognito where to take the user after login, which would be your application's url.
The 'redirect_uri' should exactly match one of the Callback URIs for the app client you configured for security reasons, otherwise you will get a' redirect_mismatch' error.
To access the login endpoint:
https://mydomain.auth.us-east-1.amazoncognito.com/login?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI
For the authorize endpoint:
https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI
The authorize endpoint firsts checks to see if you have a session cookie indicating that you're already logged in, and if you are, it automatically redirects you to the redirect_uri, otherwise it will take you to the login page via the Login Endpoint with the query strings provided to the authorize endpoint.

ASP.Net MVC - OWIN - Allowing Windows/Individual Authentication

I have an ASP.Net MVC 5 application which is currently using individual authentication (account/login.cshtml page with no authentication/anonymous access) and OWIN. Works fine.
As this is an intranet app I want to allow the users to log in under their windows account, another users windows account or an application account(admin, special user etc. - these accounts have no associated domain account).
For the first option I wanted to display their windows username on the login screen and they can simply click the "ok" button to login. To get the username I modified the Visual Studio Project properties to disable anonymous authentication and enable windows authentication. Also modified the web.config and set the authentication mode to Forms. This causes "HTTP Error 404.15 - Not Found". This appears to be due to an authentication loop caused by OWIN with the following suggestions to fix:
Ensure Login controller methods allow anonymous access (seems to be this way by default).
or Modify Startup.auth, comment out the LoginPath property.
or Modify the web.config, add the appSetting "owin:AutomaticAppStartup" with value "false".
I opted for the LoginPath fix and this appears to work (as does web.config change) in that there are no errors and the login page displays with the windows username (retrieved using System.Threading.Thread.Currentprinciple.Identity.Name).
The problem is now that once the user has logged in the OwinContext has no user ( HttpContext.GetOwinContext().GetUserManager()).
Ideally I don't need IIS or OWIN doing any authentication as it's done by the app - but I need the initial request (for the account/login page) to include the Authenticate headers so I can get the windows user.
Firstly I would like to understand what causes the "HTTP Error 404.15" and fix.
Secondly, how do I get OWIN to work with the authentication change - I just need it to persist the user for controller authentication.
This is just a guess but I believe the error is caused by the misconfiguration you've described: you have set the authentication mode to "Forms" but set the project to use Windows Authentication. It can be confusing but Windows Authentication is not Forms Authentication. When you are using Forms Authentication the user provides the credentials in the form that is submitted, validated (including all anti-forgery goodness) against the user store (I believe you are using ASP.NET Identity which would be a default for "Individual Authentication" setting) and if the validation is successful a cookie to set is included in the response. This cookie is then used to authenticate further requests.
As confirmed by Katana documentation, there is no built-in middleware for Windows Authentication - Microsoft simply assumes that IIS should be used for that. Which effectively prevents us from easily combining Katana OWIN middleware providers with Windows authentication. Now, easily is the key word: we still can "hack" our way around it.
Unfortunately, it still will be a hack: I have not found a way to make the authentication "transparent" (as in "a user opens the login form and can enter both the AD account credentials or the individual account credentials and everything just works"). You will need to maintain the individual account record for every Windows user (as you would do with any external OWIN middleware, such as Google or Facebook). You can automate the account creation and association though and make it look transparent. You can add an "external provider" button for your Windows authentication.
Authenticating the user would look like (in a separate "AD Authentication" controller):
bool userWindowsAuthentication = Request.LogonUserIdentity.IsAuthenticated;
if (userWindowsAuthentication) {
var userStoreDatabaseContext = new ApplicationDbContext();
var userStore = new UserStore<UserModel>(userStoreDatabaseContext);
var userStoreManager = new UserManager<UserModel>(userStore);
var userWindowsLoginCredentials = GetWindowsLoginInfo();
var existingInternalUser = userStoreManager.FindAsync(userWindowsLoginCredentials.UserName)
if (existingInternalUser) {
// It means that the user already exists in the internal provider and here you simply authenticate and redirect to destination
} else {
// It means that the user does not exist. You can automatically create the internal user record here and associate the Windows user with the internal record.
}
} else {
// It means that user is not signed in using Windows authentication, so you either want to redirect back to the login page or restrict access or do something else
}
As you can see, it's "dirty". Another hack: you can have additional layer (separate application or a virtual application) that accepts only Windows authentication. This app can be your log-in resource. If the user is authenticated with Windows AD you can redirect them to the correct login page. You can go even further and add their login info in the redirect request header but if you do so - the header must be encrypted to ensure that Windows authentication cannot be faked and the only thing that should be able to decrypt and validate it should be your main application. Again, dirty, but works.

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);

Browser occasionally losing HttpCookie for authentication after postback and redirect

This has been a nagging issue for some time, but very sporadic and difficult to isolate.
From time to time, browsers that have authenticated on a web application, have been open for a while, have logged in and out of the same web application multiple times, have multiple tabs, are pretty much any browser (Chrome, IE, Firefox, Safari), and seemingly at random, lose their ability to retain an AuthCookie after being set and followed by a redirect. Closing the browser and starting a new session resolves the issue, as does opening up a different browser and attempting to authenticate.
Our team uses forms authentication for all of our websites and web application. This is a pretty typical setup where a login form is displayed, the user enters credentials and a cookie is set on the click event of the postback, then a redirect occurs to the same page where the cookie is then referenced and used to complete authentication.
In this situation
FormsAuthentication.FormsCookieName = ".WebAuth"
Within Event:
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, Username, DateTime.Now, DateTime.Now.AddMinutes(SessionTimeout), false, Username);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
Response.Cookies.Add(faCookie);
Response.Redirect(Request.RawUrl, true);
After the redirect, on PreInit:
HttpCookie authCookie = Request.Cookies[cookieName];
At this point, the authCookie variable is typically not null, but in these isolated circumstances that I've outlined above, the cookie comes back null after the redirect.
This happens very randomly, sometimes weeks before affecting one of our developers. As I said, restarting the browser resolves the issue.
Today I had it happen on our dev server while using Chrome. I had logged into the application, allowed the application to session timeout, and then attempted to login again. The attempted login then failed to set the cookie. I remotely attached Visual Studio to the process on the server to begin debugging. The entire time I could step through my code, even deploy new code versions to the server with updates, restart the app, restart IIS on the server, attach and reattach to the project, and the issue persisted in Chrome. In Firefox, I was able to authenticate without issue.
From Chrome, the login would validate, attempt to set a Response Cookie as outlined above. Prior to redirect, I could see the properly set Response Cookie, as well as its counterpart in the Request Cookies. However, on each redirect after a seemingly successful login, the Response and Request Cookie are gone.
I enabled Trace on the application to view the cookie collection:
There is a .WebAuth in the Request Cookies Collection, as well as ASP.NET_SessionId and several ASPSESSIONIDxxxxxxxx, but when the page loads, only the ASP.NET_SessionId and ASPSESSIONIDxxxxxxxx cookies are available in the Request.Cookies scope, no sign of the .WebAuth. However, in the page's Trace information after render, there multiple .WebAuth cookies listed, it is just that the page seems to have no access to them.
Primarily, on a working version after authentication there is both a .WebAuth Response and Request Cookie in the page's Trace info. But on a non functioning browser window, the Response Cookie is absent.
Has anyone else had any experience with this? It is such a nagging issue, and so sporadic, but I would love to be able to resolve it. My concern is that it may be affecting users and we would have no knowledge since the description of the issue is so convoluted.
Based on your scenario you may be running into browser's restrictions on number of cookies per domain/total. The limits are relatively high, but exist (spec: http://www.ietf.org/rfc/rfc2109.txt, section 6.3 , some recent information - http://www.nczonline.net/blog/2008/05/17/browser-cookie-restrictions/)
If you get it happening again try to look at actual server responses (i.e. using Fiddler) to see if cookies are send to the browser. Check what cookies are set for the domain and current page (depending on browser there are different ways of doing it, in all browsers you can see some cookies by running following in address bar javascript:alert(document.cookie) )
This is a non-persistent cookie issue. Session simply times out.
Try changing false to true in this line:
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, Username, DateTime.Now, DateTime.Now.AddMinutes(SessionTimeout), true, Username);
Also add
faCookie.Expires = DateTime.Now.AddMinutes(SessionTimeout);
I have fall in similar situation, things was certain as you described. But, later the reason have been found.
ASP.NET and IIS understood MyApplication and myapplication as one equal, but browsers undertood them as different. So, when we set auth cookies for /MyApplication, they were not sent to the server, when we go to /myapplication.
The fix is next:
protected void Application_BeginRequest(object sender, EventArgs e)
{
string url = HttpContext.Current.Request.Url.PathAndQuery;
string application = HttpContext.Current.Request.ApplicationPath;
if (!url.StartsWith(application))
{
HttpContext.Current.Response.Redirect(application + url.Substring(application.Length));
Response.End();
return;
}
}

FormsAuthentication.FormsCookiePath

Q1
I’ve read that when setting the timeout of an authentication cookie, we should keep in mind that the longer the cookie persists, the greater the chance of a cookie being stolen and misused.
A) But assuming we secure our application against replay attacks by enabling SSL for the entire application, and since forms authentication module also encrypts authentication data in authentication cookie, then I would think there is no chance of this cookie being misused and thus cookies being persisted for longer periods of time should not present any security risks?!
Q2
FormsAuthentication.FormsCookiePath specifies where authentication cookie is stored. Default value is ‘/’.
A) Assuming default value ’/’ is used, where is cookie saved then?
B) Is this option only used for persistent cookies?
thanx
2A The cookie path is the path on the server the cookie relates to, not the path where the cookie is store.
From http://www.quirksmode.org/js/cookies.html
The path gives you the chance to specify a directory where the cookie is active. So if you want the cookie to be only sent to pages in the directory cgi-bin, set the path to /cgi-bin. Usually the path is set to /, which means the cookie is valid throughout the entire domain.
This script does so, so the cookies you can set on this page will be sent to any page in the www.quirksmode.org domain (though only this page has a script that searches for the cookies and does something with them).
You are using ASP.Net. Also see the "CookieLess" Session and Authenication options e.g.
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.formscookiepath.aspx If you are worried about cookies. This uses a URL session ID instead to track your session.
You can also use a SQL Server to track session state or a State server.
e.g.
<sessionState mode="SQLServer" sqlConnectionString="SQLSessionDB" cookieless="false" timeout="65" cookieName="MSESSID"/>
1A. SSL encrypts transport. Hence your cookies will be less likely to be stolen on route to the client or back. That doesn't mean a malicious program on the client computer can't steal it. This is very unlikely though.

Categories