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=";
link: </>; rel="/", <;; rel="alternate"; type="application/json", </>; rel=shortlink
nel: {"report_to":"cf-nel","max_age":604800}
referrer-policy: no-referrer-when-downgrade
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare\/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=";
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\/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
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
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>
session.save_handler
is set tomemcached
and thatsession.save_path
is set to the appropriate path. – Jesus Iniesta Commented Nov 23, 2020 at 12:56wp-config.php
( they must match ), PHP sessions are a complete red herring – Tom J Nowell ♦ Commented Nov 23, 2020 at 15:16