gentics / mesh

Gentics Mesh - The open source headless CMS for developers
https://getmesh.io
Apache License 2.0
570 stars 115 forks source link

/api/v2/auth/login doesn't respond to OPTIONS (404) request for CORS check #1008

Open marvin-w opened 4 years ago

marvin-w commented 4 years ago

Gentics Mesh Version, operating system, or hardware.

Operating System

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cms
  namespace: business
spec:
  replicas: 1
  selector:
    matchLabels:
       app: cms
  template:
    metadata:
      labels:
        app: cms
    spec:
      serviceAccountName: traefik-ingress-controller
      containers:
      - image: gentics/mesh:1.4.0
        imagePullPolicy: Always
        env:
          - name: MESH_ELASTICSEARCH_URL
            value: 'http://elasticsearch.business'
          - name: MESH_ELASTICSEARCH_START_EMBEDDED
            value: 'false'
          - name: MESH_AUTH_KEYSTORE_PASS
            value: 'h678fio876r57gikj76rf' - not the real one ;)
          - name: MESH_MONITORING_HTTP_HOST
            value: '0.0.0.0'
        name: cms
        ports:
        - containerPort: 8080
        volumeMounts:
          - mountPath: /graphdb
            name: cms-graphdb-volume
          - mountPath: /keystore
            name: cms-keystore-volume
          - mountPath: /uploads
            name: cms-uploads-volume
      volumes:
        - name: cms-graphdb-volume
          persistentVolumeClaim:
            claimName: cms-graphdb-pvc
        - name: cms-keystore-volume
          persistentVolumeClaim:
            claimName: cms-keystore-pvc
        - name: cms-uploads-volume
          persistentVolumeClaim:
            claimName: cms-uploads-pvc
---
---
apiVersion: v1
kind: Service
metadata:
  name: cms-http-service
  namespace: business
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: cms
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    ingress.kubernetes.io/custom-response-headers: Access-Control-Allow-Origin:* || Access-Control-Allow-Methods:POST, GET, HEAD, OPTIONS, PUT, DELETE
  name: cms-ingress
  namespace: business
spec:
  rules:
  - host: cms.xxxxx.de
    http:
      paths:
      - path: /
        backend:
          serviceName: cms-http-service
          servicePort: 80

JVM

Problem

When I try to log in via my angular frontend in order to obtain data via the graphql API I find the following log in my console:

OPTIONS https://cms.xxxxx.de/api/v2/auth/login 404 Access to XMLHttpRequest at 'https://cms.xxxxx.de/api/v2/auth/login' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

When I try to reproduce it locally via curl it also returns the following 404 error:

curl -X  OPTIONS https://cms.xxxxx.de/api/v2/auth/login -v
*   Trying 37.24.225.83...
* ....
> OPTIONS /api/v2/auth/login HTTP/2
> Host: cms.xxxxxx.de
> User-Agent: curl/7.58.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< **HTTP/2 404** 
< access-control-allow-methods: POST, GET, HEAD, OPTIONS, PUT, DELETE
< access-control-allow-origin: *
< content-type: application/json; charset=utf-8
< vary: Accept-Encoding
< x-powered-by: getmesh.io
< content-length: 243
< date: Sat, 15 Feb 2020 23:42:48 GMT
< 
{
  "message" : "Not Found",
  "internalMessage" : "The rest endpoint or resource for given path {/api/v2/auth/login} could not be found. Please verify that your Accept header is set correctly. I got {*/*}. It must accept {application/json}"
* Connection #0 to host cms.xxxxxx.de left intact

Expected behaviour and actual behaviour

Expected: OPTIONS request to /v2/api/auth/login returns status code 200 Observed: OPTIONS request to /v2/api/auth/login returns status code 404 Not Found

Jotschi commented 4 years ago

@marvin-w Please add Access-Control-Allow-Credentials: true to your ingress configuration. I assume this is the reason why CORS is not working for you as expected.

marvin-w commented 4 years ago

@Jotschi Thanks for the fast response. I added the header but unfortunately it still does not work. I do get the same error. I added the frontend code that triggers the login below. I had that exact same code for another project and it was working there (but both projects were hosted on the same host).

login(): Promise<any> {
        this.jwtToken = null;

        this.apollo.create({
            link: this.httpLink.create({uri: `${this.getAPiUrlWithProjectName()}/graphql`}),
            cache: new InMemoryCache()
        });

        return this.http.post(API_URL + 'auth/login', {
            username: this.username,
            password: this.password
        }).toPromise().then((data: any) => this.jwtToken = data.token,
            () => Promise.resolve());
    }

    /**
     * Sends a graphQL request to the CMS
     */
    graphRequest(data: any): Observable<any> {
        return this.apollo.query({
            query: data,
            context: {
                headers: {
                    Authorization: 'Bearer ' + this.jwtToken
                }
            }
        }).pipe(
            map(response => {
                return response.data;
            })
        );
    }