@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix content: <http://purl.org/rss/1.0/modules/content/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<https://lhero.org/portfolio/lh-membership/>
  a sioc:Post ;
  dc:title "Single sign-on" ;
  dcterms:identifier 149638 ;
  dc:modified "2026-10-10T16:07:00Z"^^xsd:dateTime ;
  dc:created "2026-10-10T16:07:00Z"^^xsd:dateTime ;
  sioc:link <https://lhero.org/portfolio/lh-membership/single-sign-on/> ;
  sioc:has_creator <https://lhero.org/author/1/#account> ;
  sioc:has_container <https://lhero.org/#posts> ;
  content:encoded """<ul class="lh_portfolio-meta"><li><strong>Part of:</strong> <a href="https://lhero.org/portfolio/lh-membership/">LH Membership</a></li></ul>
<p class="wp-block-paragraph">Signing in once logs a member in across every site on the network. The main site holds the session; subsites borrow it rather than creating sessions of their own.</p>



<h2 class="wp-block-heading">How it works</h2>



<ul class="wp-block-list">
<li><strong>Logged-out visit to a subsite.</strong> A script sends the browser to the main site with <code>lh_membership-sso_return</code>. If the browser has a main-site session, the main site issues a short-lived signed token carrying the user ID, that session&#8217;s token and the return URL, and redirects back.</li>



<li><strong>Callback on the subsite.</strong> The subsite checks the token&#8217;s HMAC signature and expiry, confirms the session token is still valid with <code>WP_Session_Tokens::verify()</code>, and sets its own auth cookies on that same session. It then fires <code>wp_login</code> once, so login actions such as role upgrades and audit logging run.</li>



<li><strong>Login on a subsite.</strong> A normal login on a subsite is synced the other way: the login redirect is routed through the main site with a token, so the main site gets the session too.</li>
</ul>



<p class="wp-block-paragraph">All three endpoints run on <code>template_redirect</code>, so cookies are set in a normal request. The token lifetime defaults to 60 seconds, filterable with <code>lh_membership_sso_token_ttl</code>.</p>



<h2 class="wp-block-heading">Two Factor</h2>



<p class="wp-block-paragraph">When the Two Factor plugin is active, its <code>wp_login</code> handler is removed while the SSO callback fires <code>wp_login</code>, then restored. The session being transferred was created on the main site and has already passed any second factor there, so the subsite does not challenge again. Every real login, on any site, is still challenged as usual. (Since 2.91.6.)</p>
"""^^rdf:XMLLiteral ;
  sioc:content """Part of: LH Membership
Signing in once logs a member in across every site on the network. The main site holds the session; subsites borrow it rather than creating sessions of their own.



How it works




Logged-out visit to a subsite. A script sends the browser to the main site with lh_membership-sso_return. If the browser has a main-site session, the main site issues a short-lived signed token carrying the user ID, that session&#8217;s token and the return URL, and redirects back.



Callback on the subsite. The subsite checks the token&#8217;s HMAC signature and expiry, confirms the session token is still valid with WP_Session_Tokens::verify(), and sets its own auth cookies on that same session. It then fires wp_login once, so login actions such as role upgrades and audit logging run.



Login on a subsite. A normal login on a subsite is synced the other way: the login redirect is routed through the main site with a token, so the main site gets the session too.




All three endpoints run on template_redirect, so cookies are set in a normal request. The token lifetime defaults to 60 seconds, filterable with lh_membership_sso_token_ttl.



Two Factor



When the Two Factor plugin is active, its wp_login handler is removed while the SSO callback fires wp_login, then restored. The session being transferred was created on the main site and has already passed any second factor there, so the subsite does not challenge again. Every real login, on any site, is still challenged as usual. (Since 2.91.6.)
""" ;
  sioc:topic <https://lhero.org/?taxonomy=author&term=cap-1> .

<https://lhero.org/author/1/#account> rdfs:seeAlso <https://lhero.org/author/1/?feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=author&term=cap-1> rdfs:seeAlso <https://lhero.org/?taxonomy=author&term=cap-1&feed=lhrdf&format=turtle> .
