From c9661d5e4f0d60b908ef0d4d1e1b761064982ce2 Mon Sep 17 00:00:00 2001 From: John Wang Date: Mon, 2 Nov 2026 07:20:35 -0800 Subject: [PATCH 1/4] fix(auth): end the SystemAuth login session after signing out Signing out ended the app's session but left SystemAuth's login session, so the next sign-in resumed it and the person was signed straight back in. signOut and logout now ask the BFF for JSON and, when it names SystemAuth's sign-out page, submit a form there with return_to, so SystemAuth ends its login session and returns the browser signed out. SessionProvider and AuthProvider take endSession to change this, or null to stay on the page; readSignOut and endLoginSession are exported. Co-Authored-By: Claude Opus 5.5 --- packages/auth/src/AuthProvider.tsx | 10 +++- packages/auth/src/bff-client.ts | 7 ++- packages/auth/src/index.ts | 2 + packages/auth/src/session/SessionProvider.tsx | 17 +++++- packages/auth/src/session/client.ts | 12 ++++- packages/auth/src/signout.ts | 54 +++++++++++++++++++ packages/auth/src/types.ts | 9 ++++ 7 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 packages/auth/src/signout.ts diff --git a/packages/auth/src/AuthProvider.tsx b/packages/auth/src/AuthProvider.tsx index d04b8d4..afaad4f 100644 --- a/packages/auth/src/AuthProvider.tsx +++ b/packages/auth/src/AuthProvider.tsx @@ -1,3 +1,4 @@ +import { endLoginSession } from './signout'; import { createContext, useContext, @@ -57,6 +58,7 @@ export function AuthProvider({ onSessionExpired, onAuthError, checkInterval = 60000, + endSession = endLoginSession, }: AuthProviderProps) { // loginUrl and defaultRedirect are stored in config for other components void _loginUrl; @@ -181,9 +183,13 @@ export function AuthProvider({ const logout = useCallback(async () => { setIsLoading(true); try { - await client.logout(); + const next = await client.logout(); setUser(null); setError(null); + if (next && endSession) { + // SystemAuth ends its login session too, then returns here signed out. + endSession(next); + } } catch (err) { // Even if logout fails on server, clear local state setUser(null); @@ -191,7 +197,7 @@ export function AuthProvider({ } finally { setIsLoading(false); } - }, [client, handleError]); + }, [client, handleError, endSession]); /** * Refresh user data diff --git a/packages/auth/src/bff-client.ts b/packages/auth/src/bff-client.ts index 02c7cf7..da7193b 100644 --- a/packages/auth/src/bff-client.ts +++ b/packages/auth/src/bff-client.ts @@ -1,3 +1,4 @@ +import { readSignOut, type SystemAuthSignOut } from './signout'; import type { User, SessionStatus, @@ -88,10 +89,12 @@ export class BFFClient { /** * Logout current session */ - async logout(): Promise { - await this.request('/bff/auth/logout', { + async logout(): Promise { + const body = await this.request('/bff/auth/logout', { method: 'POST', + headers: { Accept: 'application/json' }, }); + return readSignOut(body); } /** diff --git a/packages/auth/src/index.ts b/packages/auth/src/index.ts index 8b44bfc..4b1b85d 100644 --- a/packages/auth/src/index.ts +++ b/packages/auth/src/index.ts @@ -45,6 +45,8 @@ export * from './session'; // BFF client (for advanced use cases) export { BFFClient, defaultBFFClient } from './bff-client'; +export { endLoginSession, readSignOut } from './signout'; +export type { SystemAuthSignOut } from './signout'; // Types export type { diff --git a/packages/auth/src/session/SessionProvider.tsx b/packages/auth/src/session/SessionProvider.tsx index 26cee0f..15516d4 100644 --- a/packages/auth/src/session/SessionProvider.tsx +++ b/packages/auth/src/session/SessionProvider.tsx @@ -8,6 +8,7 @@ import { useState, type ReactNode, } from 'react'; +import { endLoginSession, type SystemAuthSignOut } from '../signout'; import { SessionClient, type SignInOptions } from './client'; import type { Session } from './types'; @@ -42,6 +43,12 @@ export interface SessionProviderProps { onUnauthorized?: () => void; /** Navigation for sign-in, for tests. Default `window.location.assign`. */ navigate?: (url: string) => void; + /** + * Ends SystemAuth's login session after the app's sign-out, when the BFF + * names its sign-out page. Default: a form POST there, which navigates + * away; `null` stays on the page, signed out of the app only. + */ + endSession?: ((target: SystemAuthSignOut) => void) | null; } const SessionContext = createContext(null); @@ -59,6 +66,7 @@ export function SessionProvider({ refreshOnFocus = true, onUnauthorized, navigate, + endSession = endLoginSession, }: SessionProviderProps) { const bff = useMemo(() => client ?? new SessionClient(), [client]); const [status, setStatus] = useState('loading'); @@ -111,11 +119,16 @@ export function SessionProvider({ ); const signOut = useCallback(async () => { - await bff.signOut(); + const next = await bff.signOut(); // Signing out on purpose is not an unauthorized surprise. wasAuthenticated.current = false; + if (next && endSession) { + // SystemAuth ends its login session too, then returns here signed out. + endSession(next); + return; + } await refresh(); - }, [bff, refresh]); + }, [bff, refresh, endSession]); const value = useMemo( () => ({ status, session, error, refresh, signIn, signOut }), diff --git a/packages/auth/src/session/client.ts b/packages/auth/src/session/client.ts index 36461c7..bdd480f 100644 --- a/packages/auth/src/session/client.ts +++ b/packages/auth/src/session/client.ts @@ -1,3 +1,4 @@ +import { readSignOut, type SystemAuthSignOut } from '../signout'; import { toSession } from './adapter'; import type { Session, WireSession } from './types'; @@ -64,15 +65,22 @@ export class SessionClient { return returnTo ? `${path}?return_to=${encodeURIComponent(returnTo)}` : path; } - /** Ends the session. The BFF requires a same-origin request, which this is. */ - async signOut(): Promise { + /** + * Ends the app's session. The BFF requires a same-origin request, which + * this is. Returns SystemAuth's sign-out, where the browser goes next to + * end its login session, when the BFF names one. + */ + async signOut(): Promise { const res = await this.doFetch(`${this.base}/auth/logout`, { method: 'POST', credentials: 'include', + headers: { Accept: 'application/json' }, }); if (!res.ok) { throw await errorFrom(res); } + if (res.status === 204) return undefined; + return readSignOut(await res.json().catch(() => undefined)); } } diff --git a/packages/auth/src/signout.ts b/packages/auth/src/signout.ts new file mode 100644 index 0000000..8c6f2ae --- /dev/null +++ b/packages/auth/src/signout.ts @@ -0,0 +1,54 @@ +/** + * SystemAuth's sign-out, which the BFF names when it ends the app's session: + * the browser posts a form to `url` with a `return_to` field of `returnTo`, + * and SystemAuth ends its login session and redirects there. Without it, the + * next sign-in would resume the login session, and a person who signed out + * would be signed straight back in. + */ +export interface SystemAuthSignOut { + /** SystemAuth's sign-out page, such as `https://auth.example.com/logout`. */ + url: string; + /** Where SystemAuth sends the browser afterwards. */ + returnTo: string; +} + +/** + * Reads the sign-out target from the body of `POST /bff/auth/logout`, or + * returns undefined when the BFF named none or the body is not one. + */ +export function readSignOut(body: unknown): SystemAuthSignOut | undefined { + if (typeof body !== 'object' || body === null) return undefined; + const signOut = (body as { signOut?: unknown }).signOut; + if (typeof signOut !== 'object' || signOut === null) return undefined; + const { url, returnTo } = signOut as { url?: unknown; returnTo?: unknown }; + if (typeof url !== 'string' || typeof returnTo !== 'string') return undefined; + if (!isHTTPURL(url) || !isHTTPURL(returnTo)) return undefined; + return { url, returnTo }; +} + +function isHTTPURL(s: string): boolean { + try { + const u = new URL(s); + return u.protocol === 'https:' || u.protocol === 'http:'; + } catch { + return false; + } +} + +/** + * Sends the browser to SystemAuth's sign-out with a form POST, which + * SystemAuth accepts from the app's origin. The page navigates away. + */ +export function endLoginSession(target: SystemAuthSignOut, doc: Document = document): void { + const form = doc.createElement('form'); + form.method = 'POST'; + form.action = target.url; + form.style.display = 'none'; + const field = doc.createElement('input'); + field.type = 'hidden'; + field.name = 'return_to'; + field.value = target.returnTo; + form.appendChild(field); + doc.body.appendChild(form); + form.submit(); +} diff --git a/packages/auth/src/types.ts b/packages/auth/src/types.ts index f5e10b5..70f57ea 100644 --- a/packages/auth/src/types.ts +++ b/packages/auth/src/types.ts @@ -1,3 +1,5 @@ +import type { SystemAuthSignOut } from './signout'; + /** * User representation from the SystemForge backend */ @@ -121,6 +123,13 @@ export interface AuthConfig { */ onAuthError?: (error: AuthError) => void; + /** + * Ends SystemAuth's login session after logout, when the BFF names its + * sign-out page. Default: a form POST there, which navigates away; `null` + * stays on the page, signed out of the app only. + */ + endSession?: ((target: SystemAuthSignOut) => void) | null; + /** * Interval to check session validity in ms (default: 60000) */ From 4290823fa07d76371be67fab06842cd8ddacf31f Mon Sep 17 00:00:00 2001 From: John Wang Date: Mon, 2 Nov 2026 07:20:35 -0800 Subject: [PATCH 2/4] test(auth): cover ending the SystemAuth login session on sign-out Co-Authored-By: Claude Opus 5.5 --- packages/auth/src/__tests__/signout.test.ts | 49 +++++++++++++++++++ .../__tests__/SessionProvider.test.tsx | 28 +++++++++++ .../auth/src/session/__tests__/client.test.ts | 15 ++++++ 3 files changed, 92 insertions(+) create mode 100644 packages/auth/src/__tests__/signout.test.ts diff --git a/packages/auth/src/__tests__/signout.test.ts b/packages/auth/src/__tests__/signout.test.ts new file mode 100644 index 0000000..6122921 --- /dev/null +++ b/packages/auth/src/__tests__/signout.test.ts @@ -0,0 +1,49 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { endLoginSession, readSignOut } from '../signout'; + +const target = { url: 'https://auth.example.com/logout', returnTo: 'https://app.example.com/' }; + +describe('readSignOut', () => { + it('reads the sign-out target', () => { + expect(readSignOut({ signOut: target })).toEqual(target); + }); + + it('ignores a body that is not one', () => { + for (const body of [ + undefined, + null, + 'x', + {}, + { signOut: null }, + { signOut: { url: target.url } }, + ]) { + expect(readSignOut(body)).toBeUndefined(); + } + }); + + it('refuses a URL that is not http or https', () => { + expect( + readSignOut({ signOut: { url: 'javascript:alert(1)', returnTo: target.returnTo } }) + ).toBeUndefined(); + expect(readSignOut({ signOut: { url: target.url, returnTo: '/relative' } })).toBeUndefined(); + }); +}); + +describe('endLoginSession', () => { + afterEach(() => { + vi.restoreAllMocks(); + document.body.innerHTML = ''; + }); + + it('posts a form with return_to to the sign-out page', () => { + const submit = vi.spyOn(HTMLFormElement.prototype, 'submit').mockImplementation(() => {}); + endLoginSession(target); + const form = document.querySelector('form'); + expect(form?.method).toBe('post'); + expect(form?.action).toBe(target.url); + const field = form?.querySelector('input[name="return_to"]'); + expect(field?.type).toBe('hidden'); + expect(field?.value).toBe(target.returnTo); + expect(submit).toHaveBeenCalledOnce(); + }); +}); diff --git a/packages/auth/src/session/__tests__/SessionProvider.test.tsx b/packages/auth/src/session/__tests__/SessionProvider.test.tsx index 4c12ac6..8e8939e 100644 --- a/packages/auth/src/session/__tests__/SessionProvider.test.tsx +++ b/packages/auth/src/session/__tests__/SessionProvider.test.tsx @@ -87,6 +87,34 @@ describe('SessionProvider', () => { expect(onUnauthorized).not.toHaveBeenCalled(); }); + it('ends the SystemAuth login session after signing out', async () => { + const signOut = { + url: 'https://auth.example.com/logout', + returnTo: 'https://app.example.com/', + }; + const f = fakeFetch({ + '/bff/session': () => json(twoOrgs), + '/bff/auth/logout': () => json({ signOut }), + }); + const endSession = vi.fn(); + render( + + + + ); + await waitFor(() => expect(screen.getByTestId('status').textContent).toBe('authenticated')); + await act(async () => { + screen.getByText('out').click(); + }); + await waitFor(() => expect(endSession).toHaveBeenCalledWith(signOut)); + // The browser leaves for SystemAuth: the session is not read again here. + expect(f.calls.filter((c) => c.url.endsWith('/bff/session'))).toHaveLength(1); + }); + it('signs in by navigating to the BFF', async () => { const f = fakeFetch({ '/bff/session': () => json(signedOut) }); const navigate = vi.fn(); diff --git a/packages/auth/src/session/__tests__/client.test.ts b/packages/auth/src/session/__tests__/client.test.ts index 33e27de..fa1c4e9 100644 --- a/packages/auth/src/session/__tests__/client.test.ts +++ b/packages/auth/src/session/__tests__/client.test.ts @@ -54,6 +54,21 @@ describe('SessionClient', () => { expect(f.calls[0].init?.method).toBe('POST'); }); + it('asks for JSON and returns where to end the SystemAuth login session', async () => { + const signOut = { + url: 'https://auth.example.com/logout', + returnTo: 'https://app.example.com/', + }; + const f = fakeFetch({ '/bff/auth/logout': () => json({ signOut }) }); + await expect(new SessionClient({ fetch: f.fn }).signOut()).resolves.toEqual(signOut); + expect(new Headers(f.calls[0].init?.headers).get('Accept')).toBe('application/json'); + }); + + it('returns nothing when the BFF names no sign-out page', async () => { + const f = fakeFetch({ '/bff/auth/logout': () => new Response(null, { status: 204 }) }); + await expect(new SessionClient({ fetch: f.fn }).signOut()).resolves.toBeUndefined(); + }); + it('reports a rejected sign-out', async () => { const f = fakeFetch({ '/bff/auth/logout': () => From 0415449fcb6da67b059c052ac6e0e02e2a52e6fa Mon Sep 17 00:00:00 2001 From: John Wang Date: Mon, 2 Nov 2026 07:21:08 -0800 Subject: [PATCH 3/4] docs(auth): describe ending the SystemAuth login session on sign-out Co-Authored-By: Claude Opus 5.5 --- docs/packages/auth.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/docs/packages/auth.md b/docs/packages/auth.md index 5f655b9..aae2ddd 100644 --- a/docs/packages/auth.md +++ b/docs/packages/auth.md @@ -139,15 +139,32 @@ The session is re-read when the window regains focus and every five minutes (`refreshInterval`, `refreshOnFocus`). `onUnauthorized` runs when a signed-in session is found signed out, not after a deliberate sign-out. +### Signing out of SystemAuth too + +Signing out ends the app's session at the BFF, then SystemAuth's login +session, so the next sign-in asks who the person is instead of resuming +it. `signOut` (and `logout`) asks the BFF for JSON; a BFF on SystemForge +v0.30.1 or later answers with SystemAuth's sign-out page, and the provider +submits a form there with `return_to`. SystemAuth ends its login session, +revokes the person's tokens, ends their sessions in the other apps, and +returns the browser signed out. An older BFF answers `204`, and the page +stays as before. + +`endSession` on `SessionProvider` or `AuthProvider` replaces that step; +`null` leaves it out. SystemAuth must list the app's origin in +`social_login.allowed_redirect_origins`, and the app and SystemAuth must +share a site, such as `app.example.com` and `auth.example.com`. + ## API Reference ### AuthProvider Props -| Prop | Type | Description | -| ------------- | ------------------------ | ---------------------------------------------- | -| `bffBaseUrl` | `string` | Base URL for BFF auth endpoints | -| `loginPath` | `string` | Path to redirect for login (default: `/login`) | -| `onAuthError` | `(error: Error) => void` | Error callback | +| Prop | Type | Description | +| ------------- | ---------------------------- | ---------------------------------------------------------------------------------------- | +| `bffBaseUrl` | `string` | Base URL for BFF auth endpoints | +| `loginPath` | `string` | Path to redirect for login (default: `/login`) | +| `onAuthError` | `(error: Error) => void` | Error callback | +| `endSession` | `((target) => void) \| null` | Ends SystemAuth's login session after logout (default: a form POST to its sign-out page) | ### useAuth Return Value From 0660cc6c5ae5e37b92b8d91d80c6254a01933a82 Mon Sep 17 00:00:00 2001 From: John Wang Date: Mon, 2 Nov 2026 07:21:31 -0800 Subject: [PATCH 4/4] docs(release): add v0.5.1 changelog and release notes @plexusone/auth goes to 0.2.2. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.json | 34 ++++++++++++++++++++++++++++++++++ CHANGELOG.md | 25 ++++++++++++++++++++++++- docs/changelog.md | 25 ++++++++++++++++++++++++- docs/releases/v0.5.1.md | 37 +++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + packages/auth/package.json | 2 +- 6 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 docs/releases/v0.5.1.md diff --git a/CHANGELOG.json b/CHANGELOG.json index fb88222..82e2eb0 100644 --- a/CHANGELOG.json +++ b/CHANGELOG.json @@ -6,6 +6,40 @@ "commitConvention": "conventional", "maintainers": ["grokify", "johncwang@gmail.com"], "releases": [ + { + "version": "v0.5.1", + "date": "2026-11-02", + "highlights": [ + { + "description": "`@plexusone/auth` 0.2.2: signing out also ends the SystemAuth login session, so the next sign-in asks who the person is instead of resuming it", + "commit": "c9661d5" + } + ], + "security": [ + { + "description": "`signOut` and `logout` follow the BFF's SystemAuth sign-out with a form POST, so a person who signs out, for example on a shared computer, is no longer signed straight back in by the still-open login session", + "commit": "c9661d5" + } + ], + "added": [ + { + "description": "`endSession` on `SessionProvider` and `AuthProvider`, and the exported `readSignOut`, `endLoginSession` and `SystemAuthSignOut`", + "commit": "c9661d5" + } + ], + "tests": [ + { + "description": "Cover the sign-out target, the form post, the session client's JSON sign-out and the provider leaving for SystemAuth", + "commit": "4290823" + } + ], + "documentation": [ + { + "description": "The auth package's guide describes signing out of SystemAuth too, and its requirements", + "commit": "0415449" + } + ] + }, { "version": "v0.5.0", "date": "2026-10-26", diff --git a/CHANGELOG.md b/CHANGELOG.md index 67eea10..d939519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,28 @@ and this changelog is generated by [Structured Changelog](https://github.com/gro ## [Unreleased] +## [v0.5.1] - 2026-11-02 + +### Highlights + +- `@plexusone/auth` 0.2.2: signing out also ends the SystemAuth login session, so the next sign-in asks who the person is instead of resuming it + +### Security + +- `signOut` and `logout` follow the BFF's SystemAuth sign-out with a form POST, so a person who signs out, for example on a shared computer, is no longer signed straight back in by the still-open login session ([`c9661d5`](https://github.com/plexusone/systemforge-web/commit/c9661d5)) + +### Added + +- `endSession` on `SessionProvider` and `AuthProvider`, and the exported `readSignOut`, `endLoginSession` and `SystemAuthSignOut` ([`c9661d5`](https://github.com/plexusone/systemforge-web/commit/c9661d5)) + +### Documentation + +- The auth package's guide describes signing out of SystemAuth too, and its requirements ([`0415449`](https://github.com/plexusone/systemforge-web/commit/0415449)) + +### Tests + +- Cover the sign-out target, the form post, the session client's JSON sign-out and the provider leaving for SystemAuth ([`4290823`](https://github.com/plexusone/systemforge-web/commit/4290823)) + ## [v0.5.0] - 2026-10-26 ### Highlights @@ -255,7 +277,8 @@ and this changelog is generated by [Structured Changelog](https://github.com/gro - Shared pnpm workflows from grokify/.github ([`bb07c1d`](https://github.com/plexusone/systemforge-web/commit/bb07c1d)) -[unreleased]: https://github.com/plexusone/systemforge-web/compare/v0.5.0...HEAD +[unreleased]: https://github.com/plexusone/systemforge-web/compare/v0.5.1...HEAD +[v0.5.1]: https://github.com/plexusone/systemforge-web/compare/v0.5.0...v0.5.1 [v0.5.0]: https://github.com/plexusone/systemforge-web/compare/v0.4.0...v0.5.0 [v0.4.0]: https://github.com/plexusone/systemforge-web/compare/v0.3.1...v0.4.0 [v0.3.1]: https://github.com/plexusone/systemforge-web/compare/v0.3.0...v0.3.1 diff --git a/docs/changelog.md b/docs/changelog.md index 67eea10..d939519 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -9,6 +9,28 @@ and this changelog is generated by [Structured Changelog](https://github.com/gro ## [Unreleased] +## [v0.5.1] - 2026-11-02 + +### Highlights + +- `@plexusone/auth` 0.2.2: signing out also ends the SystemAuth login session, so the next sign-in asks who the person is instead of resuming it + +### Security + +- `signOut` and `logout` follow the BFF's SystemAuth sign-out with a form POST, so a person who signs out, for example on a shared computer, is no longer signed straight back in by the still-open login session ([`c9661d5`](https://github.com/plexusone/systemforge-web/commit/c9661d5)) + +### Added + +- `endSession` on `SessionProvider` and `AuthProvider`, and the exported `readSignOut`, `endLoginSession` and `SystemAuthSignOut` ([`c9661d5`](https://github.com/plexusone/systemforge-web/commit/c9661d5)) + +### Documentation + +- The auth package's guide describes signing out of SystemAuth too, and its requirements ([`0415449`](https://github.com/plexusone/systemforge-web/commit/0415449)) + +### Tests + +- Cover the sign-out target, the form post, the session client's JSON sign-out and the provider leaving for SystemAuth ([`4290823`](https://github.com/plexusone/systemforge-web/commit/4290823)) + ## [v0.5.0] - 2026-10-26 ### Highlights @@ -255,7 +277,8 @@ and this changelog is generated by [Structured Changelog](https://github.com/gro - Shared pnpm workflows from grokify/.github ([`bb07c1d`](https://github.com/plexusone/systemforge-web/commit/bb07c1d)) -[unreleased]: https://github.com/plexusone/systemforge-web/compare/v0.5.0...HEAD +[unreleased]: https://github.com/plexusone/systemforge-web/compare/v0.5.1...HEAD +[v0.5.1]: https://github.com/plexusone/systemforge-web/compare/v0.5.0...v0.5.1 [v0.5.0]: https://github.com/plexusone/systemforge-web/compare/v0.4.0...v0.5.0 [v0.4.0]: https://github.com/plexusone/systemforge-web/compare/v0.3.1...v0.4.0 [v0.3.1]: https://github.com/plexusone/systemforge-web/compare/v0.3.0...v0.3.1 diff --git a/docs/releases/v0.5.1.md b/docs/releases/v0.5.1.md new file mode 100644 index 0000000..7338338 --- /dev/null +++ b/docs/releases/v0.5.1.md @@ -0,0 +1,37 @@ +# v0.5.1 Release Notes + +**Release Date:** 2026-11-02 + +A security fix in `@plexusone/auth` 0.2.2. The other packages are unchanged. + +## Highlights + +- **Signing out ends the SystemAuth login session too.** Signing out ended + the app's session at the BFF but left SystemAuth's login session, so the + next sign-in resumed it without asking, and a person who signed out, for + example on a shared computer, was signed straight back in. `signOut` and + `logout` now ask the BFF for JSON; when it names SystemAuth's sign-out + page, the provider submits a form there, and SystemAuth ends its login + session, revokes the person's tokens, ends their sessions in the other + apps and returns the browser signed out. See + [Signing out of SystemAuth too](../packages/auth.md#signing-out-of-systemauth-too). + +## Requirements + +- systemforge v0.30.1 or later names SystemAuth's sign-out page. An older + BFF answers `204`, and sign-out stays as before. +- SystemAuth lists the app's origin in `social_login.allowed_redirect_origins`. +- The app and SystemAuth share a site, such as `app.example.com` and + `auth.example.com`: SystemAuth's login cookie is `SameSite=Lax`, so a + browser does not send it on a cross-site `POST`. + +## Installation + +```bash +pnpm add @plexusone/auth@^0.2.2 +``` + +## Upgrading + +Nothing to change. `endSession` on `SessionProvider` or `AuthProvider` +replaces the form post, or `null` leaves it out. diff --git a/mkdocs.yml b/mkdocs.yml index 9acfc26..f13a884 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,6 +87,7 @@ nav: - Tasks: specs/initiatives/invention/productgraph/TASKS.md - Releases: - Changelog: changelog.md + - v0.5.1: releases/v0.5.1.md - v0.5.0: releases/v0.5.0.md - v0.4.0: releases/v0.4.0.md - v0.3.1: releases/v0.3.1.md diff --git a/packages/auth/package.json b/packages/auth/package.json index 76b34e7..e0ba439 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -1,6 +1,6 @@ { "name": "@plexusone/auth", - "version": "0.2.1", + "version": "0.2.2", "description": "Authentication primitives for SystemForge applications", "homepage": "https://plexusone.github.io/systemforge-web/packages/auth/", "main": "./dist/index.js",