How can I get an Ionix 4 (Angular) Application using a Nest Application Backend in a LAN to Beat the "Same Origin CORS" Error?

I have built an Ionic 4 application that makes API calls to a NestJs application, I also developed on the same system. Everything works as expected between both applications in development, but how do I deploy them to a server in a LAN and avoid the error: “…Same Origin Policy disallows … http://localhost://9900/auth/login…”? I’ve searched the Internet for a solution, and even Stackoverflow all week long, but my problem seems to defy all the solutions on offer.

1) This is for CentOS server in a LAN: MongoDB, Nginx, etc. already installed and tested OK.
2) The Ionic 4 App developed and tested OK, and communicates well with the NestJs, when run both on the server itself, and on the development laptop PC.
3) API Calls are made on the NestJS application (named server) by the Ionic 4 application (called regmanager). The code supplied here is limited to the relevant calls, in order to leave my question (I believe) as simple as possible.

// (1) A TYPICAL CALL FROM THE IONIC 4 (ANGULAR) APP
// EVERYTHING WORKS AS EXPECTED IN DEVELOPMENT (AND PRODUCTION, IF ON THE SAME DOMAIN)

  httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
        'Authorization': 'Bearer {JWT Token}'
      })
   };

   endpointUrl = 'http://localhost:9900/users';

   /** POST: add a new user to the database */
   createNew(user: User): Observable<User> {
      user.username = user.username.toLowerCase();
      user.sname = user.sname.toUpperCase();
      user.fname = this.strkit.toTitleCase(user.fname);
      user.onames = this.strkit.toTitleCase(user.onames);

      const ret = this.http.post<User>(this.endpointUrl, user, This.httpOptions);
      ret.subscribe(e => {
        console.log(
          `Maybe saved records for ${e.sname}, ${e.fname} ${
          e.onames
          } to database.`
        );
      });
      return ret;
  }


/// (2) BACKEND CODE: Using Nestjs
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

declare const module: any;

    async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    app.enableCors();
    app.use((req, res, next) => {
        res.header('Access-Control-Allow-Origin', '*');
        res.header('Access-Control-Allow-Methods','GET,PUT,POST,DELETE,OPTIONS');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
      next();
  });
    await app.listen(9900);

    if (module.hot) {
      module.hot.accept();
      module.hot.dispose(() => app.close());
  }
}
bootstrap();

//// (3) CREATING A TEST USER IN MONGODB WORKED! 
 curl -X POST -H 'content-type: application/json' -d '{
    "username":"betty",
    "email":"[email protected]",
    "password": "betty1999",
    "passwordHash": "",
    "sname": "Andrews",
    "fname": "Elizabeth",
    "onames": "Baby",
    "phoneNo":"08086669874",
    "active": true,
    "roles": ["user", "admin"]
  }' localhost:9900/auth/register

//// (4) LOGGING IN THE SAME TEST USER IN MONGODB WORKED!
curl -X POST -H 'content-type: application/json' -d '{
    "username": "betty",
    "password": "betty1999"
  }' localhost:9900/auth/login

//// (5) NGINX CONFIGURATION /etc/nginx/nginx.conf ///
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

http {

    server {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Content-Length' 0;
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';

    server_name  localhost;
        # configuration of HTTP virtual server 1   
        # listen      80 default_server;
        listen [::]:8000 default_server;    

        add_header 'Access-Control-Allow-Origin' 'http://localhost';
    # add_header 'Access-Control-Allow_Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';

       # location / {
    #   root /var/www/html/mainapp/www/;
    #   try_files $uri $uri/ /index.html;      
    # }  
    location / {
      root /var/www/html/mainapp/www/;
      try_files $uri $uri/ /index.html;

    proxy_pass http://localhost:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'application/json';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
        add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
     } 
        }   

        location ~ .html? {
            # configuration for processing URIs starting with '/one'
            root /var/www/html/mainapp/www/;
            try_files $uri $uri/ /index.html;

        }
        location ~ .js? {
            # configuration for processing URIs starting with '/two'
            root /var/www/html/serverapp/dist/;
        }
    }

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

Source: Angular

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.