Skip to content

Add "Sign in with 3AG Accounts" - #6

Merged
SourovCodes merged 3 commits into
mainfrom
feature/sign-in-with-3ag-accounts
Sep 19, 2026
Merged

SourovCodes merged 3 commits into
mainfrom
feature/sign-in-with-3ag-accounts

Conversation

@SourovCodes

Copy link
Copy Markdown
Member

SalesReport becomes a relying party of the identity provider at accounts.3ag.app, so a client signs in once there instead of keeping a separate password here.

Pairs with 3agApp/Accounts#2that has to be deployed and seeded first, since the client id and secret come from it.

How it works

A Socialite provider drives the authorization code flow with PKCE. Claims come from the provider's /oauth/userinfo rather than the ID token, because that call is a direct back-channel request over TLS and needs no signature check of its own.

The callback resolves the local account by oidc_sub first. Failing that it matches on email — but only when the provider reports the address verified. Without that check, anyone able to set an unverified email at the provider could claim an existing account here. Otherwise it creates the user and continues into the existing onboarding flow.

This is additive

Local login, registration and password reset all still work, and the existing 303 tests are untouched. THREE_AG_SSO_ONLY=true is the switch that retires them: it redirects the sign-in pages to the provider, removes the endpoints that would accept a local password, and ends the session at the provider on logout. It ships off — flipping it is a separate, deliberate change once the flow is proven in production.

Testing

12 new feature tests: linking by subject, linking by email exactly once, refusing an unverified email, rejecting a tampered callback, and both sides of the SSO-only switch. Verified in a browser against a real Accounts instance — an existing user was linked by verified email with no duplicate created.

Deploying this

.env needs THREE_AG_BASE_URL=https://accounts.3ag.app plus the THREE_AG_CLIENT_ID and THREE_AG_CLIENT_SECRET printed by the client seeder over there. The user also needs php artisan accounts:grant <email> SalesReport on the Accounts side, or they will be refused at the door.

🤖 Generated with Claude Code

SourovCodes and others added 3 commits September 19, 2026 23:22
SalesReport becomes a relying party of the identity provider at
accounts.3ag.app, so a client signs in once there instead of keeping a
separate password here.

A Socialite provider drives the authorization code flow with PKCE. Claims
come from the provider's userinfo endpoint rather than the ID token, because
that call is a direct back-channel request over TLS and needs no signature
check of its own.

The callback resolves the local account by oidc_sub first. Failing that it
matches on email, but only when the provider reports the address verified:
without that check anyone able to set an unverified email there could claim
an existing account here. Otherwise it creates the user and carries on into
the existing onboarding flow.

This is additive. The local login, registration and password reset all still
work, and the existing suite is untouched. THREE_AG_SSO_ONLY=true is the
switch that retires them, redirecting the sign-in pages to the provider,
removing the endpoints that would accept a local password, and ending the
session at the provider on logout. It ships off; flipping it is a separate
and deliberate change once the flow is proven in production.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`deploy.php` shares only `storage` and `.env`, so a SQLite file under
`database/` is replaced on every release, taking the shops and orders with
it. The example environment now describes MySQL, which is what production
should have been using all along.

CI gets a MySQL service to match, because SQLite waves through differences
the real engine enforces. That change immediately caught one: a query-log
assertion in the report tests matched SQLite's double-quoted identifiers,
which MySQL writes as backticks. It now compares against an unquoted column
list and passes on both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The override dropped Fortify's JSON branch and ignored the configured logout
redirect, changing how every existing session logs out in order to serve the
one case that needs diverting.

Now only a session that came from the provider, with SSO-only on, is sent to
end its session there. Everything else falls through to exactly what Fortify
would have done.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@SourovCodes
SourovCodes merged commit 4b3d24d into main Sep 19, 2026
1 check passed
@SourovCodes
SourovCodes deleted the feature/sign-in-with-3ag-accounts branch September 19, 2026 18:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant