I had reproduced a library to verify firebase token base on this respo. My app uses the azure function like a backend, so after the user logged in, every action will send to the azure function with the token, and the azure function will validate that token then respond to the results. The library takes the public key from here. I had created an azure function to test this library. My request:
var client = new RestClient("http://localhost:7071/api/test-connection");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("x-requested-with", "XMLHttpRequest");
request.AddHeader("Authorization", "Bearer <My Firebase Token>");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
I encountered an exception
IDX10516: Signature validation failed. Unable to match key:
kid: 'System.String'.
Exceptions caught:
'System.Text.StringBuilder'.
token: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'. Valid Lifetime: 'System.Boolean'. Valid Issuer: 'System.Boolean'
I had spent over 2 days researching the reasons and solutions. A week before my code worked well. Is the problem caused by the public keys I got from google?
I was getting the same error, and was having a really hard time debugging it.
Based on this answer, I added the following code to my Startup.cs:
if (env.IsDevelopment())
{
IdentityModelEventSource.ShowPII = true;
}
Once I made this change and reproduced the error, I was able to see the actual value for kid (instead of kid: 'System.String' in my error message, I saw kid: 'ABCDEF' - not the real value, but hopefully you get the idea).
Next, I compared that value to the kid values listed here - and sure enough, that value was not present, hence the "unable to match key" error.
In my case, it turns out that I was not obtaining the token from Firebase correctly. I was making a request to https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword, but from the documentation I found this:
returnSecureToken boolean - Should always be true.
I was not setting this property in my request. After using a token obtained when setting this property correctly, I stopped getting the "IDX10516: Signature validation failed. Unable to match key" error in my C# code.
Related
I want to use the V3 SnipCart API to get data about specific orders on my thank you page. I am using C# to do this. I keep getting this error when trying to use the API
System.Net.WebException:'The remote server returned an error: (401)
Unauthorized.'
I have tried to follow their documentation by using only the API key with no password as shown here. Below is my code that I wrote that is giving me the error. I wrote this inside my controller. I get the error as soon as the breakpoint hits this line responseObjGet = (HttpWebResponse)requestObjGet.GetResponse();
//Testing API get data begin
string strurltest = String.Format("https://app.snipcart.com/api/orders/c5541254-r8541-8501-0024-juy85vv002154");
WebRequest requestObjGet = WebRequest.Create(strurltest);
requestObjGet.Credentials = new NetworkCredential("HihiukoJOUBVCTYIiijiGiiYTd6tOiUyTYo", "");
requestObjGet.Method = "GET";
HttpWebResponse responseObjGet = null;
responseObjGet = (HttpWebResponse)requestObjGet.GetResponse(); //401 is triggered here
string strresulttest = null;
using (Stream stream = responseObjGet.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresulttest = sr.ReadToEnd();
sr.Close();
}
Concerns that I have as well are the following:
1.The API key that I entered here is my public api key since I am still in the development and testing phase. I am not sure if this api call will work with the test api key or if I have to use the real secret production key. Any thoughts?
2.I am debugging this off my local machine (localhost:) for now before I deploy these API calls to production to test these changes in prod still with the test api key, could that be a reason for the 401? Since the URL that is trying to get the info is my localhost: url and not my actual domain that I added to SnipCart Dashboard. I was thinking maybe I have to try and hit this from prod environment instead? Any thought?
These are the 2 possibilities that come to mind for me. I am not too savvy on APi's yet so I don't know if my call is missing something.
Summary: All I am trying to do is be able to use the API so that I can load the data I want for an order when users reach my custom thank you page with their token.
Our 401 "Unauthorized" status code is returned when the authentication failed to our API with your Authorization header's value.
Here's the documentation about the auth to our APIs. Make sure to return us a base64 value of your secret API key and the trailing single colon character at the end to respect the Basic Authentication Scheme.
And if you are trying to get data for an order that was placed in live mode then you would need to use the live secret API key.
I hope this makes sense. I am using the Zoho C# SDK examples to write records to the CRM Leads. While calling recordOperations.CreateRecords(); it fails after trying to GetToken from the Token Store.
Here is the token I am saving
Token token = new OAuthToken(
"xxxx.clientid.goes.here.xxxxx",
"xxxx.clientsecret.goes.here.xxxx",
"REFRESH/GRANT token",
TokenType.GRANT,
string.Empty);
TokenStore tokenStore = new CustomTokenStore();
tokenStore.SaveToken(user, token);
And I am sending this token into the SDKInitilizer.Initialize. No errors at this point. Next I try and create a lead. When it gets inside of recordOperations.CreateRecords(); it tries GetToken and I've hard coded it to return exactly what was in the token object above. CreateRecords throws an error for "invalid_code". Here is what is in the log file
21-09-07 16:49:34 [INFO]: Initialization successful for Email Id : myemail#email.com in Environment : https://www.zohoapis.com.
21-09-07 16:49:47 [INFO]: Access Token has expired. Hence refreshing.
21-09-07 16:49:50 [ERROR]: Exception in authenticating current request : {"Code":"INVALID CLIENT ERROR","Message":"invalid_code","Cause":null,"Details":null,"StackTrace":" at Com.Zoho.API.Authenticator.OAuthToken.ParseResponse(String response)\r\n at Com.Zoho.API.Authenticator.OAuthToken.RefreshAccessToken(UserSignature user, TokenStore store)\r\n at Com.Zoho.API.Authenticator.OAuthToken.Authenticate(APIHTTPConnector urlConnection)\r\n at Com.Zoho.Crm.API.Util.CommonAPIHandler.APICall[T](Type className, String encodeType)","Data":{},"InnerException":null,"HelpLink":null,"Source":"ZCRMSDK","HResult":-2146233088}
It appears to be failing when it tries to refresh the token so I assume I am not sending in the right info in the token object?
*** Edit for #sucasa ***
This is what I am sending into the Initialize method.
What I have figured out since my first post is, I'm not getting the initial token from Initialize and its not calling the custom TokenStore.SaveToken() I created and it should, right? If I save it, all I have is what is above, not an actual token. So I think when I go to create the lead, I don't actually have the initial token to refresh. I hope that's clearer.
Access Tokens expire and must be refreshed using a refresh token. The error message indicates this. Can you log the value of token and report back here?
As I am on my way to switch from using the legacy header authentication method to the JWT Token method, I have used the following example found here.
However, I get the following error :
Error calling Login: {
"errorCode": "PARTNER_AUTHENTICATION_FAILED",
"message": "The specified Integrator Key was not found or is disabled. An Integrator key was not specified."
}
Below is my C# code.
string oauthBasePath = "account-d.docusign.com";
string privateKeyFilename = "./private.pem";
int expiresInHours = 1;
ApiClient apiClient = new ApiClient(docuSignUrl);
apiClient.ConfigureJwtAuthorizationFlow(
"IntegratorKey",
"USER ID GUID",
oauthBasePath,
privateKeyFilename,
expiresInHours);
AuthenticationApi authApi = new AuthenticationApi(apiClient.Configuration);
return authApi.Login();
I have found this thread that shows the similar error but it doesn't seem resolved
Update 05/07/2018: I have validated the domain used in my account but I still get the same error message
Update 05/11/2018: When I use my code but that I replace the IntegratorKey, UserID and private key used in the DocuSign Unit Tests here, my code now works !? Hence, I can only conclude that the issue doesn't come from my code but maybe a configuration issue on the DocuSign side ? do I need to configure my Integrator Key a specific way ?
After more investigation, the reason with such an error is that I was not generating the Authorization Code Grant prior to executing my code.
Based on the information found here, I had to perform the following HTTPRequest example :
GET /oauth/auth?
response_type=token
&scope=signature
&client_id=YOUR_INTERGRATOR_KEY
&state=a39fh23hnf23
&redirect_uri=http://www.example.com/callback
Once it is approved, then I can run my code successfully.
In the end, the initial error message is really misleading (I might argue it could be considered a bug ?).
This is a followup of this question here. Might not be directly related to that.
I am trying to call a web service secured with a token (federated security, WS-Trust 1.3) which I obtain from a Secure Token Service. I have the SecurityToken (generic XML) and I create a ChannelFactory<T> on which I then call CreateChannelWithIssuedToken.
The actual error appears when I attempt to invoke a service method. The message is very short and I actually have no idea where to look next: MessageSecurityException and message Unable to create token reference. Well, that can mean anything.
The relevant code:
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
var factory = new ChannelFactory<IService>(
binding,
new EndpointAddress("..."));
factory.Credentials.SupportInteractive = false;
var token = STSClient.Issue();
_channel = factory.CreateChannelWithIssuedToken(token);
And calling the service is:
var svcParams = ...;
//MessageSecurityException is thrown here
var svcResponse = _channel.SomeServiceMethod(params);
What I would like to know is where can I look next. What could cause this error ?
Additional details:
The error is thrown before any request is made to the server (checked with Fiddler).
The server is not WCF based. It's some service that complies to WS-Trust and WS-Security.
Actually, the issue was insufficient configuration of the federation binding. Because I already have the token and it is already signed I should have set the IssuedKeyType on the message security to SecurityKeyType.BearerKey.
By playing further with this turns out that Unable to create token reference is thrown every time when there are, well, not enough details to embed the token in the request (typically it's missing configuration on the binding or on the binding's TransportSecurityBindingElement).
This does not completely solve the entire "calling the service with a token" issue, but it does solve this particular error:
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.NegotiateServiceCredential = false;
I have a WCF client that is crashing with the error "The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken'." for every response.
I've looked around and this blog post seems to indicate that the problem is with my certificate set up, but I'm not sure what I am doing wrong...
My client uses a custom binding with a MutualCertificateBindingElement for security, I am configuring the certificates in code as follows:
client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
client.ClientCredentials.ServiceCertificate.SetDefaultCertificate
(
StoreLocation.CurrentUser,
StoreName.AddressBook,
X509FindType.FindBySerialNumber,
"[serial number 1]"
);
client.ClientCredentials.ClientCertificate.SetCertificate
(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySerialNumber,
"[serial number 2]"
);
The serial numbers match the values in the <X509SerialNumber> elements in both the request and the response messages.
One discrepancy I have noticed is the <X509IssuerName> elements in the request and the response are formatted differently:
Request: CN=[CN], O=[O], L=[L], C=[C]
Response: C=[C],L=[L],O=[O],CN=[CN]
Is it possible this is causing the issue?
UPDATE
Turns out it was the certificate name formatting causing the issue. I managed to resolve it by replacing the cert names in the response with what WCF expects by using a custom encoder. Now I have this ugly hack, but it works so I'll live with it!
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
var msgContents = new byte[buffer.Count];
Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length);
bufferManager.ReturnBuffer(buffer.Array);
var message = Encoding.UTF8.GetString(msgContents);
// Fix certificate issuer name formatting to match what WCF expects.
message = message.Replace
(
"C=[C],L=[L],O=[O],CN=[CN]",
"CN=[CN], O=[O], L=[L], C=[C]"
);
var stream = new MemoryStream(Encoding.UTF8.GetBytes(message));
return ReadMessage(stream, int.MaxValue);
}
The issuer name order that you mentioned is most probably the issue. Since these names are not signed I suggest you write a custom encoder in your client that replaces the names in the response to be formatted as in the request.
Besides obvious cert mismatch and barring miss-configuration... I have seen an issue trying to access private key. Check that client has appropriate permissions to the cert private key. If you right click on the cert in certmanager you should see AllTasks/Manage Private Keys. Add your client's process identity to the list.
Also make sure that the certificate you are using is correct. I used self-signed certificate which was missing Subject Key Identifier.
WCF : The EncryptedKey clause was not wrapped with the required encryption token 'System.IdentityModel.Tokens.X509SecurityToken'