Unable to verify the first certificate Next.js - npm

I am trying to build a new application.
It accesses one API to get some data over HTTPS.
Status2.getInitialProps = async () => {
console.info('ENTERRRRRRRR')
const res = await fetch('https://test.com/api/v1/messages', {
method: 'get',
headers: {
'Authorization': 'Bearer ffhdfksdfsfsflksfgjflkjW50aXNocjEiLCJpYXQiOjE2MDc1ODIzODQsImF1ZCI6InJlY3J1aXRpbmdhcHAtMTAwMC5kZXZlbG9wLnVtYW50aXMuY29tIiwiaXNzIjoicmVjcnVpdGluZ2FwcC0xMDAwLmRldmVsb3AudW1hbnRpcy5jb20ifQ.0jqPutPOM5UC_HNbTxRiKZd7xVc3T5Mn3SjD8NfpEGE',
'Accept': 'application/vnd.api+json'
}
}
)
}
When the browser tries to access this API then it gives me the following error:
Server Error
FetchError: request to https://test.com/api/v1/messages failed, reason: unable to verify the first certificate
This error happened while generating the page. Any console logs will be displayed in the terminal window.
C
To solve this issue I followed this but when tried it, it gave me another error:
'NODE_TLS_REJECT_UNAUTHORIZED' is not recognized as an internal or external command,
operable program or batch file.

The NODE_TLS_REJECT_UNAUTHORIZED solution is a no-go as it is against the main purpose of having a trusted connection between your front-end and API. We run into this error message recently with a NextJS as the front-end, ExpressJS as the back-end, and Nginx as the webserver.
If you or your team are on implementing the API, I would suggest looking into your webserver config and how you are handling the path of the certificates as the problem might be related to a misconfiguration of the intermediate certificate. Combining the certificate + intermediate certificate like so did the trick for us:
# make command
cat {certificate file} {intermediate certificate file} > {new file}
# config file /etc/nginx/conf.d/xxx.conf
ssl_certificate {new file};

create a next.config.js file if you not already have one in your project and add the following to your webpack config:
const webpack = require("webpack");
module.exports = {
webpack: (config) => {
config.node = {
fs: "empty",
};
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
const env = Object.keys(process.env).reduce((acc, curr) => {
acc[`process.env.${curr}`] = JSON.stringify(process.env[curr]);
return acc;
}, {});
config.plugins.push(new webpack.DefinePlugin(env));
return config;
},
};
Do not use it like this in production. It should only be used in a dev environment.

Related

Cannot import module from Cypress spec file

I am trying to use the #peculiar/x509 library to decode a CSR to use some of the information in my tests. The tests are using Cypress.
Here is an extract of my code:
import * as x509 from '#peculiar/x509';
const request = {
certificateSigningRequest: `-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----`,
};
describe('PKI', () => {
it('works', () => {
console.log(x509);
const stringPEM = request.certificateSigningRequest
.replace(/(-----(BEGIN|END) CERTIFICATE REQUEST-----|\n)/g, "");
const cert = new x509.X509Certificate(stringPEM);
console.log(cert.subject);
return;
// Stuff I want to test
});
});
When I try to log the x509 variable it returns an empty object.
And on the const cert = new x509.X509Certificate(stringPEM); line, I get an error:
x509.X509Certificate is not a constructor.
If I try to set up a simple project with a Typescript file to import the library and just log the x509 variable, it displays all the exports correctly.
I can't figure why it behaves like that with Cypress, so any help is appreciated.
EDIT: Diving a bit more into how Cypress works, I now understand that my assumption about the spec files running/controlled in a Node process was wrong. Spec files are running in the browser. So I would need to inject the browser version of the library in the spec file.
This can be done via the plugin API of Cypress, because it runs in the Cypress node process.
You can import a specific build, either x509.es.js or x509.cjs.js and your code works. The base #peculiar/x509 is for <script> inclusion.
One thing, the BEGIN and END tokens need to remain in the request for it to be recognized.
import * as x509 from '#peculiar/x509/build/x509.es.js'
// const x509 = require('#peculiar/x509/build/x509.cjs.js') // alternative
// hard left for multiline strings, otherwise request is not correctly formatted
const request = {
certificateSigningRequest: `-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----`,
};
// copied from #peculiar/x509 to verify format - not necessary for test
const isPem = (data) => {
return typeof data === "string"
&& /-{5}BEGIN [A-Z0-9 ]+-{5}([a-zA-Z0-9=+/\n\r]+)-{5}END [A-Z0-9 ]+-{5}/g.test(data);
}
console.log(isPem(request.certificateSigningRequest))
describe('PKI', () => {
it('works', () => {
console.log(x509);
const stringPEM = request.certificateSigningRequest // leave in BEGIN and END
const cert = new x509.X509Certificate(stringPEM);
console.log(cert.subject); // prints e.g. "CN=Test certificate, E=some#email.net"
return;
// Stuff I want to test
});
});
Possibly due to NodeJS version issue.
The X509Certificate was added recently in NodeJS version 15.6.0. Changelog here. So it requires that version. It might have worked on your simple project because of a newer NodeJS version.
And by default, Cypress is using its bundled NodeJS version, which since Cypress version 7.0.0 to 8.2.0, it's using bundled NodeJS version 14.16.0, as per the changelog here:
The bundled Node.js version was upgraded from 12.18.3 to 14.16.0.
So you can try changing/overriding the bundled NodeJS version in Cypress configuration to version 15.6.0, as per this configuration:
nodeVersion

Unable to verify the first certificate using Amazon SDK and Minio

Trying to connect to a minio server using the following code:
var AWS = require('aws-sdk');
var s3 = new AWS.S3({
accessKeyId: 'minio' ,
secretAccessKey: 'minio123' ,
endpoint: 'https://minio.dev' ,
s3ForcePathStyle: true, // needed with minio?
signatureVersion: 'v4',
sslEnabled: false,
rejectUnauthorized: false
});
// putObject operation.
var params = {Bucket: 'documents', Key: 'testobject', Body: 'Hello from MinIO!!'};
s3.putObject(params, function(err, data) {
if (err)
console.log(err)
else
console.log("Successfully uploaded data to documents/testobject");
});
// getObject operation.
var params = {Bucket: 'documents', Key: 'testobject'};
var file = require('fs').createWriteStream('/tmp/mykey');
s3.getObject(params).
on('httpData', function(chunk) { file.write(chunk); }).
on('httpDone', function() { file.end(); }).
send();
I get the following error:
{ Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1051:34)
at TLSSocket.emit (events.js:189:13)
at TLSSocket.EventEmitter.emit (domain.js:441:20)
at TLSSocket._finishInit (_tls_wrap.js:633:8)
message: 'unable to verify the first certificate',
code: 'NetworkingError',
region: 'us-east-1',
hostname: 'minio.dev',
retryable: true,
time: 2019-07-11T23:38:45.382Z }
I have passed the options "sslEnabled: false", but this doesn't change anything. I've also tried to disable SSL on the node side and it also fails to change the behavior.
Does anybody have any ideas on how to ignore the self signed cert error? (if that is the issue, which I believe it is)
const AWS = require('aws-sdk');
const https = require('https');
// Allow use with Minio
AWS.NodeHttpClient.sslAgent = new https.Agent({ rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0' });
// the rest of the code snippet remains unchanged
rejectUnauthorized: false is the key. In this example, I've tied it to the existence of a commonly used environment variable that toggles the behavior in the request module. AWS SDK doesn't use it for its API, but reusing it seemed appropriate since it performed the same function.
Now if NODE_TLS_REJECT_UNAUTHORIZED=0 is set, the whole Node process including the AWS SDK will work with mocked HTTPS endpoints.
WARNING: Only use this in a development environment, such as mocking public services on your local workstation. It can leave you open to Man-In-The-Middle attacks!

Network error with axios and react native

I have created an API endpoint using the Django python framework that I host externally. I can access my endpoint from a browser (mydomain.com/endpoint/) and verify that there is no error. The same is true when I run my test django server on locally on my development machine (localhost:8000/endpoint/). When I use my localhost as an endpoint, my json data comes through without issue. When I use my production domain, axios gets caught up with a network error, and there is not much context that it gives... from the debug console I get this:
Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
at XMLHttpRequest.dispatchEvent (event-target.js:172)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:554)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:387)
at XMLHttpRequest.js:493
at RCTDeviceEventEmitter.emit (EventEmitter.js:181)
at MessageQueue.__callFunction (MessageQueue.js:353)
at MessageQueue.js:118
at MessageQueue.__guardSafe (MessageQueue.js:316)
This is my axios call in my react native component:
componentDidMount() {
axios.get('mydomain.com/get/').then(response => { // localhost:8000/get works
this.setState({foo:response.data});
}).catch(error => {
console.log(error);
});
}
If you are trying to call localhost on android simulator created with AVD, replacing localhost with 10.0.2.2 solved the issue for me.
It seems that unencrypted network requests are blocked by default in iOS, i.e. https will work, http will not.
From the docs:
By default, iOS will block any request that's not encrypted using SSL.
If you need to fetch from a cleartext URL (one that begins with http)
you will first need to add an App Transport Security exception.
change from localhost to your ip(192.168.43.49)
add http://
http://192.168.43.49:3000/user/
If you do not find your answer in other posts
In my case, I use Rails for the backend and I tried to make requests to http://localhost:3000 using Axios but every time I got Network Error as a response. Then I found out that I need to make a request to http://10.0.2.2:3000 in the case of the android simulator. For the iOS simulator, it works fine with http://localhost:3000.
Conclusion
use
http://10.0.2.2:3000
instead of
http://localhost:3000
update
might worth trying
adb reverse tcp:3000 tcp:3000
For me, the issue was because my Remote URL was incorrect.
If you have the URL is a .env file, please crosscheck the naming and also ensure
that it's prefixed with REACT_APP_ as react might not be able to find it if named otherwise.
In the .env file Something like REACT_APP_BACKEND_API_URL=https://appurl/api
can be accessed as const { REACT_APP_BACKEND_API_URL } = process.env;
Try
"Content-Type": "application/x-www-form-urlencoded",
Accept: "application/json"
If you are using android then open your command prompt and type ipconfig. Then get your ip address and replce it with localhost.
In my case, first I used http://localhost:8080/api/admin/1. Then I changed it to http://192.168.1.10:8080/api/admin/1. It worked for me.
Make sure to change localhost to your_ip_address which you can find by typing ipconfig in Command Prompt
Trying adding to your AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
I was facing the same issue.
i looked deeper and my
endpoint url was not correct.
By giving axios right exact url, my api worked like charm.
Hope it may help anyone
Above mentioned answers only works if you are using localhost but if your code is hosted on a server and Axios throwing Network Error then you can solve this by adding one line.
const config = {
method: 'post',
url: `${BASE_URL}/login`,
headers: {
'Content-Type': 'multipart/form-data'. <----- Add this line in your axios header
},
data : formData
};
axios(config).then((res)=> console.log(res))
I'm using apisauce dependancy & Adding header work for me with React Native Android.
Attach header with request like below:
import { create } from 'apisauce';
const api = create({
baseURL: {baseUrl},
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
export async function empLogin(data) {
try {
const response = api.post('Login', data);
return await response;
} catch (error) {
console.log(error);
return [];
}
}
before:
axios.get("http://localhost:3456/apt")
.then(
response => {
alert(JSON.stringify(response));
....
}
)
.catch(function(error) {
alert(error.message);
console.warn(error.response._response);
});
I get Error "Network error" Failed to connect to the localhost after that, I make some steps to resolved the error.
Network Error related to axios resloved by the disabling the system firewall and access from the system IP Address like
axios.get("http://192.168.12.10:3456/apt")
.then(
response => {
alert(JSON.stringify(response));
....
}
)
.catch(function(error) {
alert(error.message);
console.warn(error.response._response);
});
For me adding "Accept" in headers resolved the problem:
Accept: 'application/json'

How to serve data for AJAX calls in a Vue.js-CLI project?

I have a Vue.js CLI project working.
It accesses data via AJAX from localhost port 8080 served by Apache.
After I build the project and copy it to a folder served by Apache, it works fine and can access data via AJAX on that server.
However, during development, since the Vue.js CLI website is being served by Node.js which is serving on a different port (8081), I get a cross-site scripting error) and want to avoid cross-site scripting in general.
What is a way that I could emulate the data being provided, e.g. some kind of server script within the Vue.js-CLI project that would serve mock data on port 8081 for the AJAX calls during the development process, and thus avoid all cross-site scripting issues?
Addendum
In my config/index.js file, I added a proxyTable:
dev: {
env: require("./dev.env"),
port: 8081,
autoOpenBrowser: true,
assetsSubDirectory: "static",
assetsPublicPath: "/",
proxyTable: {
"/api": {
target: "http://localhost/data.php",
changeOrigin: true
}
},
And now I make my AJAX call like this:
axios({
method: 'post',
url: '/api',
data: {
smartTaskIdCode: 'activityReport',
yearMonth: '2017-09',
pathRewrite: {
"^/api": ""
}
}
But now I see in my JavaScript console:
Error: Request failed with status code 404
Addendum 2
Apparent axios has a problem with rerouting, so I tried it with vue-resource but this code is showing an error:
var data = {
smartTaskIdCode: 'pageActivityByMonth',
yearMonth: '2017-09'
}
this.$http.post('/api', data).then(response => {
this.pageStatus = 'displaying';
this.activity = response.data['activity'];
console.log(this.activity);
}, response => {
this.pageStatus = 'displaying';
console.log('there was an error');
});
The webpack template has its own documentation, and it has a chapter about API proxying during development:
http://vuejs-templates.github.io/webpack/proxy.html
If you use that, it means that you will request your data from the node server during development (and the node server will proxy< the request to your real backend), and the real backend directly in production, so you will have to use different hostnames in each environment.
For that, you can define an env variable in /config/dev.env.js & /config.prod.env.js

electron certificates network

I am trying to write a simple electron app to interface with a REST server. The server doesn't have the appropriate certificates. When I try to make a 'GET' request (using fetch()), I get the following error message:
Failed to load resource: net::ERR_BAD_SSL_CLIENT_AUTH_CERT
Fixing the certs is not currently an option. I tried to use the 'ignore-certificates-error' flag (see below). It seems like it should allow me to skip over this error, but it doesn't.
var electron = require('electron');
var app = electron.app
app.commandLine.appendSwitch('ignore-certificate-errors');
...
The result is the same error.
Questions:
I am correct in assuming this options is supposed to help here?
If so, any ideas what I am doing wrong?
Electron version: 1.2.8
Thanks!
You can update your version of electron and use this callback:
app.on('certificate-error', (event, webContents, link, error, certificate, callback) => {
if ('yourURL/api/'.indexOf(link) !== -1) {
// Verification logic.
event.preventDefault();
callback(true);
} else {
callback(false);
}
});
That you going do the fetch to your api with https.