zmartzone / lua-resty-openidc

OpenID Connect Relying Party and OAuth 2.0 Resource Server implementation in Lua for NGINX / OpenResty
Apache License 2.0
976 stars 249 forks source link

Various cookie renew issues with redis session provider #446

Open mateodelnorte opened 2 years ago

mateodelnorte commented 2 years ago

Thanks for putting together this library. It's very close to getting us across the finish line, but we are running into recurring issues.

We are seeing various issues with the redis session provider, specifically on cookie expiry. We see the following various error messages as 500's instead of our site content:

  1. EVP_DecryptFinal_ex failed
    api-gateway_1  | 2022/08/15 15:18:06 [alert] 10#10: *392 ignoring stale global SSL error (SSL: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt), client: 192.168.48.1, server: localhost, request: "GET /auth-adfs?code=AAAAAAAAAAAAAAAAAAAAAA.qJhkWtF-2ghIUvALtyVYiB2aYkY.P5Cj-Q14JTx7D5Nxr6_IapWXqiZuPGUHtdFGbxTf-ZDJGUrAN6DM3CG1QibT9q67P6zvqkzBzw003IInWJTxkgzHU0f9-Tk78mIooR6yqhDELL6DsVi21rtW6OxxW8b8hZwEp2EMN-ZOYPAvsFrojRXP_S9nlOmnosJfrbc2FkV3eZmjcLOQABvExhAmmfefUYOazSPYrPpLbw6-Q3efWeGpltwAZ-IthgwNry6aW47q0wfAPslisdtkOU0o2CKnRIsMK3SpTOeYYi_Jt-U3qaXkvG7XQQZmNVQzCSiw9WmI63Fo_t3hNFQLVLgBD1g6yABgcWMZsM5xSBX1r3AoAQ&state=8ca375da8e7f0ecb26afa1a7971c50e9 HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
  2. session cookie expired
  3. Cookie has invalid signature
  4. I'm also sometimes seeing an issue where, after cookie expiry, all requests are getting Set-Cookie instead of using the cookie provided by the parent request

image

Environment
Expected behaviour

Various cookie and session renewal issues

Actual behaviour

Automatic session and token renewal via the openid flow.

Minimized example

Minimal, complete configuration that reproduces the behavior.

Configuration and NGINX server log files
worker_processes 1;

error_log /dev/stdout $NGINX_ERROR_LOG_LEVEL;
pid       /usr/local/openresty/nginx/logs/nginx.pid;

env ADFS_AUTH_OPENID_CLIENT_ID;
env ADFS_AUTH_OPENID_CLIENT_SECRET;
env ADFS_AUTH_OPENID_DISCOVERY;
env ADFS_AUTH_OPENID_REDIRECT_URL;
env ADFS_AUTH_OPENID_REDIRECT_URI_PATH;
env ADFS_AUTH_OPENID_REDIRECT_URI_SCHEME;
env ADFS_AUTH_OPENID_RESOURCE;
env ADFS_AUTH_OPENID_SCOPE;
env ADFS_AUTH_OPENID_TTL;
env ADFS_AUTH_URL;

events {
    worker_connections 1024;
}

http {
    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;
    ssl_ciphers ALL:!kEDH!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;

    resolver $NGINX_HTTP_RESOLVER;

    lua_package_path '/usr/local/openresty/luajit/share/lua/5.1/nginx/?.lua;/usr/local/openresty/luajit/share/lua/5.1/resty/?.lua;;';

    lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
    lua_ssl_verify_depth 2;

    # cache for sessions
    lua_shared_dict sessions 10m;
    # cache for discovery metadata documents
    lua_shared_dict discovery 5m;
    # cache for JWKs
    lua_shared_dict jwks 5m;

    default_type  application/octet-stream;

    client_header_buffer_size 64k;
    large_client_header_buffers 4 64k;

    proxy_read_timeout 300;
    proxy_connect_timeout 300;
    proxy_send_timeout 300;

    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  /dev/stdout  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_requests 1000;
    keepalive_timeout  65;

    gzip  on;

    include /etc/nginx/conf.d/*.conf;
}
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=STATIC:10m inactive=7d use_temp_path=off;

server {
  set $session_storage redis;

  set $session_redis_host $REDIS_HOST;
  set $session_redis_password $PASSWORD;
  set $session_redis_port $REDIS_PORT;

  set $session_check_ssi on;
  set $session_cookie_httponly on;
  set $session_cookie_persistent on;
  set $session_cookie_samesite Lax;
  set $session_cookie_secure on;
  set $session_secret $SESSION_SECRET;
  set $session_cookie_lifetime 86400;

  default_type text/html;

  access_log $ACCESS_LOG;

  gzip on;
  gzip_comp_level 4;
  gzip_proxied any;
  gzip_types text/css application/javascript image/svg+xml;

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

  listen $APPLICATION_PORT;
  server_name localhost;

  root /etc/nginx;

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

  rewrite_log on;

  location /health {
    return 200;
  }

  location /analytics {
    return 302 /analytics/;
  }

  location /analytics/ {
    if ($args ~ ^(.*)idsite=MATOMO_SITE_ID(.*)$) {
      set $args $1idsite=$MATOMO_SITE_ID$2;
    }

    access_by_lua_file ensure-authorized.lua;
    proxy_http_version 1.1;
    proxy_pass $MATOMO_PROTOCOL://$MATOMO_HOST:$MATOMO_PORT/;
    proxy_pass_request_headers      on;
    proxy_redirect off;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Upgrade $http_upgrade;
  }

  location /graphql {
    if ($request_method = OPTIONS ) {
      add_header "Access-Control-Allow-Origin"  * always;
      add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD";
      add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
      add_header 'Content-Type' 'text/plain charset=UTF-8';
      add_header 'Content-Length' 0;
      return 204;
    }
    access_by_lua_file ensure-authorized.lua;
    proxy_http_version 1.1;
    proxy_pass $GRAPHQL_PROTOCOL://$GRAPHQL_HOST:$GRAPHQL_PORT/graphql;
    proxy_pass_request_headers      on;
    proxy_redirect off;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Upgrade $http_upgrade;
  }

  location /login {
    try_files $uri /login.html;
  }

  location / {
    if ($request_method = OPTIONS ) {
      add_header "Access-Control-Allow-Origin"  * always;
      add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD";
      add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
      add_header 'Content-Type' 'text/plain charset=UTF-8';
      add_header 'Content-Length' 0;
      return 204;
    }
    access_by_lua_file ensure-authorized.lua;
    proxy_http_version 1.1;
    proxy_pass $SERVER_PROTOCOL://$SERVER_HOST:$SERVER_PORT;
    proxy_pass_request_headers      on;
    proxy_redirect off;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Upgrade $http_upgrade;
  }

}
pankgeorg commented 2 years ago

We too have very similar issues. I would try changing set $session_check_ssi on;, to off, see https://github.com/bungle/lua-resty-session#nginx-configuration-variables. ~And probably use some locking.~ And the regenerate strategy (without locking).