unable to verify the first certificate
La cadena de certificados está incompleta.
Significa que el servidor web al que se está conectando está mal configurado y no incluyó el certificado intermedio en la cadena de certificados que le envió.
Cadena de certificados
Lo más probable es que se vea de la siguiente manera:
- Certificado de servidor: almacena un certificado firmado por intermediario.
- Certificado intermedio: almacena un certificado firmado por la raíz.
- Certificado raíz: almacena un certificado autofirmado.
El certificado intermedio debe instalarse en el servidor, junto con el certificado del servidor.
Los certificados raíz están integrados en las aplicaciones de software, navegadores y sistemas operativos.
La aplicación que sirve el certificado tiene que enviar la cadena completa, esto significa el certificado del servidor en sí y todos los intermedios. Se supone que el cliente debe conocer el certificado raíz.
Recrear el problema
Vaya a https://incomplete-chain.badssl.com usando su navegador.
No muestra ningún error (el candado en la barra de direcciones es verde).
Es porque los navegadores tienden a completar la cadena si no se envía desde el servidor.
Ahora, conéctese a https://incomplete-chain.badssl.com usando Node:
// index.js
const axios = require('axios');
axios.get('https://incomplete-chain.badssl.com')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Registros: " Error: no se puede verificar el primer certificado ".
Solución
Debe completar la cadena de certificados usted mismo.
Para hacer eso:
1: Necesita obtener el certificado intermedio que falta en .pem
formato, luego
2a: extienda el almacén de certificados incorporado de Node usando NODE_EXTRA_CA_CERTS
,
2b: o pase su propio paquete de certificados (intermedios y raíz) usando la ca
opción
1. ¿Cómo obtengo el certificado intermedio?
Usando openssl
(viene con Git para Windows ).
Guarde los detalles del certificado del servidor remoto:
openssl s_client -connect incomplete-chain.badssl.com:443 -servername incomplete-chain.badssl.com | tee logcertfile
Estamos buscando el emisor (el certificado intermedio es el emisor / firmante del certificado del servidor):
openssl x509 -in logcertfile -noout -text | grep -i "issuer"
Debería proporcionarle el URI del certificado de firma. Descargalo:
curl --output intermediate.crt http://cacerts.digicert.com/DigiCertSHA2SecureServerCA.crt
Finalmente, conviértalo a .pem
:
openssl x509 -inform DER -in intermediate.crt -out intermediate.pem -text
2a. NODE_EXTRA_CERTS
Estoy usando cross-env para establecer variables de entorno en el package.json
archivo:
"start": "cross-env NODE_EXTRA_CA_CERTS=\"C:\\Users\\USERNAME\\Desktop\\ssl-connect\\intermediate.pem\" node index.js"
2b. ca
opción
Esta opción sobrescribirá las CA raíz integradas del nodo.
Es por eso que necesitamos crear nuestra propia CA raíz. Use ssl-root-cas .
Luego, cree un https
agente personalizado configurado con nuestro paquete de certificados (raíz e intermedio). Pase este agente a axios
cuando haga una solicitud.
// index.js
const axios = require('axios');
const path = require('path');
const https = require('https');
const rootCas = require('ssl-root-cas').create();
rootCas.addFile(path.resolve(__dirname, 'intermediate.pem'));
const httpsAgent = new https.Agent({ca: rootCas});
axios.get('https://incomplete-chain.badssl.com', { httpsAgent })
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
En lugar de crear un https
agente personalizado y pasárselo axios
, puede colocar los certificados en el https
agente global:
// Applies to ALL requests (whether using https directly or the request module)
https.globalAgent.options.ca = rootCas;
Recursos:
- https://levelup.gitconnected.com/how-to-resolve-certificate-errors-in-nodejs-app-involving-ssl-calls-781ce48daded
- https://www.npmjs.com/package/ssl-root-cas
- https://github.com/nodejs/node/issues/16336
- https://www.namecheap.com/support/knowledgebase/article.aspx/9605/69/how-to-check-ca-chain-installation
- /superuser/97201/how-to-save-a-remote-server-ssl-certificate-locally-as-a-file/
- Cómo convertir .crt a .pem