We have an ASP.NET Core application which has the default authentication system and is hosted on Azure.
Recently, we created a new AppService and routed the users to that service while maintaining connection to the same database.
However, when users use the new server, we get continuous crashes with the following error:
The key {xxx-xxx-xxx-xxx} was not found in the key ring.
of type
System.Security.Cryptography.CryptographicException
and method
Microsoft.AspNetCore.Antiforgery.Internal.DefaultAntiforgeryTokenSerializer.Deserialize(String
serializedToken)
Our understanding is that the server is trying to decrypt the token but since it was received from a different server, our server just crashes.
We would so much appreciate if you can suggest a way to solve this issue temporarily until we change the DataProtection provider.
We want a way that wouldn't let our server crash.
Thank you so much
Update: I'm surprised now that this error happens in: POST Account/Login and POST Account/Register while these methods do not require authorization, however these methods are decorated with:
[ValidateAntiForgeryToken]
Both Get Account/Login and Post Account/Login happen on the same server.
Make sure you have machine key same across the farm. You should set it at the application level, meaning, different apps have different keys but the same app has the same key on all server of the farm.
The machine mey is responsible for encrypting some internals of selected features of the engine, including the antiforgery tokens. A different key on different servers causes the exact issue you describe.
https://blogs.msdn.microsoft.com/amb/2012/07/31/easiest-way-to-generate-machinekey/
https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.100).aspx
In my case.
This error happened as I was using two or more instances for the identity server.
So,
Login goes fine but checking the token cause errors.
As the login was done by an instance and checking was done using other instance.
The easiest way to solve this is to make sure that your identity server or API is using only one instance.
Related
We have as SAAS application that runs for multiple customers at the same time. All customers use the same application, and by checking the URL used to access the application, users are redirected to the correct data for the organization.
Underwater, every organization has their own database. To make sure that users don't accidentally end up in the wrong database, we want to impersonate the request being executed to a user that only has access to the correct database. We used to do this and this worked beautifully on IIS in classic mode.
However, in integrated pipeline mode, we run into a threading issue. We use an HTTP module to impersonate the request to the correct user in the "PreRequestHandlerExecute" event. The problem that (apparently) there is no guarantee that this method is executed in the same thread as the handler that actually processes the request. This causes the impersonation to sometimes not work because the thread processing the request is not impersonated.
I've created a test project in GitHub (https://github.com/PaulVrugt/ImpersonationExample/tree/master/ImpersonationTest) demonstrating the issue (apologies for the vb.net, but you'll get the idea). When you run the example connected to an IIS using integrated pipeline mode, you'll see that sometimes the impersonated user is not used, and each time it is not used, the managedthreadid of the thread processing the request is different from the thread used in the httpmodule.
Now that I understand why it "sometimes" doesn't work, I begin to suspect I'm going about this all wrong. Is there a way to achieve what I am trying to do?
We've already tried to impersonate in the prerequesthandler in the global.asax, but that results in the same issue.
I have been puzzling over this and can't think of an good way of doing this. I am developing a website that would require the user to log in to use the system. I'm thinking of using ASP.NET MVC 4's built in authentication. That isn't much of a problem.
The user would be able to use tools on another server (our server would authenticate him and tell the other website, he is good to go, these messages are passed via HTTPS using XML). The other server, require us to create an authentication token for the user to use when the messages are passed between us.
We need to keep the token in our database to authenticate for every request/response with the other server. Which means that this "token table" knows nothing about the forms authentication time out on our server and vice-verse.
Now the problem, let's say the user uses the other server's tools. He would be on the other server for a long time, this would cause the authentication on our server to log him out, since there doesn't seem to be any perceived activity. The other server will not log him out since we are manually maintaining the token. This would be a troublesome for the user, because now, if he needs to use our service, he'll have to log in again even though he was "online" all the time.
Is there a way to "sync" the 2 authentications? At first I was thinking of getting our server to look up the "token table" (instead of using the built in authentication) so that if the last activity was x ago, the user will be required to log in again, this would solve the untimely logging out from our server. But I'm worried about the security implications.
What would be the best way to do this?
Thank you.
Desmond
If I've understood you correctly you are using Forms Authentication in an MVC4 application to authenticate users, but users will also use another web service located on a different server and so while they are using this other server you don't want the MVC4 application's authentication (for the user) to timeout. Is that correct?
If so, one idea that comes to mind is that your MVC4 application could have an API to the external world that would take in a username and use RenewTicketIfOld() to refresh the timer associated with the ticket. You could do this via the other web server making an HTTP request or by simply placing some AJAX on the page to call the API on every page.
There are, of course, security concerns with this method that you would need to consider. Without knowing more about your situation I'm not sure what solution would be best.
I'm very new to ASP.NET and I've been struggling trying to get the username of the client sending requests to a web service script on the server side.
After searching online I found two properties that supposedly gives the server page access to the client username;
User.Identity.Name
and then I got another piece of code from an ex-senior colleague who left before figuring this problem out, his function used UserPrincipal.Current.DisplayName
and for both of these I'm getting a blank string.
I've searched for what my problem could be and I'm suspecting it's because I don't authenticate the user on the server side somehow.
I just accessed those two properties/variables directly (UserPrincipal.Current.DisplayName and User.Identity.Name)
can anyone help shed some light on this issue please? I haven't a clue what I'm doing wrong/ not doing.
Your suspicions are correct; you have to explicitly authenticate the user via a built-in .NET mechanism such as Forms Authentication or Windows Authentication for User.Identity to be populated by the framework.
You didn't specify from where the requests are coming (web, windows app, windows service, etc), but this article provides nice overview of getting Forms Authentication set up with asmx.
I'm getting a 401 (access denied) calling a method on an internal web service. I'm calling it from an ASP.NET page on our company intranet. I've checked all the configuration and it should be using integrated security with an account that has access to that service, but I'm trying to figure out how to confirm which account it's connecting under. Unfortunately I can't debug the code on the production network. In our dev environment everything is working fine. I know there has to be a difference in the settings, but I'm at a loss with where to start. Any recommendations?
Have you looked in the IIS logs?
I would also recommend looking in the Security event log on the server for authentication failures. You should find a footprint of the failed authorisation attempt here. Be warned though - it is not unusual to get 10s of security events a second, so ideally you need to be able to access the event log as the requests are failing.
If you do not specify which credentials to use in your ASP.NET page when you instantiate the web service then I believe it defaults to NT_Authority\Anonymous.
If you're using System.Net.CredentialCache then your web service needs to be in a trusted domain, accessed over HTTPS and using either NTLM, Kerberos or Digest Auth otherwise it does not pass the credentials from the cache.
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultcredentials.aspx
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultnetworkcredentials.aspx
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultcredentials.aspx
Perhaps the production server uses a different user for its application pool than your dev environment? I once spent a day figuring that one out. Another option would be the (lack of) impersonation in the web.config
I am in the process of writing an application that will need multiple forms of authentication.
The application will need to support authentication to Active Directory, but be able to fail back to a SQL Membership Provider if the user is not in Active Directory. We can handle the failing to the SQL Provider in code based on the username provided because the username will be a different format than the Active Directory username.
Is this even possible? What I mean is, can I use membership and use both ActiveDirectoryMembershipProvider and SqlMembershipProvider together or will I have to roll my own?
Another additional added complexity is that I would like to automatically authenticate my internal users based of Windows Authentication back to AD, but use Forms Authentication for users not on our internal network, or users that are using the SQL Provider.
These will most likely be separate servers, one internal, and the other external so I have a lot of planning to do to figure out the data replication, and how I will authenticate the AD users if they hit the outside server etc.
I am wondering what thoughts are out there as I start down this road. Is what I am wanting to do even possible without me rolling my own, or is there a way to mesh these together?
Thanks for the reply.
The reason I asked originally was because I was able to get this specific senerio working about 7 years ago using IIS to authenticate and then passing back the credentials to a Lotus Domino Server Web App. If the user was not authenticated via the Windows Authentication/ISS then Domino would handle the authentication. This was what I was looking to do here, but really couldn't think of a way to make it work in IIS.
As for the rest of your reply, I think you are on to the way that I will need to take. I have thought this through and tossed it around in my head a lot. The application will be somewhat different on the two servers anyway since there is going to be limited access to the data on the external server anyway. The fact that so much is going to be different already I may just treat these as two applications, thus negating the need to use two types of authentication in the same application anyway.
I am playing around with the idea already of writing my own authentication/login window for the external server, and if the user trys to log in with their AD credentials on the external server I will be able to detect that and redirect them to the internal server. If they are not on the local network or VPN'd in they will simply not get access. This part still has some thought process to go though so I am not sure.
As an additional thought - is there a way to pull just enough of AD into a SQL database to allow me to authenticate users to the SQL database from the external server using their AD credentials, without creating any security issues? I hope I am clearly typing what I am thinking....
Thanks again!
Tim
This is the way I've handled a similar situation based on this info:
Configured the application to use Forms authentication.
Set the LoginUrl to a page called WinLogin.aspx.
In WinLogin.aspx, use Request.ServerVariables["LOGON_USER"] to get the username then call FormsAuthentication.RedirectFromLoginPage( authorizedUserName, false ) to log them in. I guess you can manually check Active Directory as this point as well.
Create an html page that redirects to a page called Login.aspx
Login.aspx is your standard username/password login.
In IIS, Enable Integrated Authentication and Anonymous on the entire site, but deny anonymous access to WinLogin.aspx.
In IIS, set your 401 errors to the page created in step 3.
What basically happens is that when an unauthenicated user hits the site, they're redirected to WinLogin.aspx. Since anonymous is turned off, integrated security makes a check. If that passes, your custom code in WinLogin can run. If the integrated security check fails, a 401 error occurs. Your custom 401 page redirects to Login.aspx where the user can log in using their username and password with the SQL provider.
As far as I know, Web Applications are configured to use either Windows Authentication or Forms Authentication, but not both. Therefore, I do not believe it is possible to automatically authenticate internal users while requiring others to enter a username / password.
You could authenticate to Active Directory or a SQL user store via Forms authentication by using a custom provider. However, the AD users would still need to enter their username and password. Although I've never combined these two methods, I have used Forms authentication to authenticate against both sources at one time or another.
With that said, I think you may want to consider reducing the "flexibility" of your system. If you have an external facing server and an internal facing server, you could simply change the provider configuration on each copy of the application to go against a different source. Then, you could configure the internal one to use Windows (automatic) authentication and the external one to use Forms authentication.
IMHO, I believe that internal users should not be using the external server to access the application. If they are, they should have a user account stored in SQL, completely separated from their AD account. Basically, when someone accesses the application externally, they are acting as an external user, irregardless of their physical location.
Well, it is possible to use ActiveDirectoryMembershipProvider and SqlMembershipProvider, but this requires you design your log on page with your own code instead of the Login controls.
About the mix authentication (Windows and Forms), as far as I know only IIS 7 makes it easy and clean. See this post for details,
http://mvolo.com/blogs/serverside/archive/2008/02/11/IIS-7.0-Two_2D00_Level-Authentication-with-Forms-Authentication-and-Windows-Authentication.aspx