motiv-labs / janus

An API Gateway written in Go
https://hellofresh.gitbooks.io/janus
MIT License
2.77k stars 319 forks source link

CORS and OAUTH2 plugin doesn't return access control headers on OPTIONS method #484

Closed MadalinNitu closed 1 year ago

MadalinNitu commented 1 year ago

Hello,

I tried to use janus to secure an endpoint using my own oauth server. The auth2 server works as expected from Postman. Ask me for Authorization header but now I try to integrate in a frontend application and I get error.

My endpoint config:

{ "name" : "auth-covers", "active" : true, "proxy" : { "preserve_host" : false, "listen_path" : "/Books/", "upstreams" : { "balancing": "roundrobin", "targets": [ {"target": "http://10.10.6.4/"} ] }, "strip_path" : false, "append_path" : true, "methods" : ["GET", "OPTIONS"] }, "health_check": { "url": "http://10.10.6.4/", "timeout": 3 }, "plugins": [ { "name": "cors", "enabled" : true, "config": { "domains": [""], "methods": ["GET"], "options_passthrough": true } }, { "name": "oauth2", "enabled" : true, "config": { "server_name": "local" } } ] }

And the request capture:

OPTIONS https://api.example.com/Books/example.jpg HTTP/1.1 Accept: / Access-Control-Request-Method: GET Access-Control-Request-Headers: authorization Origin: https://app.example.com User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36 Sec-Fetch-Mode: cors Sec-Fetch-Site: same-site Sec-Fetch-Dest: empty Referer: https://app.example.com/ Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9,ro;q=0.8,it;q=0.7,fr;q=0.6,la;q=0.5

HTTP/1.1 400 date: Tue, 02 Aug 2022 12:22:24 GMT content-type: application/json content-length: 40 vary: Origin vary: Access-Control-Request-Method vary: Access-Control-Request-Headers x-request-id: ee1747a6-a82b-4680-8779-0335cea3ba86 strict-transport-security: max-age=31536000 cf-cache-status: DYNAMIC expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct" report-to: {"endpoints":[{"url":""}],"group":"cf-nel","max_age":604800} nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800} server: cloudflare cf-ray: 7346c761b827927f-FRA alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400

And the log from janus:

{"level":"debug","msg":"Starting Stats middleware","path":"/Books/example.jpg ","time":"2022-08-02T12:22:24Z"} {"level":"debug","method":"OPTIONS","msg":"Started request","path":"/Books/example.jpg ","time":"2022-08-02T12:22:24Z"} {"level":"debug","msg":"Starting Oauth2KeyExists middleware","time":"2022-08-02T12:22:24Z"} {"level":"warning","msg":"Attempted access with malformed header, no auth header found.","origin":"172.18.0.3:32776","path":"/Books/example.jpg ","time":"2022-08-02T12:22:24Z"} [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=tokens.key-exists.header.- [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=tokens-fail.key-exists.header.- [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.tokens [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.tokens-fail {"code":400,"error":"authorization field missing","level":"info","msg":"Internal error handled","request-id":"ee1747a6-a82b-4680-8779-0335cea3ba86","time":"2022-08-02T12:22:24Z"} {"code":400,"duration":0,"duration-fmt":"163.238µs","host":"api.example.com","level":"info","method":"OPTIONS","msg":"Completed handling request","referer":"https://app.example.com/","remote-addr":"172.18.0.3:32776","request":"/Books/example.jpg ","request-id":"ee1747a6-a82b-4680-8779-0335cea3ba86","time":"2022-08-02T12:22:24Z","user-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"} [StatsGo] 2022/08/02 12:22:24 Stats timer finished bucket=request.options.Books.IT elapsed=227.028µs [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=request.options.Books.IT [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=request-fail.options.Books.IT [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.request [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.request-fail [StatsGo] 2022/08/02 12:22:24 Stats timer finished bucket=round.options.Books.IT elapsed=227.028µs [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=round.options.Books.IT [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=round-ok.options.Books.IT [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.round [StatsGo] 2022/08/02 12:22:24 Stats counter incremented metric=total.round-ok

I think is a miss-configuration but I don't figure out what.

Many thanks.

MadalinNitu commented 1 year ago

I think the problem is that I use both cors and oauth plugins. Becouse the OPTIONS method have to presint the Authorization header. How can I skip/bypass in oauth this method?