Invalid Signature Key IdentityServer4 - asp.net-core

I'm facing this exception in my authenticated applications with identityserver4:
SecurityTokenInvalidSignatureException: IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.RsaSecurityKey , KeyId:
'. Exceptions caught: ''. token: '{"alg":"RS256","typ":"JWT"}.{"nbf":1501510053,"exp":1501510353,"iss":"http://localhost:5000","aud":"clientId","nonce":"636371068531446271.Nzc2YzRjZGMtN2M0Ny00MGZiLWI3NTQtN2Q2NWIxZGM5MWUyODY2MGE5NTgtYWMzNS00YWJmLWEyMDktNjcwMmJhYTlkYWJk","iat":1501510053,"c_hash":"teGUAAIvU0EY9L1WzjfI2Q","sid":"c870b6184744290472b157ce5992f8e0","sub":"a3915666-8586-476b-9166-b5b183af609e","auth_time":1501508734,"idp":"local","amr":["pwd"]}'.
At this time, I don't have a certificate to use in my Sign in credentials in identity server. So I try this code, sometimes works, but I have sure this is wrong. Someone have a step by step how to use SignInCredentials without a .pfx certificate?
var signinkey = new RsaSecurityKey(RSA.Create());
var signingCredentials = new SigningCredentials(signinkey,
SecurityAlgorithms.RsaSha256);
// Adds IdentityServer
services.AddIdentityServer()
.AddSigningCredential(signingCredentials)
...

Use
services.AddIdentityServer().AddDeveloperSigningCredential()
This will create you a random RSA key pair at first launch and cache it on disk.

Related

Adding Certificate .CER to SAML2 Configuration ITfoxtec.Identity.Saml2

I'm trying to implement SSO using SAML2 and ITfoxtec.Identity.Saml2 package in my ASP.NET MVC ( .NET 6.0 ).
I have the metadata file of the IDP ( Azure AD ) and the .cer certificate file ( both given by the IDP ).
When i'm testing the assertion , i'm getting SAML response success and i can read the claims but when i come to unbind i get " Signature is invalid " , i think because i did not add the public key ( .cer file ) to the Saml config but i'm not sure.
I found how to configure .pfx certificate file ( which required password (private key) ),but not the case for the .cer.
Any ideas please ?
Thanks.
It is enough to read the Azure AD IdP metadata. The IdP metadata contain the public .cer file.
You need to ensure that the code read the certificate correctly in the IdP metadata. Please use the following sample code as a reference.
foreach (var signingCertificate in entityDescriptor.IdPSsoDescriptor.SigningCertificates)
{
if (signingCertificate.IsValidLocalTime())
{
saml2Configuration.SignatureValidationCertificates.Add(signingCertificate);
}
}
if (saml2Configuration.SignatureValidationCertificates.Count <= 0)
{
throw new Exception("The IdP signing certificates has expired.");
}
if (entityDescriptor.IdPSsoDescriptor.WantAuthnRequestsSigned.HasValue)
{
saml2Configuration.SignAuthnRequest = entityDescriptor.IdPSsoDescriptor.WantAuthnRequestsSigned.Value;
}

I'm unable to fetch CNF value in the Token. My Identity Model package version 5.1.0

**I'm testing mTLS with the latest version of IdentityServer4 (straight from the repository). I've configured a client on the test site to use/require mTLS and this works perfectly. (I've verified that I cannot get a token without the client certificate I've configured.)
However, when I look at the JWT token that the server returns, there seems to be a problem with the cnf claim. According to the mTLS specification (RFC8705), the cnf claim should have a property "x5t#S256" that holds the hash of the certificate that was used when the token was requested. **
However, this is the (unpacked) token I got from IdentityServer4:
`I'm using Identity Model package version 5.1.0 but I still don't receive the CNF value.
This issue can be reproduced by the following code.
var payload = new JwtPayload();
payload.Add("cnf", JRaw.Parse("{\"x5t#S256\":\"foo\"}"));
var newtonsoftJson = Newtonsoft.Json.JsonConvert.SerializeObject(payload);
// output is {"cnf":{"x5t#S256":"foo"}}
var textJson = JsonSerializer.Serialize(payload);
// output is {"cnf":{"x5t#S256":[]}}
It has been fixed in https://github.com/cnblogs/IdentityServer4/pull/1/commits/0a7997d00105fd0ba7bca87ed1994d26eb99994e

Not able to connect from Windows Application to IdentityServer4 with SSL

I have a Windows application that is using the "password" grant type. It is able to authenticate to the Identityserver4 without SSL, but not with SSL. The problem is that it is giving an error:
The underlying connection was closed: An unexpected error occurred on a send
I tried it from postman, and it worked, but not from my Windows Application. Below is the code:
var tokenClient = new TokenClient($"{IdentityServer}/connect/token", Constants.ClientId, Constants.ClientSecret);
var tokenResponseTask = tokenClient.RequestResourceOwnerPasswordAsync(username, password, Constants.Scope);
tokenResponseTask.Wait();
return tokenResponseTask.Result;
Below also is another code the I tried, but it doesn't work:
TokenResponse tokenResponse;
string request = $"client_id={clientId}&client_secret={clientSecret}&grant_type={grantType}&scope={scope}&username={username}&password={password}";
using (var client = new WebClient())
{
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
byte[] result = client.UploadData(endpointUrl, "POST", Encoding.UTF8.GetBytes(request));
string resultJson = Encoding.UTF8.GetString(result, 0, result.Length);
tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(resultJson);
}
Finally, I was able to find the solution under the following link:
Authentication failed because remote party has closed the transport stream
'The underlying connection was closed' error is often seen when the SSL handshake fails.
SSL handshake failure usually has something to do with the relevant SSL certificate and whether or not the certificate is trusted.
Check ...
Whether IdentityServer is configured to run under HTTP and HTTPS.
Your Windows Application is correctly configured for SSL.
Test some of the IdentityServer endpoints using a browser with the https protocol.
Hope this gets you going on a helpful investigation path.

Cannot find a token authenticator for the 'Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken' token

I am trying to use WS2007HttpRelayBinding with end to end security mode set to TransportWithMessageCredential. I am using IssuedToken as the credential type. I get the token from a ADFS 2.0 one calling the service I get the following in the on premises wcf trace log
Cannot find a token authenticator for the 'Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken' token type. Tokens of that type cannot be accepted according to current security settings.
update:
This is how I am configuring the service host
ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
serviceConfiguration.ServiceCertificate = GetServiceCertificateWithPrivateKey();
serviceConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
serviceConfiguration.IssuerNameRegistry = new X509IssuerNameRegistry("localhost");
serviceConfiguration.SaveBootstrapTokens = true;
serviceConfiguration.SecurityTokenHandlers.AddOrReplace(new Saml2SecurityTokenHandler());
serviceConfiguration.SecurityTokenHandlers.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri("https://mynamespace.servicebus.windows.net/Service1/"));
FederatedServiceCredentials.ConfigureServiceHost(host, serviceConfiguration);
host.Open();
Can you verify if Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler is added in
<securityTokenHandlers>
<add type="Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler" />
</securityTokenHandlers>
Edit: And also be sure to verify certificates configuration.
Edit: Maybe this will also help MSDN WCF forums
The binding security elements is set to look for SAML 1.1 tokens. I added the following code to the server after constructing the ‘CustomBinding’ element
IssuedSecurityTokenParameters issuedTokenParameters =
myBinding.Elements.Find<TransportSecurityBindingElement>().EndpointSupportingTokenParameters.Endorsing[0] as IssuedSecurityTokenParameters;
issuedTokenParameters.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";
Alexey's answer is perfect for web.config/app.config modifications. Besides that you can also configure the token handler in code (sample from the How to: Authenticate with a Username and Password to a WCF Service Protected by ACS article (learn.microsoft.com) - How to: Authenticate with a User Name and Password):
//
// This must be called after all WCF settings are set on the service host so the
// Windows Identity Foundation token handlers can pick up the relevant settings.
//
ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
serviceConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;
// Accept ACS signing certificate as Issuer.
serviceConfiguration.IssuerNameRegistry = new X509IssuerNameRegistry( GetAcsSigningCertificate().SubjectName.Name );
// Add the SAML 2.0 token handler.
serviceConfiguration.SecurityTokenHandlers.AddOrReplace( new Saml2SecurityTokenHandler() );

Unable to sign security tokens with certificate in WIF scenario

I'm trying to implement a custom STS for a WIF scenario I'm investigating, but it's failing. It's failing when trying to obtain the private key from the certificate used to sign the tokens. I create the STS with the following configuration:
var signingCert = new X509Certificate2(#"C:\<path>\MySigningCertificate.pfx");
var config
= new SecurityTokenServiceConfiguration()
{
DisableWsdl = true,
TokenIssuerName = "Tribold",
SecurityTokenService = typeof(TriboldSecurityTokenService),
SigningCredentials = new X509SigningCredentials(signingCert),
CertificateValidationMode = X509CertificateValidationMode.Custom,
CertificateValidator = new CertificateValidator()
};
However, with WCF diagnostic logging configured, I get the following message in the Service Trace Viewer:
The private key is not present in the X.509 certificate.
This appears to be logged as the code comes out of my custom STS (i.e., after calling GetOutputClaimsIdentity(...) on my custom STS class, and therefore I can only assume that it's now trying to sign the issued security token and failing because it can't obtain a private key to do so.
The private key appears to be present on the loaded certificate:
Debug.Assert(signingCert.HasPrivateKey == true);
but it fails later on. I'm having no luck resolving this, please help!
It looks like thread "cant use .pfx file for X.509 certificates" in the Geneva (= AD FS 2.0) forums covers the same problem which you report. So the resolution reported there might work, which is "specifying the X509KeyStorageFlags.PersistKeySet flag when initiating the X509Certificate2 object".
I'd be surprised if you didn't have to specify a password when opening a PFX file. X509Certificate2 has overloads that take a password in the form of a string or a SecureString.