UNABLE_TO_GET_ISSUER_CERT_LOCALLY error when calling the Coinbase NODEJS API - coinbase-api

Since yesterday 5:30 PM (Paris time), I get a UNABLE_TO_GET_ISSUER_CERT_LOCALLY when trying to list my accounts.
I'm using the nodejs library, and it was working fine since several months.
The exact error from the client.getAccounts is :
{ Error: unable to get local issuer certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1142:34)
at TLSSocket.emit (events.js:188:13)
at TLSSocket._finishInit (_tls_wrap.js:631:8) code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY' }
Edit: I've just tried the same calls with the Python API, and it's working fine.
So I feel like there is an issue currently with the Coinbase NodeJS API.

According to Coinbase they updated their certificates at 10.30am PST yesterday. The node client has strictSSL set to true so requests will fail as the certificate chain fails.
Fix: when you initiate the client you can either set strictSSL to false or pass in the new valid certificates.
Set strictSSL to false:
var Client = require('coinbase').Client;
var client = new Client({
apiKey: mykey,
apiSecret: mysecret,
strictSSL: false
});
update cert files (you should be able to export them here - https://baltimore-cybertrust-root.chain-demos.digicert.com/ or try coinbase.com and export there):
var Client = require('coinbase').Client;
var client = new Client({
apiKey: mykey,
apiSecret: mysecret,
caFile: myNewCertFile
});
myNewCertFiles should follow this files format with the updated certs: https://github.com/coinbase/coinbase-node/blob/master/lib/CoinbaseCertStore.js

"What are the security risks (if any) associated with setting strictSSL to false? How do you "export" the new SSL certificates?"
The connection is encrypted, and TLS prevents tampering, BUT with strictSSL set to false it's theoretically possible to do a MITM (Man In The Middle) attack, since the SSL certificate is not fully checked to make sure it's authentic, some hoser (the man in the middle) could use a fake certificate. I'd switch it to get going, but get new certificates going as soon as possible.

Related

Client XXX is configured for secret but secret was not received - React using amazon-cognito-identity-js

I'm asking this question because I was surprised how little information I could find from Googling. However, I was able to track down what I think is the root cause. I'll share it as an answer and see if someone is able to elaborate or provide a better explanation.
So, to clarify, I'm using the AWS JavaScript SDK for Cognito. When I tried some of the standard use cases, I received the following error:
Client is configured for secret but secret was not received
What steps can I take to resolve this?
I heard the same issue and I have to delete App Clients. Create a new App Clients and uncheck Generate client secret. Everything worked as expected in my code.
Looking at the NPM package for Amazon Cognito, I notice that:
When creating the App, the generate client secret box must be unchecked because the JavaScript SDK doesn't support apps that have a client secret.
Checking my app, I found that it had a client secret. I'll try remaking the app without the secret and see if that resolves the issue.
Even i got the same error , I unchecked the "app client secret" check box during new app client creation in cognito . This solved my problem. Thanks.
If you are not using an SDK to communicate with Cognito, you can include "SECRET_HASH" in "AUTH_PARAMETERS". To compute the "SECRET_HASH", please refer to AWS Docs:
https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html#cognito-user-pools-computing-secret-hash
Here is an example of how to log in users using Python using a client that has both a client ID and client secret:
import json
import requests
import hmac
import hashlib
import base64
client_id = ""
client_secret = ""
cognito_url = ""
username = ""
password = ""
secret_hash = base64.b64encode(hmac.new(bytes(client_secret, 'utf-8'), bytes(
username + client_id, 'utf-8'), digestmod=hashlib.sha256).digest()).decode()
reqData = {
"AuthParameters": {
"USERNAME": username,
"PASSWORD": password,
"SECRET_HASH": secret_hash
},
"AuthFlow": "USER_PASSWORD_AUTH",
"ClientId": client_id
}
headers = {
"X-Amz-Target": 'AWSCognitoIdentityProviderService.InitiateAuth',
"Content-Type": 'application/x-amz-json-1.1'
}
jsonResponse = requests.post(
url=cognito_url, data=json.dumps(reqData), headers=headers).json()
print(jsonResponse)

Identity Server Invalid Request Because Of Http Redirection

I am using .net core mvc as identity server client application. When going to the identity server in localhost, the redirect uri goes as https and connects, no problem. But it goes as http on the test server. And cause it is defined as https on the identity server, invalid request returns. How do I make this http part https?
Eror picture:
https://ibb.co/2k2LK5j
I am using UserHttpsRedirection()
I marked with ** related parts in requests.
Working request:
https://test.identityserversite.com/im/connect/authorize?client_id=bla_bla_client&redirect_uri=**https**://localhost:5001/signin-oidc&response_type=id_token
token&scope=openid
profile&response_mode=form_post&nonce=637975263254748013.MTUyNTc5OTgtYmJlMS00ZTAyLTgxMjAtNTNjZDNmZDBjMjY3MWIyNzg2ZDEtNmE1OS00NTUyLWEwNWMtNDI1N2ZiODAwMGVk&state=CfDJ8N9E0C7WvvpEoty-MgpSP4cRET_Y6sOuFDy58PjxCQcyD64gal_CBwXNx6DbTf7FyF8sQ9sJxeGZH1dAQPRn6mVHvUULG3FFz99XW7O9fpq8lTRvDSSxmBMoyBmSt4KwjbXdE60mbnllnlC7kbWT1ytqArRRKj8YtzkGQp2eg69TbuTJkgwIJsnFFbsfZ0Uo0A9xdYBP7eQRuMi9HrCZ6RU8l28E-U4fByg5Qzss2dcmLJDhPxWJd94z17MJwgEK6d1L34Kivc33NsGhXtwvFSypp6m2sgkSR3fT_bwvH-yy&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=6.10.0.0
Not Working request:
https://test.identityserversite.com/im/connect/authorize?client_id=bla_bla_client&redirect_uri=**http**://clienttestsite.com/signin-oidc&response_type=id_token
token&scope=openid
profile&response_mode=form_post&nonce=637975265040994314.NmNiY2Q1MWQtOGJmYy00OWE0LTgxNGMtODk5MjkyY2QwOGNhYTJkMzdlZmItMzI4Ny00NmFkLTg3YjgtYjA4M2UzZDQ5OGZj&state=CfDJ8BWH8w1S3EBHujbHFc1L6rvNMx0jXRaUdB5aDFJ5wMA4IF5h17dNCV78tPAPLThXL6lS937Rz6mt3Jrbhn1cjozAeIL4bFu5YRkQLQeBKdGeAYA2Ikh610MqPSrG7bnCezbpdKrsGVNIKYZqIBuECh_gEm45T_b5HcuhzucF2du1Cz8sDtDmDzYKuSjBUo49b4-YNxM1zkGH8v2dkWxhNpduYYMQJwV53yy_BogGgaaT_8i9bffFKl_rYfOgtNAiw2OzZRpEqaqdvjCNQEetaNPcNnZiJYBEnloBSeG73njLAHIEoWD-OveWAT5-216OBw&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=6.10.0.0
Error Update:
We must use server as http without ssl behind the load balancer by company policy.
We have conf page like this:
options.Authority = identitySettings.Issuer;
options.ClientId = identitySettings.ClientId;
options.ClientSecret = identitySettings.ClientSecret;
options.RequireHttpsMetadata = true;
options.UsePkce = true;
options.SaveTokens = true;
options.TokenValidationParameters.NameClaimType = "given_name";
options.TokenValidationParameters.RoleClaimType = "role";
options.ClaimActions.DeleteClaim("s_hash");
//options.SignedOutCallbackPath = "/account/accessdenied";
//options.SignedOutRedirectUri = "/account/accessdenied";
Func<RedirectContext, Task> redirectToIdentityProvider = (ctx) =>
{
if (!ctx.ProtocolMessage.RedirectUri.StartsWith("https"))
ctx.ProtocolMessage.RedirectUri = ctx.ProtocolMessage.RedirectUri.Replace("http", "https");
return Task.FromResult(0);
};
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = redirectToIdentityProvider
};
// this code changes http redirectUri to https redirectUri
options.CorrelationCookie.SameSite = SameSiteMode.None;
options.NonceCookie.SameSite = SameSiteMode.None;
//options.TokenValidationParameters.ValidateIssuer = false;
//options.TokenValidationParameters.ValidAudience = "9cd9c695-cd02-4b70-a10b-df669cd77ed8";
options.ResponseType = "id_token token";
options.Scope.Clear();
var scopes = identitySettings.Scopes.Split(',');
foreach (var scope in scopes)
{
options.Scope.Add(scope);
}
When we send request from browser our site redirects to identity server with http(issue at top). Identity server wants us to come with https. First identity server return us to "invalid reqquest". Cause allowedRedirectUri is "https:localhost:5001" So we manipulate the redirectUri http to https.(with event OnRedirectToIdentityProvider . You can see on top code). Now our site returns "correlation failed".
UPDATE
Type of our problem has been changed in a while. We figured out problen at the top with assigning ssl to server, not only load balancer.
You should not try to use OpenID connect over HTTP using a browser. Why? Besides security, the browsers will not accept the cookies involved when sent over HTTP.
This is due to the samesite=none attribute set on some of the cookies. Browsers will reject these cookies if sent over HTTP.
HTTP problem
your client seems in development since it is on local host. the client will deploy as http service behind reverse proxy and the domain/subdomains is configured with ssl in the front as your identity is referred as https address. (SSL offloading)
https://test.identityserversite.com
so i dont think you have any problem in that. my services including identity server are http behind reverse proxy and i have subdomain with ssl configuration in nginx and i dont have any problem. and ofcourse for dployment you configure forward headers.
Corelation
in my case it happens when i played around samesite cookies.the configurations for cookie are mismatch between identity server and the client. i was able to reach login but after login i got the error.but it seems you stay samesite to none i guess. how ever it is mostly related to you cookies between client and identityserver

PassportJS not deserializing user on Heroku server

I'm working on a project which is using PassportJS Google OAuth 2.0. When I test on my local machine (with a React client on localhost:3000 and a Express server on localhost:4000), the flow works fine. I am able to send requests to the server and deserialize the user on each request. However, when I host the client on Google Firebase Hosting and the server on Heroku, the user no longer get deserialized on each request.
Here are some specifics of the things I've done / tried / worked locally along with extra information:
The client and server and hosted on different domains.
I am using axios to send the request to the server. In the request, I make sure to set the "withCredentials" property in the options to true to make sure the cookies connected to that domain are sent on each request.
On the server I have CORS enabled for the domain the client is hosted on (as it is currently being hosted on a different domain) and I have "credentials" set to true to allow the credentials to be sent and received.
Please let me know if I've forgotten to include something in the post or if any extra information would be helpful. Thank you in advance.
I don't know if you fix this, but I got the exact same problem, in my case I added sameSite: "none" in my express session setting, it worked.
cookie: {
sameSite: "none", //add this line
...
},

How to allow express backend REST API to set cookie in a react frontend which is using axios?

Backend
I am trying make a JWT cookie based authentication work. I am currently performing the following cookie setting as part of a login route in the backend API.
res.cookie('authCookie', token, {maxAge: 900000, httpOnly: true});
Later when I am auth(ing) any other requests, I am reading off of this cookie and testing it in a passport-jwt strategy.
I have gotten this work in postman - when I perform a login and access a secured route - it works perfectly fine + the cookie is also getting set in postman.
Frontend
Now, I am performing the following call stack in the frontend just to test the working,
axios.post("http://localhost:3001/login", logInParams, config)
.then(result => {
// User is logged in so push them to the respective dashboard
console.log(result);
axios.get("http://localhost:3001/user/profile")
.then(result => {
console.log(result);
})
.catch(err => {
console.log(err);
return;
})
})
.catch(err => {
console.log(err)
return;
});
So basically, I log the user in and that works perfectly fine - I am getting a JSON response as intended, but the call is supposed to set a cookie which it is not and hence the next axios.get call is not returning successfully. Though for some reason I see session cookie and a CSRF cookie. Only this authCookie or the jwt-cookie is not getting set.
Some extra details
I am using cors with default parameters - could this be an error of this? Or is there any changes I have to do with axios? I have seen some answers and being new to MERN I don't really understand them. Does someone know about this or have experienced it and solved it?
Are you running the server from a different port than the one that provides the client (i.e: webpack-dev-server running on localhost:3000 and Express server on localhost:3001)? This looks like a same-site cookie issue. In the latest versions of some browsers such as Chrome cookie setting is being blocked when this one comes from a different origin site. This is due to security concerns; you can learn more about same-site cookies here.
The change made in the browsers is related to the default value they give to a cookie policy property called same-site. The old workaround was treating all the cookies from a different origin as None by default, but last year it changed to consider the same-site policy as Lax when no same-site policy was not explicitly provided by the server. This is a desirable behaviour from the browser because it helps at preventing third party sites making use of the cookie provided by the server, but you can edit it by different ways:
Changing the default same-site policy of your browser settings (the article about same site cookies explains).
Sending a same-site:'None' from the server. Express has a way to do so explaind on its docs. Keep in mind browsers also have a new policy to ignore same-site:'None' when the cookie is not marked as Secure, what demands the use of HTTPS (I guess this behaviour can be edited in your browser settings if you want to check while using HTTP).
Obviously, any strategy that demands the users to change their browser settings is a no-go, so running HTTPS with Secure cookies is mandatory for same-site:'None'.
You always have the approach of making both browser and client same origin, so you won't have any issues at all with same-site (i.e. the Express server returning the index.html of the production build of your client as its main static). I haven't found any way to configure CORS module to have a default same site cookies policy (or its sole use as middleware to change it), likely not its purpose, but you can try by adding a dynamic origin config.
As far as I've seen, Postman does not support the same-site cookie property yet, so that would explain why is it working on Postman but not on the browser.
From the looks of it - it seems to be an issue with how cors works and I am adding the following answer to help anyone else coming across it. Thank me later :)
Server Side
You will have a cors in your server that looks like this,
app.use(cors());
You will have to set credentials to true and set the allowedHeaders and origin as follows,
app.use(cors({
credentials: true,
allowedHeaders: ['Content-Type', 'Authorization'],
origin: ['http://localhost:3000']
}));
This is because normally cookies are not allowed to be set in the browser if the server and the client are in the same port. To handle this the above is required on the server side.
Client Side
We also have to pass the cookies when we are sending the request and to do this with axios just add the following in the index.js of your react app as so,
axios.defaults.withCredentials = true;
I think you should write send('cookies are set') at the end in res.cookie('authCookie', token, {maxAge: 900000, httpOnly: true});

NodeJS and AngularJS - Secure REST API with Client Certificate Authentication

I am currently working on making my REST Api Server (NodeJS + Express + Mongoose) secure, so nobody, except my client application (AngularJS 1.6) and my admin application (based on AngularJS 1.6), can access the routes and fetch or put data into my database. Everything is running on https with a valid SSL certificate.
I mainly thought about two approaches:
Shared secret keys where specific routes needs an "access key"
Client certificate authentication
I went with no. 2, because in my thoughts this is the most secure (please correct if I am wrong :))
So I set up my API Server to run on https and request a valid client certificate:
var options = {
ca: fs.readFileSync(__dirname + "/cert/server.ca"),
key: fs.readFileSync(__dirname + "/cert/server.key"),
cert: fs.readFileSync(__dirname + "/cert/server.crt"),
requestCert: true,
rejectUnauthorized: false
};
https.createServer(options, app)
.listen(PORT, () => {
console.log(`up and running #: ${os.hostname()} on port: ${PORT}`);
console.log(`enviroment: ${process.env.NODE_ENV}`);
});
I handle the rejection of unathorized users directly in the app via:
if (!req.client.authorized) {
var cert = req.socket.getPeerCertificate();
console.log("unauthorized: ", cert);
return res.status(401).send('Not authorized!');
}
And here the problems begin :). On every request my client application does I receive an error:
401 - not authorized
I thought that the client application is sending the SSL certificate with every request (or if requested by nodejs) via "requestCert" and everything is working just fine. But it seems to be a bit more complicated.
In my server.ca file I currently have the certificate chain which I received from the CA.
In console.log the transmitted certificate in the request, but its always empty.
What am I doing wrong? Do I have to configure Angular to send it along with every request? Any suggestions?

Resources