0

I have WordPress running in Kubernetes with horizontal autoscaling, my site uses BuddyPress to provide social-networking functionality. I also have a memcached server accessed by all the deployments of the website, and PHP session handler set as memcached with the appropriate path.

Despite this setup, which I believe should allow logged-in users to talk to any deployment without being asked to log in again, whenever the server changes the user is redirected to the login page.

Sticky sessions are not an option as I want to have autoscalability as well as the option to roll-out new deployments, which would be compromised by sticky session.

Edit: Adding PHP Info session related values

| **Directive**                     |  **Local Value**  |   **Master Value** |
| session.name                      |  PHPSESSID    |   PHPSESSID |
| session.referer_check             |  no value     |   no value |
| session.save_handler              |  memcached    |   memcached |
| session.save_path                 |  <path_tested_with_w3tc>:11211    |   <path_tested_with_w3tc>:11211 |
| session.serialize_handler         |  php  |   php |
| session.sid_bits_per_character    |  4    |   4  |
| session.sid_length                |  32   |   32 |
| session.upload_progress.cleanup   |  On   |   On |
| session.upload_progress.enabled   |  On   |   On |
| session.upload_progress.freq      |  1%   |   1% |
| session.upload_progress.min_freq  |  1    |   1  |
| session.upload_progress.name      |  PHP_SESSION_UPLOAD_PROGRESS  |   PHP_SESSION_UPLOAD_PROGRESS |
| session.upload_progress.prefix    |  upload_progress_ |   upload_progress_ |
| session.use_cookies               |  1    |   1 |
| session.use_only_cookies          |  1    |   1 |
| session.use_strict_mode           |  0    |   0 |
| session.use_trans_sid             |  0    |   0 |

Cookies generated after login:

set-cookie: wordpress_sec_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606311709%7CW9rYFhxdPDZXsn0eEAsTgQjAYUz5JS9mW3i8vZasqNY%7Cf272d224acddd83e4b5325619a84ab9c6b0a8e164bab70d02fd8d2988be5ae8a; path=/wp-content/plugins; secure; HttpOnly
set-cookie: wordpress_sec_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606311709%7CW9rYFhxdPDZXsn0eEAsTgQjAYUz5JS9mW3i8vZasqNY%7Cf272d224acddd83e4b5325619a84ab9c6b0a8e164bab70d02fd8d2988be5ae8a; path=/wp-admin; secure; HttpOnly
set-cookie: wordpress_logged_in_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606311709%7CW9rYFhxdPDZXsn0eEAsTgQjAYUz5JS9mW3i8vZasqNY%7Cc62acb99725ffe6017e887ba7f380a3658cbcc22f1194a40d70edbb409f4063f; path=/; secure; HttpOnly
set-cookie: wordpress_user_sw_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:41:49 GMT; Max-Age=0; path=/
set-cookie: wordpress_user_sw_secure_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:41:49 GMT; Max-Age=0; path=/
set-cookie: wordpress_user_sw_olduser_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:41:49 GMT; Max-Age=0; path=/
set-cookie: po_assigned_roles[0]=administrator; path=/
set-cookie: po_assigned_roles[1]=community_member; path=/
set-cookie: po_assigned_roles[2]=tpc_team_member; path=/
set-cookie: po_assigned_roles[3]=bbp_keymaster; path=/
set-cookie: po_assigned_roles[4]=collective_member; path=/

Cookies sent to NEW instance:

cookie: 
    __cfduid=d0173c09618ab13e2c6b4fb6ba43057ff1606138743; 
    dwqa_anonymous=ftswkkbhNkZwV07Xhv6uO1IdoLqLkNmIShN9OsDEzHQ; 
    Pastease.passive.chance.yJUaALuUqv6jdyG=chance6.9; 
    Pastease.passive.activated.yJUaALuUqv6jdyG=0; 
    _ga=GA1.2.2022121795.1606138752; 
    _gid=GA1.2.558054667.1606138752; 
    _fbp=fb.1.1606138752341.26687996; 
    _hjTLDTest=1; 
    _hjid=9d9690df-9108-4e17-8814-7cee6ca9a482; 
    _hjFirstSeen=1; 
    __hstc=114933784.830ff540ba6bdbe7807f9f22ababe3ea.1606138753838.1606138753838.1606138753838.1; 
    hubspotutk=830ff540ba6bdbe7807f9f22ababe3ea; 
    __hssrc=1; 
    wordpress_logged_in_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606311709%7CW9rYFhxdPDZXsn0eEAsTgQjAYUz5JS9mW3i8vZasqNY%7Cc62acb99725ffe6017e887ba7f380a3658cbcc22f1194a40d70edbb409f4063f; 
    po_assigned_roles[0]=administrator; 
    po_assigned_roles[1]=community_member; 
    po_assigned_roles[2]=tpc_team_member; 
    po_assigned_roles[3]=bbp_keymaster; 
    po_assigned_roles[4]=collective_member; 
    po_assigned_roles[5]=tpc_employee; 
    __hssc=114933784.2.1606138753838; 
    route=fea005034f6d3f0ec569ed6fc070f1a3

Full response headers from NEW instance

cache-control: s-max-age=604800, s-maxage=604800, max-age=60
cf-apo-via: origin,host
cf-cache-status: MISS
cf-edge-cache: cache,platform=wordpress
cf-ray: 5f6b613c3cfb1501-MAD
cf-request-id: 0696fb19a10000150178b9a000000001
content-encoding: br
content-type: text/html; charset=UTF-8
date: Mon, 23 Nov 2020 13:54:06 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
link: <https://gtest.portfolio-collective.com/wp-json/>; rel="https://api.w.org/", <https://gtest.portfolio-collective.com/wp-json/wp/v2/pages/644>; rel="alternate"; type="application/json", <https://gtest.portfolio-collective.com/>; rel=shortlink
nel: {"report_to":"cf-nel","max_age":604800}
referrer-policy: no-referrer-when-downgrade
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=0E3P639p9hpt6%2BSo1PdNJAhIG3P2%2Bvr8AckTijZs%2FEdTxNZzQv9UbzT6Qbx0Fv603GiFw5yUSeryKwmiRps%2FjjvU0isDb9pOBBNls4S2PVwSHcFwscqhDUGwsqiD25s%3D"}],"group":"cf-nel","max_age":604800}
server: cloudflare
strict-transport-security: max-age=15724800; includeSubDomains
vary: Accept-Encoding
x-powered-by: PHP/7.4.12
x-wp-cf-super-cache: cache
x-wp-cf-super-cache-active: 1
x-wp-cf-super-cache-cache-control: s-max-age=604800, s-maxage=604800, max-age=60

Response from NEW instance after logging in

Cookie ID and User remain the same, expiration and hash change

cache-control: private, no-cache, no-store, max-age=0, must-revalidate, proxy-revalidate
cf-cache-status: DYNAMIC
cf-edge-cache: cache,platform=wordpress
cf-ray: 5f6b61a66edc1501-MAD
cf-request-id: 0696fb5c0600001501ea1a3000000001
content-type: text/html; charset=UTF-8
date: Mon, 23 Nov 2020 13:54:20 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
expires: Fri, 01 Jan 2016 00:00:01 GMT
location: /collective/activity/
nel: {"report_to":"cf-nel","max_age":604800}
pragma: no-cache
referrer-policy: no-referrer-when-downgrade
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=7BldsEXB3EH36f6PSIrr7%2FLHpPgTmxAVVHfPsRUoSUvvRzY1%2B1n8SivJ0vFcuG5z%2FG3mpVizYrx5NP6UNJASzV6dqynFtvaP%2BYdsRih5inN4kiXedgrL%2BSXajtWFAgQ%3D"}],"group":"cf-nel","max_age":604800}
server: cloudflare
set-cookie: wordpress_sec_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606312459%7CC8XCWWQqr6b3YBGLwTuxfzrjP70NdIGAEuVHMaSNmvG%7C852115cba50a2f5d729857a9b9b0379c5e269c0f2bcd7e21c022ff0088e4a0d3; path=/wp-content/plugins; secure; HttpOnly
set-cookie: wordpress_sec_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606312459%7CC8XCWWQqr6b3YBGLwTuxfzrjP70NdIGAEuVHMaSNmvG%7C852115cba50a2f5d729857a9b9b0379c5e269c0f2bcd7e21c022ff0088e4a0d3; path=/wp-admin; secure; HttpOnly
set-cookie: wordpress_logged_in_b58b81a6569307dbe35afffdec99a12b=SECRET%7C1606312459%7CC8XCWWQqr6b3YBGLwTuxfzrjP70NdIGAEuVHMaSNmvG%7C2302e8cf7d25c4b1e6f9d5e665890e2e5b85c2e938dd3194123f374fd0f85144; path=/; secure; HttpOnly
set-cookie: wordpress_user_sw_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:54:19 GMT; Max-Age=0; path=/
set-cookie: wordpress_user_sw_secure_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:54:19 GMT; Max-Age=0; path=/
set-cookie: wordpress_user_sw_olduser_b58b81a6569307dbe35afffdec99a12b=%20; expires=Sun, 24-Nov-2019 13:54:19 GMT; Max-Age=0; path=/
set-cookie: po_assigned_roles[0]=administrator; path=/
set-cookie: po_assigned_roles[1]=community_member; path=/
set-cookie: po_assigned_roles[2]=tpc_team_member; path=/
set-cookie: po_assigned_roles[3]=bbp_keymaster; path=/
set-cookie: po_assigned_roles[4]=collective_member; path=/
set-cookie: po_assigned_roles[5]=tpc_employee; path=/
strict-transport-security: max-age=15724800; includeSubDomains
x-powered-by: PHP/7.4.12
x-redirect-by: WordPress
14
  • Are you 100% sure the memcached is used as session storage? (Read: did you debug this) If it is used, are you 100% sure no instance-related information is used in session storage/retrieval?
    – kero
    Commented Nov 23, 2020 at 12:13
  • Q: Are you sure memcached is used as session storage.. A: running phpinfo.php I can see that session.save_handler is set to memcached and that session.save_path is set to the appropriate path. Commented Nov 23, 2020 at 12:56
  • 1
    These are PHP session_start sessions? WordPress doesn't use those.
    – Rup
    Commented Nov 23, 2020 at 13:25
  • 1
    Are all of these servers configured with the same site URL? Do they all have the same *_KEY strings in wp-config? Can you compare the authentication cookies generated by different servers to see what's changed?
    – Rup
    Commented Nov 23, 2020 at 13:27
  • 1
    It's more likely that your cookies are not shared due to different domains, or that each instance has mismatched keys in wp-config.php ( they must match ), PHP sessions are a complete red herring
    – Tom J Nowell
    Commented Nov 23, 2020 at 15:16

1 Answer 1

3

The problem was that my *_KEY tokens were being generated each time Kubernetes was creating a new instance, as @Rup and @Tom-J-Nowel rightly pointed.

Because my docker image evolved from having an wp-config.php template included to having it generated by the official wordpress docker image I was struggling to see this was a variable. After double-checking following the advice I was given I realised it was indeed different in each instance.

Therefore, the solution was as simple as making sure that the values of the following variables were the same in all the instances:

define( 'AUTH_KEY',         '<auth_key_token>');
define( 'SECURE_AUTH_KEY',  '<secure_auth_key_token>');
define( 'LOGGED_IN_KEY',    '<logged_in_key_token>');
define( 'NONCE_KEY',        '<nonce_key_token>');
define( 'AUTH_SALT',        '<auth_salt_token>');
define( 'SECURE_AUTH_SALT', '<secure_auth_salt_token>');
define( 'LOGGED_IN_SALT',   '<logged_in_salt_token>');
define( 'NONCE_SALT',       '<nonce_salt_token>');

Which in my kubernetes object looked something like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: k8s-web
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8s-web
  template:
    metadata:
      labels:
        app: k8s-web
    spec:
      containers:
        - image: wordpress:php7.4-apache
          name: web-container
          env:
            - name: WORDPRESS_DB_HOST
              value: <wordpress_db_host>
            - name: WORDPRESS_DB_NAME
              value: <wordpress_db_name>
            - name: WORDPRESS_DB_USER
              value: <wordpress_db_user>
            - name: WORDPRESS_DB_PASSWORD
              value: <wordpress_db_password>
            - name: WORDPRESS_TABLE_PREFIX
              value: <wordpress_table_prefix>
            - name: WORDPRESS_AUTH_KEY
              value: <wordpress_auth_key>
            - name: WORDPRESS_AUTH_SALT
              value: <wordpress_auth_salt>
            - name: WORDPRESS_SECURE_AUTH_KEY
              value: <wordpress_secure_auth_key>
            - name: WORDPRESS_SECURE_AUTH_SALT
              value: <wordpress_secure_auth_salt>
            - name: WORDPRESS_LOGGED_IN_KEY
              value: <wordpress_logged_in_key>
            - name: WORDPRESS_LOGGED_IN_SALT
              value: <wordpress_logged_in_salt>
            - name: WORDPRESS_NONCE_KEY
              value: <wordpress_nonce_key>
            - name: WORDPRESS_NONCE_SALT
              value: <wordpress_nonce_salt>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.