Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions .changeset/bearer-tokens-in-guards.md

This file was deleted.

41 changes: 0 additions & 41 deletions .changeset/bearer-transport-mode.md

This file was deleted.

68 changes: 68 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
# @seamless-auth/core

## 0.16.0

### Minor Changes

- 36d530b: Accept the auth API's access token as a bearer credential in `requireAuth` and `getSeamlessUser`.

Both guards read `req.cookies` and nothing else, so a native client, which has no cookie jar
and holds the auth API's own tokens, was rejected on every request to an adopter's routes.
`requireAuth` now takes an optional `authServerUrl` + `audience` pair; with both configured it
also accepts `Authorization: Bearer <access token>`, verified against the auth API's JWKS
(issuer, audience, expiry) and required to carry `typ: "access"`, so a sign-in flow's
ephemeral token is refused even though the same key signs it. The cookie wins when both are
present, and leaving the pair out keeps the guard cookie-only, which is what every earlier
version did. Half of the pair is a setup error.

`getSeamlessUser` resolves a bearer session too. The router options already carry
`authServerUrl` and `audience`, so no new option is needed there: a request with no access
cookie but a valid bearer token is verified the same way and forwarded to `GET /users/me` as
the caller's identity, while a request with neither, or a token that fails verification,
returns `null` without an upstream call.

On the bearer path `req.user.email` and `req.user.phone` are unset, because the access token
does not carry them; `getSeamlessUser` hydrates the profile.

Core exports `verifyAccessToken`, `extractBearerToken`, `authenticateBearer`, and
`authenticateRequest`. `getSeamlessUser` in core takes an optional `bearer: { authorization,
audience }`. The JWKS memo that `verifySignedAuthResponse` used moves to a shared module so both
verifiers share one instance per auth server. Fastify gains direct tests for its guards, which
until now were covered only through the plugin parity suite.

Tracks fells-code/seamless-auth-server#147.

- 0222376: Serve a bearer transport on the auth routes for native clients, and add `POST /refresh`.

Every proxied route assumed cookies: identity came from the cookie payload, session responses
were stripped of their tokens and minted into cookies, and silent refresh ran on the refresh
cookie. A native app has no cookie jar, so it could not sign in through the adapter at all, and
going around it to the auth API directly would bypass message delivery, client IP forwarding,
and the service token, and need the auth API exposed.

A request that carries `x-seamless-auth-transport: bearer` now gets a bearer contract on the
same routes. The client presents the token a route needs in `Authorization: Bearer` (the
ephemeral token `/login` or `/registration/register` returned on pre-auth routes, the access
token on access routes) and the adapter forwards it to the auth API as-is. Session-issuing
responses come back whole, `token` and `refreshToken` included, with no `Set-Cookie`; the auth
API's signature on the access token is still verified before the body goes out. `ensureCookies`
is skipped. A route that needs an identity and gets no bearer token answers 401 with the same
error it gives a missing cookie. The header rather than the presence of `Authorization` selects
the transport, because the first request of a flow carries no token in either. Requests without
the header are served exactly as before.

`POST /refresh` is new in both adapters. In bearer transport it takes `Authorization: Bearer
<refreshToken>` and returns the rotated pair, passing the auth API's failure body through so a
client can tell `refresh_token_reused` from a transient error. Concurrent rotations of the same
token are collapsed into one upstream call, since the auth API treats a replayed refresh token as
theft. In cookie transport it rotates the refresh cookie into fresh session cookies, for a client
that wants an explicit refresh.

Core: `AuthTransport`, `resolveAuthTransport`, `AUTH_TRANSPORT_HEADER`, `sessionResult` (what
every session-issuing handler now returns through), a `transport` option on `loginHandler`,
`registerHandler`, `finishLoginHandler`, the OTP verify handlers,
`pollMagicLinkConfirmationHandler`, `switchOrganizationHandler` and `finishOAuthLoginHandler`,
`transport` and `authorization` on `checkProxyIdentity`, `transport` on `applyResult`,
`refreshBearerSession`, and `refreshHandler`. The parity suite drives a full bearer sign-in
through both adapters.

Closes fells-code/seamless-auth-server#163.

## 0.15.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@seamless-auth/core",
"version": "0.15.0",
"version": "0.16.0",
"description": "Framework-agnostic core authentication logic for SeamlessAuth",
"keywords": [
"authentication",
Expand Down
74 changes: 74 additions & 0 deletions packages/express/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,79 @@
# @seamless-auth/express

## 0.16.0

### Minor Changes

- 36d530b: Accept the auth API's access token as a bearer credential in `requireAuth` and `getSeamlessUser`.

Both guards read `req.cookies` and nothing else, so a native client, which has no cookie jar
and holds the auth API's own tokens, was rejected on every request to an adopter's routes.
`requireAuth` now takes an optional `authServerUrl` + `audience` pair; with both configured it
also accepts `Authorization: Bearer <access token>`, verified against the auth API's JWKS
(issuer, audience, expiry) and required to carry `typ: "access"`, so a sign-in flow's
ephemeral token is refused even though the same key signs it. The cookie wins when both are
present, and leaving the pair out keeps the guard cookie-only, which is what every earlier
version did. Half of the pair is a setup error.

`getSeamlessUser` resolves a bearer session too. The router options already carry
`authServerUrl` and `audience`, so no new option is needed there: a request with no access
cookie but a valid bearer token is verified the same way and forwarded to `GET /users/me` as
the caller's identity, while a request with neither, or a token that fails verification,
returns `null` without an upstream call.

On the bearer path `req.user.email` and `req.user.phone` are unset, because the access token
does not carry them; `getSeamlessUser` hydrates the profile.

Core exports `verifyAccessToken`, `extractBearerToken`, `authenticateBearer`, and
`authenticateRequest`. `getSeamlessUser` in core takes an optional `bearer: { authorization,
audience }`. The JWKS memo that `verifySignedAuthResponse` used moves to a shared module so both
verifiers share one instance per auth server. Fastify gains direct tests for its guards, which
until now were covered only through the plugin parity suite.

Tracks fells-code/seamless-auth-server#147.

- 0222376: Serve a bearer transport on the auth routes for native clients, and add `POST /refresh`.

Every proxied route assumed cookies: identity came from the cookie payload, session responses
were stripped of their tokens and minted into cookies, and silent refresh ran on the refresh
cookie. A native app has no cookie jar, so it could not sign in through the adapter at all, and
going around it to the auth API directly would bypass message delivery, client IP forwarding,
and the service token, and need the auth API exposed.

A request that carries `x-seamless-auth-transport: bearer` now gets a bearer contract on the
same routes. The client presents the token a route needs in `Authorization: Bearer` (the
ephemeral token `/login` or `/registration/register` returned on pre-auth routes, the access
token on access routes) and the adapter forwards it to the auth API as-is. Session-issuing
responses come back whole, `token` and `refreshToken` included, with no `Set-Cookie`; the auth
API's signature on the access token is still verified before the body goes out. `ensureCookies`
is skipped. A route that needs an identity and gets no bearer token answers 401 with the same
error it gives a missing cookie. The header rather than the presence of `Authorization` selects
the transport, because the first request of a flow carries no token in either. Requests without
the header are served exactly as before.

`POST /refresh` is new in both adapters. In bearer transport it takes `Authorization: Bearer
<refreshToken>` and returns the rotated pair, passing the auth API's failure body through so a
client can tell `refresh_token_reused` from a transient error. Concurrent rotations of the same
token are collapsed into one upstream call, since the auth API treats a replayed refresh token as
theft. In cookie transport it rotates the refresh cookie into fresh session cookies, for a client
that wants an explicit refresh.

Core: `AuthTransport`, `resolveAuthTransport`, `AUTH_TRANSPORT_HEADER`, `sessionResult` (what
every session-issuing handler now returns through), a `transport` option on `loginHandler`,
`registerHandler`, `finishLoginHandler`, the OTP verify handlers,
`pollMagicLinkConfirmationHandler`, `switchOrganizationHandler` and `finishOAuthLoginHandler`,
`transport` and `authorization` on `checkProxyIdentity`, `transport` on `applyResult`,
`refreshBearerSession`, and `refreshHandler`. The parity suite drives a full bearer sign-in
through both adapters.

Closes fells-code/seamless-auth-server#163.

### Patch Changes

- Updated dependencies [36d530b]
- Updated dependencies [0222376]
- @seamless-auth/core@0.16.0

## 0.15.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/express/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@seamless-auth/express",
"version": "0.15.0",
"version": "0.16.0",
"description": "Express adapter for Seamless Auth passwordless authentication",
"keywords": [
"authentication",
Expand Down
74 changes: 74 additions & 0 deletions packages/fastify/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,79 @@
# @seamless-auth/fastify

## 0.7.0

### Minor Changes

- 36d530b: Accept the auth API's access token as a bearer credential in `requireAuth` and `getSeamlessUser`.

Both guards read `req.cookies` and nothing else, so a native client, which has no cookie jar
and holds the auth API's own tokens, was rejected on every request to an adopter's routes.
`requireAuth` now takes an optional `authServerUrl` + `audience` pair; with both configured it
also accepts `Authorization: Bearer <access token>`, verified against the auth API's JWKS
(issuer, audience, expiry) and required to carry `typ: "access"`, so a sign-in flow's
ephemeral token is refused even though the same key signs it. The cookie wins when both are
present, and leaving the pair out keeps the guard cookie-only, which is what every earlier
version did. Half of the pair is a setup error.

`getSeamlessUser` resolves a bearer session too. The router options already carry
`authServerUrl` and `audience`, so no new option is needed there: a request with no access
cookie but a valid bearer token is verified the same way and forwarded to `GET /users/me` as
the caller's identity, while a request with neither, or a token that fails verification,
returns `null` without an upstream call.

On the bearer path `req.user.email` and `req.user.phone` are unset, because the access token
does not carry them; `getSeamlessUser` hydrates the profile.

Core exports `verifyAccessToken`, `extractBearerToken`, `authenticateBearer`, and
`authenticateRequest`. `getSeamlessUser` in core takes an optional `bearer: { authorization,
audience }`. The JWKS memo that `verifySignedAuthResponse` used moves to a shared module so both
verifiers share one instance per auth server. Fastify gains direct tests for its guards, which
until now were covered only through the plugin parity suite.

Tracks fells-code/seamless-auth-server#147.

- 0222376: Serve a bearer transport on the auth routes for native clients, and add `POST /refresh`.

Every proxied route assumed cookies: identity came from the cookie payload, session responses
were stripped of their tokens and minted into cookies, and silent refresh ran on the refresh
cookie. A native app has no cookie jar, so it could not sign in through the adapter at all, and
going around it to the auth API directly would bypass message delivery, client IP forwarding,
and the service token, and need the auth API exposed.

A request that carries `x-seamless-auth-transport: bearer` now gets a bearer contract on the
same routes. The client presents the token a route needs in `Authorization: Bearer` (the
ephemeral token `/login` or `/registration/register` returned on pre-auth routes, the access
token on access routes) and the adapter forwards it to the auth API as-is. Session-issuing
responses come back whole, `token` and `refreshToken` included, with no `Set-Cookie`; the auth
API's signature on the access token is still verified before the body goes out. `ensureCookies`
is skipped. A route that needs an identity and gets no bearer token answers 401 with the same
error it gives a missing cookie. The header rather than the presence of `Authorization` selects
the transport, because the first request of a flow carries no token in either. Requests without
the header are served exactly as before.

`POST /refresh` is new in both adapters. In bearer transport it takes `Authorization: Bearer
<refreshToken>` and returns the rotated pair, passing the auth API's failure body through so a
client can tell `refresh_token_reused` from a transient error. Concurrent rotations of the same
token are collapsed into one upstream call, since the auth API treats a replayed refresh token as
theft. In cookie transport it rotates the refresh cookie into fresh session cookies, for a client
that wants an explicit refresh.

Core: `AuthTransport`, `resolveAuthTransport`, `AUTH_TRANSPORT_HEADER`, `sessionResult` (what
every session-issuing handler now returns through), a `transport` option on `loginHandler`,
`registerHandler`, `finishLoginHandler`, the OTP verify handlers,
`pollMagicLinkConfirmationHandler`, `switchOrganizationHandler` and `finishOAuthLoginHandler`,
`transport` and `authorization` on `checkProxyIdentity`, `transport` on `applyResult`,
`refreshBearerSession`, and `refreshHandler`. The parity suite drives a full bearer sign-in
through both adapters.

Closes fells-code/seamless-auth-server#163.

### Patch Changes

- Updated dependencies [36d530b]
- Updated dependencies [0222376]
- @seamless-auth/core@0.16.0

## 0.6.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/fastify/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@seamless-auth/fastify",
"version": "0.6.0",
"version": "0.7.0",
"description": "Fastify adapter for Seamless Auth passwordless authentication",
"keywords": [
"authentication",
Expand Down