Microsoft.IdentityModel: Key not valid for use in specified state - cryptography

I have a claims aware web application using Windows Identity Foundation that has been working well, except on one server. I am seeing the error message shown below in the event log.
Exception information:
Exception type: CryptographicException
Exception message: Key not valid for use in specified state.
at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
at Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded)
This application is using a very standard implemenation of WIF with ADFS v2. It is not using RsaEncryptionCookieTransform. I am looking for any suggestions on how to diagnose this. Things I have tried so far:
The Application Pool is using the ASP.NET v4.0 identity which has the "Load User Profile" setting set to true.
I deleted the C:\Users\ASP.NET v4.0\AppData folder and saw this was successfully recreated.
I checked permissions on certificate private keys, which were good. I also tried disabling token encryption which did not make any difference.
Any advice would be appreciated.

This is usually caused by the application not being able to decrypt the authentication token cookie. Make sure that the identity that owns the App Pool has sufficient permission to access your certificate store. Try changing the Identity to NetworkService and see if that helps.
You should also clear your browser's cookies to make sure you don't have cookies from a different application cached.

The issue is 100% reproducible:
Indeed, after application being re-deployed, AND old authentication cookie is left on the client machine (client did not sign out) -this error appears to the client on any following request.
To fix this error client either has to delete the cookies and/or sign-in then sign-out from STS. Once all done - the error goes away and everything is fine until next upgrade....
After some research, I think this is a bug in the SessionAuthenticationModule that needs to be fixed. If you carefully look at the stack trace above, there is an interesting method called TryReadSessionTokenFromCookie, which sets expectation that authentication module will "try" to read the token from cookie, and will return false if this fails -here is the code (thanks to Resharper!):
public bool TryReadSessionTokenFromCookie(out SessionSecurityToken sessionToken)
{
byte[] sessionCookie = this.CookieHandler.Read();
if (sessionCookie == null)
{
sessionToken = null;
return false;
}
sessionToken = this.ReadSessionTokenFromCookie(sessionCookie);
if (DiagnosticUtil.TraceUtil.ShouldTrace(TraceEventType.Verbose))
{
DiagnosticUtil.TraceUtil.Trace(TraceEventType.Verbose, TraceCode.Diagnostics, SR.GetString("TraceValidateToken", new object[0]), new TokenTraceRecord(sessionToken), null);
}
return true;
}
Obviously, the code fails in this method with unhandled error and developer is left without any option to handle the error in more or less reasonable way. (...Or at least I could not find any, since this HTTP module does not pass this error onto HttpApplication object for handling, and throws it in the user's face.)
So, I think there are two bugs:
1) Security token handler needs to be more specific on the reasoning of thrown ID1073 (server side decryption error or wrong (old) cookie error)
2) There has to be a way for a developer to handle this error and sign-out the user, if it occurs. I'll take ANY help on this one...
Can anyone PLEASE create a sample code, showing how to intercept this exception so user can be automatically signed-out when this error occurs? Again, Application.Error event does not seem to get fired from this module -not sure what else can be done to handle it, other than writing my own SessionAuthenticationModule.
ANY HELP IS HIGHLY APPRECIATED!!!
Thanks!
Alex

I resolve my case because i have the same cookie name "FedAuth" for two applications (this is the name by default). Just put a different name and it's resolve :
<system.identityModel.services>
<federationConfiguration>
<cookieHandler name="ACookieName" />
</federationConfiguration>

The following worked for me:
You need to add section to system.identityModel/identityConfiguration
Reference:
SessionSecurityTokenHandler trying to decrypt SessionSecurityToken in RSA-encrypted cookie using DPAPI; why?
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<audienceUris>
<add value="yoursite.com" />
</audienceUris>
<issuerNameRegistry type="Thinktecture.IdentityModel.Tokens.MetadataBasedIssuerNameRegistry, Thinktecture.IdentityModel">
<trustedIssuerMetadata issuerName="urn:federation:company:stage" metadataAddress="https://federation-sts-stage.company.com/FederationMetadata/2007-06/FederationMetadata.xml"></trustedIssuerMetadata>
</issuerNameRegistry>
<certificateValidation certificateValidationMode="None" />
<securityTokenHandlers>
<add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,
System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler,
System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</securityTokenHandlers>
</identityConfiguration>
</system.identityModel>

Deleting the FedAuth cookies might work. When the exception occurs, try this in the Application_Error method of the Global.asax file:
Microsoft.IdentityModel.Web.FederatedAuthentication.SessionAuthenticationModule.SignOut();

This error doesn't seem to be caught by http application.
Please check out http://social.technet.microsoft.com/wiki/contents/articles/1898.aspx#Q1 instead.

This issue is because of insufficient permission.
The app pool should have ApplicationPoolIdentity Identity to make it work.
Goto your apppool -> Advanced Settings -> Build-in accounts to change the settings

Related

Handling exceptions before startup

I have an application that can throw an InvalidOperationException during the startup process before the host has been created. What I would like to do is capture this error, and handle it by displaying a static, custom error page (i.e. ErrorPage.html)
Is this possible? Everywhere I seem to look makes it seem as though this is an impossible task and that the default 500.30 - ASP.NET Core app failed to start is the only page that will appear in a situation where the host fails to establish by the time the exception is thrown.
One option to achieve a custom error page on host errors generating 500 responses would be to use some gateway or proxy in front of your app. The idea would be to handle certain responses by showing some error content from the gateway.
Options would include custom error pages in Azure Application Gateway or a middleware handler if using a YARP proxy instance.
For IIS use web.config and add a section inside element <system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<error statusCode="500" subStatusCode="30" path="ErrorPage.html" responseMode="File" />
</httpErrors>
Check docs for more information

Exception AADSTS50011 is thrown when using azure ad authentication

I have been developing a C# MVC application. Using azure ad to authenticate the users.
But when deployed on IIS, it can only works when accessing the website by "https://localhost". But an error is thrown when accessing the website by "https://machinename".
AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application: '4e392b7a-####-####-####-####'.
2 urls are configured on the azure ad authentication:
https://machinename/
https://localhost/
The configuration in the file web.config:
<add key="ClientId" value="4e392b7a-####-####-####-############" />
<add key="Tenant" value="72f988bf-####-####-####-############" />
<add key="Authority" value="https://login.microsoftonline.com/{0}/v2.0" />
<add key="RedirectUri" value="https://machinename/" />
<add key="PostLogoutRedirectUri" value="https://machinename/KeepAlive/SignOut" />
According to your error message, you must ensure that the reply URL in the Azure portal is exactly the same as the reply URL configured by the application.
I have answered similar questions before, There is a general solution to the problem of not match:
When you visit the application url , you will be redirected to the login page. Decode the authorization request URL, you will find redirect_uri, copy the value of redirect_uri and paste it into the azure portal, and try again.
Update:
Thanks for the solution provided by #Tom. For this error, you also need to add the port :
https://machinename/{port}
https://localhost/{port}

401 Error, Mule while Username/Password are Correct

I am trying to use postman to call an API that I have deployed with Mule. I have downloaded this API from a trusted source (Collibra) and thus expect it to be in working condition.
The API Request:
http://localhost:8081/connect/dgc/export/asset?filter=name%20STARTS_WITH%20E
Here is the Basic Auth setup in one of the xml files.
<mule-ss:security-manager name ="authenticationManager" doc:name="Spring Security Provider">
<mule-ss:delegate-security-provider
name="memory-provider" delegate-ref="authenticationManager-common" />
</mule-ss:security-manager>
<spring:beans>
<ss:authentication-manager alias="authenticationManager-common">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="${service.user}" password="${service.password}"
authorities="ROLE_ADMIN" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
And here is the setting of the username/password in a properties file.
service.user=user
service.password=password
The following error appears when I make a postman GET request with the correct credentials.
Failed to connect/reconnect: Work Descriptor. Root Exception was: Unexpected response with status code: 401 was returned. Message was: {"statusCode":401,"titleMessage":"Not authorized","userMessage":"The user name or password is wrong. Try again."}
And here is the error that appears if I use the incorrect credentials.
Root Exception stack trace:
org.springframework.security.authentication.BadCredentialsException: Bad credentials
What could be going wrong to have the error appear when I am passing the correct credentials through the Basic Auth? I have double-checked the string with an online header generator and it is indeed correct.
It is difficult to troubleshoot without understanding the API implementation, but given the error with incorrect credentials seems to come from the Spring Security Manager and with the correct credentials it looks to be connecting to something else, it is possible that the API is calling some backend system or API and failing to authenticate to it.

adfs windows authentication

I have tried searching for this and can't find anything.
I want users to have a true SSO experience. Meaning they login to their computer and when they hit a web app that we have set up trust with in ADFS they are taken straight to that website. Right now no matter what they are taken to the ADFS forms login page. We only want the forms login page to appear if the user is not already connected to the network. Otherwise, ADFS should recoginize that the user is on the network and use the windows authentication.
What do I have to change in ADFS to make this happen?
In ADFS web.config, what order do you have for:
<localAuthenticationTypes>
<add name="Integrated" page="auth/integrated/" />
<add name="Forms" page="FormsSignIn.aspx" />
<add name="TlsClient" page="auth/sslclient/" />
<add name="Basic" page="auth/basic/" />
</localAuthenticationTypes>
Is Forms on top?
Are these users on the internet or intranet?
Do you use an ADFS proxy?
One option is to add a handler for the RedirectingToIdentityProvider event by placing the code just below this paragraph in your global.asax. This gives you a chance to jump in before the browser is redirected to ADFS and modify what the request (query string) looks like. You can do this to specify authentication types, or home realms (if you have multiple federations and want to skip HRD), and probably a lot of other stuff I don't know about.
void Application_Init()
{
FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider += new EventHandler<RedirectingToIdentityProviderEventArgs>(WSFederationAuthentication_RedirectingToIdentityProvider);
}
Then you would add code to your handler that might look something like this:
void WSFederationAuthentication_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e)
{
WSFederationAuthenticationModule instance = FederatedAuthentication.WSFederationAuthenticationModule;
SignInRequestMessage request = instance.CreateSignInRequest(Guid.NewGuid().ToString(), instance.Realm, true);
request.AuthenticationType = "urn:federation:authentication:windows";
Response.Redirect(request.WriteQueryString());
}
When you set the request.AuthenticationType to that value, you're telling ADFS that you want to do windows (integrated) authentication. This was all that was required for me to get it to work. I didn't have to bother with switching the order of the authentication types in the web.config as nzpcmad suggested.
Also, for this to work, IIS and your web browser are working some magic outside of AD FS and your relying party, so in IE your users have to go to tools > Internet Options > Security and add the site to your Local Intranet sites. There's probably a way to push this out with group policies or something, but that's another question. Anyway, now that I think of it, this may be the only step you're missing.

SerializationException on 'CustomIdentity' when user is denied in ASP.NET

I try to implement ASP.NET Authentication and Authorization on top of our existing database.
We have a website calling a webservice to fetch its data. To use the webservice, i need to provide the username and password.
Knowing that, I decided to implement IIdentity and IPrincipal to store the encrypted password and be able to provide it when performing webservice calls.
In the future, we might want to use more of the built-in security of asp.net, so I implement membership and role provider and override just what I need (ValidateUser and GetRoles)
Though, after validating the user thanks to the membership provider implementation I am still setting my own CustomIdentity to the Context.User to be able to retrieve its password when needed.
It's working perfectly as long as the user is allowed to visit the page. but when the user is denied, instead of throwing an AccessDeniedException, the framework throws a Serialization exception on my CustomIdentity.
I found a perfectly similar behaviour with more details described on this link , but no answer have been posted.
My exception is exactly the same as on the link above
Type is not resolved for member'CW.CustomAuthentication.CWIdentity,CW.CustomAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.Serialization.SerializationException: Type is not resolved for member 'CW.CustomAuthentication.CWIdentity,CW.CustomAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[SerializationException: Type is not resolved for member 'CW.CustomAuthentication.CWIdentity,CW.CustomAuthentication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.]
Microsoft.VisualStudio.WebHost.Connection.get_RemoteIP() +0
Microsoft.VisualStudio.WebHost.Request.GetRemoteAddress() +65
System.Web.HttpRequest.get_UserHostAddress() +18
System.Web.HttpRequest.get_IsLocal() +13
System.Web.Configuration.CustomErrorsSection.CustomErrorsEnabled(HttpRequest request) +86
System.Web.HttpContext.get_IsCustomErrorEnabled() +42
System.Web.Configuration.UrlAuthFailedErrorFormatter.GetErrorText(HttpContext context) +16
System.Web.Security.UrlAuthorizationModule.WriteErrorMessage(HttpContext context) +29
System.Web.Security.UrlAuthorizationModule.OnEnter(Object source, EventArgs eventArgs) +8777783
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +68
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
Is it correct to use membership and custom IIdentity and IPrincipal at the same time?
If not, where to add properties like the password or other userdata if I use the membership and role providers?
Best regards,
Stephane Erbrech
after some more testing, according to what the link I posted said, it seems that this error is happening only when I run in debug mode from visual studio. If I set the project to run in IIS, the error is gone and the security implementation works as expected.
---Is that a bug in the lightweight webserver implemented in Visual studio then?---
Edit :
You can go in the Properties of your web project, go to the "Web" tab, and check "Use local IIS Server". However, this will require you to run Visual Studio as an Administrator and to have IIS installed on your machine, so that VS can create the virtual directory in the local IIS server when it loads the project.
In my case, I simply had to inherit from MarshalByRefObject.
public class IcmtrIdentity : MarshalByRefObject, IIdentity
{
...
}
This might not be the correct answer, but I had this issue also but fixed it.
Originally, I just had a custom class that inherited GenericIdentity (or implimented IIdentity). When I finally created a custom class which inheritted GenericPrincipal (or implimented IPrincipal) then it all worked?
my CustomPrincipal class did nothing but inherited from GenericPrincipal and had one constructor which called the base constructor.
Both the CustomPrincipal and CustomIdentity classes did NOT impliment any Serialization or ISerializable stuff. Then again, my classes were all very basic.
You can go in the Properties of your web project, go to the "Web" tab, and check "Use local IIS Server". However, this will require you to run Visual Studio as an Administrator and to have IIS installed on your machine, so that VS can create the virtual directory in the local IIS server when it loads the project.
I had the same issue when trying to run the web app using CustomIdentity. In order to set the project to use your IIS in VS 2008, you will need to define the URL to your application pool in your web application project.
This can also be resolved by adding the assembly containing your custom identity to the GAC on your dev machine.