node.jsangular

Angular, Node API, How to SSL Localhost, DEPTH_ZERO_SELF_SIGNED_CERT, Cookie


LocalHost, Angular 11 (https://localhost:4200) and Node API (https://localhost:3001), both are using OpenSSL, browser is Chrome. To iron out Status: CORS error (due to diff ports) I follow this adding Proxy, got this in Angular's console

[HPM] Error occurred while trying to proxy request /somewhere1 from localhost:4200 to https://localhost:3001 (DEPTH_ZERO_SELF_SIGNED_CERT) (https://nodejs.org/api/errors.html#errors_common_system_errors)

Following didn't help:

  1. Confirmed the Chrome brought up by F5 has chrome://flags/#allow-insecure-localhost Enabled.
  2. Added process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; to Node API's server.js.

Proxy.conf.json

{
    "context": 
    [
        "/path1",      
        "/path2"
    ],
    "target" : "https://localhost:3001", 
    "secure": true,    
    "changeOrigin": true,  
    "rejectUnauthorzied": false,
    "logLevel": "info"  
}

angular.json

"serve": {
          ...
          "options": {
            "browserTarget": "myapp:build",
            "ssl": true,
            "proxyConfig": "src/proxy.conf.json"

Call API:

private http: HttpClient;
const httpOptions = 
      {
          headers: new HttpHeaders({'Content-Type': 'application/json'}),
          rejectUnauthorized: false
      };
this.http.post<any[]>("/somewhere1/hello", {}, httpOptions).subscribe

Believe this is Angular end.


Solution

  • After days of frustration, I'm finally able to resolve them all and posting the solution here hope will help someone forward.

    Environment:

    1. Angular 11/12 front-end uses 3rd-party authentication such as Google.
    2. API server is node 14.
    3. Both are httpS/SSL.

    Solution:

    1. Follow this article to create trusted .crt and .key files
    2. I didn't add localhost to hosts file.
    3. Add a proxy.conf.js (or .json file with conformed format) and include it into angular.json file.
    4. No need to specify httpOption for each individual http call.
    5. API node, add the two files from 1 to server.js.

    My Proxy.conf.js:

    const PROXY_CONFIG = 
    [
        {
            context: 
            [
                "/path1",      
                "/path2",
                ...
            ],
            "target" : "https://localhost:3001", // I use 3000 for non-SSL
            "changeOrigin": true,  // helps on CORS Error in F12
            "logLevel": "debug",
            "rejectUnauthorzied": true, // or false if ok for you
            "secure": false,            // PROD must be "true", but DEV false else "UNABLE_TO_VERIFY_LEAF_SIGNATURE"
            "strictSSL": true,          // false is default
            "withCredentials": true     // required for Angular to send in cookie
        }
    ]
    module.exports = PROXY_CONFIG;
    

    My Angular.json:

    "architect": {
            "serve": {
              "builder": "@angular-devkit/build-angular:dev-server",
              "options": {
                "browserTarget": "myapp:build",
                "ssl": true,
                "proxyConfig": "src/proxy.conf.js"
                ...
    

    My Server.js:

    const fs = require("fs");
    // following are the two files mentioned in No.5
    const HttpSOptions = 
        {
            key: fs.readFileSync('ssl\\server.key'),
            cert: fs.readFileSync('ssl\\server.crt')
        }
    const httpSServer = httpS.createServer(HttpSOptions, app);
    httpSServer.listen(3001, ()=>{console.log('httpS is on 3001');});
    

    To verify certificates are FULLY trusted by Chrome, open one of your API URL call in Chrome, for example http://localhost:3001/path1/func/xyz, you should not see this

    enter image description here