ory/oathkeeper

Duplicate requests using decisions endpoint via NGINX

karlis-vagalis opened this issue · 0 comments

Preflight checklist

Ory Network Project

No response

Describe the bug

I am facing an issue using Oathkeeper's Access Control Decision API.

It is being used as for Nginx via Authentication Based on Subrequest Result. Most of the logic works well and correctly, user is being redirected to the authentication page (based on the rule), can log in, is redirected back to the page, but then the issue starts. For example, requesting test.mydomain.com should check authentication from Ory Kratos (v1.1.0) or redirect to auth page at auth.mydomain.com and then allow accessing the site.

As Oathkeepers logs indicate, for whatever reason the /decisions request seems to be duplicated. The first request indicates, that the access to the url is granted (200, OK), but afterwards (no idea why), follows a send request with same headers, but that one is being responded with 404, Not Found, even though the URI is same. I thought I made an error in my rule definition, but why would the next request fail then, if the first did match?

The configuration files are attached below.

Config files

Oathkeeper Rules

rules.yml :

- id: "mydomain:subdomains:private"
  match:
    url: "<http|https>://<[^.]+>.mydomain.com<(.*)?>"
    methods:
      - GET
      - POST
      - PUT
      - DELETE
      - PATCH
  authenticators:
    - handler: cookie_session
  authorizer:
    handler: allow
  mutators:
    - handler: noop

NGINX

server {

    listen 443 ssl http2 proxy_protocol;
    listen [::]:443 ssl http2 proxy_protocol;

    server_name test.mydomain.com;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    include /config/nginx/ory-server.conf;

    location / {
        
        include /config/nginx/ory-location.conf;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app test;
        set $upstream_port 80;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    }
}

ory-server.conf:

# Location for Ory Oathkeeper authentication requests
location = /decisions {
    internal;

    include /config/nginx/proxy.conf;
    include /config/nginx/resolver.conf;

    set $upstream_proto http;
    set $upstream_app oathkeeper;
    set $upstream_port 4456;

    proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    ## Include the Set-Cookie header if present
    auth_request_set $set_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $set_cookie;

    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
}

# Virtual location for Ory Oathkeeper authentication redirects
location @ory_proxy_signin {
    internal;

    ## Include the Set-Cookie header if present
    auth_request_set $set_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $set_cookie;

    ## Set the $target_url variable based on the original request
    set_escape_uri $target_url $scheme://$http_host$request_uri;

    ## Translate the Location response header from the auth subrequest into a variable
    auth_request_set $signin_url $upstream_http_location;

    if ($signin_url = '') {
        ## Set the $signin_url variable
        set $signin_url https://auth.mydomain.com/login?return_to=$target_url;
    }

    ## Redirect to login
    return 302 $signin_url;
}

ory-location.conf:

auth_request /decisions;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal
error_page 401 = @ory_proxy_signin;

# ## Translate the user information response headers from the auth subrequest into variables
auth_request_set $email $upstream_http_remote_email;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $user $upstream_http_remote_user;

## Inject the user information into the request made to the actual upstream
proxy_set_header Remote-Email $email;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-User $user;

## Translate the Set-Cookie response header from the auth subrequest into a variable
auth_request_set $set_cookie $upstream_http_set_cookie;

## Translate the Location response header from the auth subrequest into a variable
auth_request_set $signin_url $upstream_http_location;

Reproducing the bug

  1. Have valid and working Ory Kratos instance.
  2. Start Oathkeeper with described configuration and rules
  3. Set up NGINX reverse proxy to use Ory Oathkeeper for auth_request to access server.
  4. Try to access server.

Relevant log output

{"handling":"","level":"info","msg":"started","request":"","time":"2024-03-27T09:24:04Z"}
time=2024-03-27T09:24:04Z level=info msg=Access request granted audience=application granted=true http_host=test.mydomain.com http_method=GET http_url=https://test.mydomain.com/ http_user_agent=Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 service_name=ORY Oathkeeper service_version=v0.40.7
{"handling":"","level":"info","msg":"completed","request":"","time":"2024-03-27T09:24:04Z"}
{"handling":"","level":"info","msg":"started","request":"","time":"2024-03-27T09:24:04Z"}
{"handling":"","level":"info","msg":"completed","request":"","time":"2024-03-27T09:24:04Z"}
time=2024-03-27T09:24:04Z level=info msg=started handling request http_request=map[headers:map[accept:image/avif,image/webp,*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 cache-control:no-cache connection:close cookie:[ory_kratos_session=MTcxMTUyOTQxNnx6Q0xpYnRYbE9jakxkM05LLWVMYS02Q1N5bnBnR1hZQmR3VTFRMTJaMWZneVZUR0hCU2RKa2VEaU5GZkJ5dWZJRkhPdGNKbmgwN3VDY0h2d0tDT3ZGUmhwWkFfMGlaRkVEdkNIVWhubmo5WHo5V0diSGJYdmZvd3RrUFRoVFIwNkNETGlfRHJmaE5mMWRVT283SFpGSlBGQ1pFYnVIN0FiSnpISnFiaHlUaHVKR0FjZkVGV0dQRkdRQU5zOUxocUxUMnZzbWRYOFB3a3gzSkJoUjJNbzR6QVJHa21uTjdDemktaWF5azhHME80Rm1qdDRiOFdrdU84Wi1GVmg1WVdnQmZnckVIRy02eWlZTW1TekxnQ2t8Y_TSiwcfeY5FN5_mi6wPFZqxjdXBlTzL2DyL5_Ot9gc=] dnt:1 pragma:no-cache referer:https://test.mydomain.com/ sec-fetch-dest:image sec-fetch-mode:no-cors sec-fetch-site:same-origin sec-gpc:1 user-agent:Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 x-forwarded-for:192.168.2.26 x-forwarded-host:test.mydomain.com x-forwarded-method:GET x-forwarded-port:443 x-forwarded-proto:https x-forwarded-server:test.mydomain.com x-forwarded-ssl:on x-forwarded-uri:/favicon.ico x-original-method:GET x-original-url:https://test.mydomain.com/favicon.ico x-real-ip:192.168.2.26] host:test.mydomain.com method:GET path:/decisions query:<nil> remote:[fd00:2::10]:56798 scheme:http]
time=2024-03-27T09:24:04Z level=info msg=Access request granted audience=application granted=true http_host=test.mydomain.com http_method=GET http_url=https://test.mydomain.com/favicon.ico http_user_agent=Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 service_name=ORY Oathkeeper service_version=v0.40.7
time=2024-03-27T09:24:04Z level=info msg=completed handling request http_request=map[headers:map[accept:image/avif,image/webp,*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 cache-control:no-cache connection:close cookie:[ory_kratos_session=MTcxMTUyOTQxNnx6Q0xpYnRYbE9jakxkM05LLWVMYS02Q1N5bnBnR1hZQmR3VTFRMTJaMWZneVZUR0hCU2RKa2VEaU5GZkJ5dWZJRkhPdGNKbmgwN3VDY0h2d0tDT3ZGUmhwWkFfMGlaRkVEdkNIVWhubmo5WHo5V0diSGJYdmZvd3RrUFRoVFIwNkNETGlfRHJmaE5mMWRVT283SFpGSlBGQ1pFYnVIN0FiSnpISnFiaHlUaHVKR0FjZkVGV0dQRkdRQU5zOUxocUxUMnZzbWRYOFB3a3gzSkJoUjJNbzR6QVJHa21uTjdDemktaWF5azhHME80Rm1qdDRiOFdrdU84Wi1GVmg1WVdnQmZnckVIRy02eWlZTW1TekxnQ2t8Y_TSiwcfeY5FN5_mi6wPFZqxjdXBlTzL2DyL5_Ot9gc=] dnt:1 pragma:no-cache referer:https://test.mydomain.com/ sec-fetch-dest:image sec-fetch-mode:no-cors sec-fetch-site:same-origin sec-gpc:1 user-agent:Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 x-forwarded-for:192.168.2.26 x-forwarded-host:test.mydomain.com x-forwarded-method:GET x-forwarded-port:443 x-forwarded-proto:https x-forwarded-server:test.mydomain.com x-forwarded-ssl:on x-forwarded-uri:/favicon.ico x-original-method:GET x-original-url:https://test.mydomain.com/favicon.ico x-real-ip:192.168.2.26] host:test.mydomain.com method:GET path:/favicon.ico query:<nil> remote:[fd00:2::10]:56798 scheme:http] http_response=map[headers:map[accept:image/avif,image/webp,*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 cache-control:no-cache connection:close cookie:[ory_kratos_session=MTcxMTUyOTQxNnx6Q0xpYnRYbE9jakxkM05LLWVMYS02Q1N5bnBnR1hZQmR3VTFRMTJaMWZneVZUR0hCU2RKa2VEaU5GZkJ5dWZJRkhPdGNKbmgwN3VDY0h2d0tDT3ZGUmhwWkFfMGlaRkVEdkNIVWhubmo5WHo5V0diSGJYdmZvd3RrUFRoVFIwNkNETGlfRHJmaE5mMWRVT283SFpGSlBGQ1pFYnVIN0FiSnpISnFiaHlUaHVKR0FjZkVGV0dQRkdRQU5zOUxocUxUMnZzbWRYOFB3a3gzSkJoUjJNbzR6QVJHa21uTjdDemktaWF5azhHME80Rm1qdDRiOFdrdU84Wi1GVmg1WVdnQmZnckVIRy02eWlZTW1TekxnQ2t8Y_TSiwcfeY5FN5_mi6wPFZqxjdXBlTzL2DyL5_Ot9gc=] dnt:1 pragma:no-cache referer:https://test.mydomain.com/ sec-fetch-dest:image sec-fetch-mode:no-cors sec-fetch-site:same-origin sec-gpc:1 user-agent:Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 x-forwarded-for:192.168.2.26 x-forwarded-host:test.mydomain.com x-forwarded-method:GET x-forwarded-port:443 x-forwarded-proto:https x-forwarded-server:test.mydomain.com x-forwarded-ssl:on x-forwarded-uri:/favicon.ico x-original-method:GET x-original-url:https://test.mydomain.com/favicon.ico x-real-ip:192.168.2.26] size:0 status:200 text_status:OK took:2.55136ms]
time=2024-03-27T09:24:04Z level=info msg=started handling request http_request=map[headers:map[accept:image/avif,image/webp,*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 cache-control:no-cache connection:close cookie:[ory_kratos_session=MTcxMTUyOTQxNnx6Q0xpYnRYbE9jakxkM05LLWVMYS02Q1N5bnBnR1hZQmR3VTFRMTJaMWZneVZUR0hCU2RKa2VEaU5GZkJ5dWZJRkhPdGNKbmgwN3VDY0h2d0tDT3ZGUmhwWkFfMGlaRkVEdkNIVWhubmo5WHo5V0diSGJYdmZvd3RrUFRoVFIwNkNETGlfRHJmaE5mMWRVT283SFpGSlBGQ1pFYnVIN0FiSnpISnFiaHlUaHVKR0FjZkVGV0dQRkdRQU5zOUxocUxUMnZzbWRYOFB3a3gzSkJoUjJNbzR6QVJHa21uTjdDemktaWF5azhHME80Rm1qdDRiOFdrdU84Wi1GVmg1WVdnQmZnckVIRy02eWlZTW1TekxnQ2t8Y_TSiwcfeY5FN5_mi6wPFZqxjdXBlTzL2DyL5_Ot9gc=] dnt:1 pragma:no-cache referer:https://test.mydomain.com/ sec-fetch-dest:image sec-fetch-mode:no-cors sec-fetch-site:same-origin sec-gpc:1 user-agent:Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 x-forwarded-for:192.168.2.26 x-forwarded-host:test.mydomain.com x-forwarded-method:GET x-forwarded-port:443 x-forwarded-proto:https x-forwarded-server:test.mydomain.com x-forwarded-ssl:on x-forwarded-uri:/favicon.ico x-original-method:GET x-original-url:https://test.mydomain.com/favicon.ico x-real-ip:192.168.2.26] host:test.mydomain.com method:GET path:/favicon.ico query:<nil> remote:[fd00:2::10]:56804 scheme:http]
time=2024-03-27T09:24:04Z level=info msg=completed handling request http_request=map[headers:map[accept:image/avif,image/webp,*/* accept-encoding:gzip, deflate, br accept-language:en-US,en;q=0.5 cache-control:no-cache connection:close cookie:[ory_kratos_session=MTcxMTUyOTQxNnx6Q0xpYnRYbE9jakxkM05LLWVMYS02Q1N5bnBnR1hZQmR3VTFRMTJaMWZneVZUR0hCU2RKa2VEaU5GZkJ5dWZJRkhPdGNKbmgwN3VDY0h2d0tDT3ZGUmhwWkFfMGlaRkVEdkNIVWhubmo5WHo5V0diSGJYdmZvd3RrUFRoVFIwNkNETGlfRHJmaE5mMWRVT283SFpGSlBGQ1pFYnVIN0FiSnpISnFiaHlUaHVKR0FjZkVGV0dQRkdRQU5zOUxocUxUMnZzbWRYOFB3a3gzSkJoUjJNbzR6QVJHa21uTjdDemktaWF5azhHME80Rm1qdDRiOFdrdU84Wi1GVmg1WVdnQmZnckVIRy02eWlZTW1TekxnQ2t8Y_TSiwcfeY5FN5_mi6wPFZqxjdXBlTzL2DyL5_Ot9gc=] dnt:1 pragma:no-cache referer:https://test.mydomain.com/ sec-fetch-dest:image sec-fetch-mode:no-cors sec-fetch-site:same-origin sec-gpc:1 user-agent:Mozilla/5.0 (X11; Linux x86_64; rv:124.0) Gecko/20100101 Firefox/124.0 x-forwarded-for:192.168.2.26 x-forwarded-host:test.mydomain.com x-forwarded-method:GET x-forwarded-port:443 x-forwarded-proto:https x-forwarded-server:test.mydomain.com x-forwarded-ssl:on x-forwarded-uri:/favicon.ico x-original-method:GET x-original-url:https://test.mydomain.com/favicon.ico x-real-ip:192.168.2.26] host:test.mydomain.com method:GET path:/favicon.ico query:<nil> remote:[fd00:2::10]:56804 scheme:http] http_response=map[headers:map[content-type:text/html; charset=utf-8] size:1168 status:404 text_status:Not Found took:180.073µs]

Relevant configuration

authenticators:
  cookie_session:
    enabled: true
    config:
      check_session_url: http://kratos:4433/sessions/whoami
      preserve_path: true
      extra_from: "@this"
      subject_from: "identity.id"
      only:
        - ory_kratos_session

authorizers:
  allow:
    enabled: true

mutators:
  noop:
    enabled: true

access_rules:
  matching_strategy: regexp
  repositories:
    - file:///home/ory/rules.yml

log:
  level: trace
  leak_sensitive_values: true

Version

v0.40.7

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Docker Compose

Additional Context

No response