Skip to content

refactor(express)!: remove the dead issuer option#93

Merged
Bccorb merged 1 commit into
mainfrom
refactor/remove-dead-issuer-option
Jul 20, 2026
Merged

refactor(express)!: remove the dead issuer option#93
Bccorb merged 1 commit into
mainfrom
refactor/remove-dead-issuer-option

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Closes #77.

What

issuer was required on the public SeamlessAuthServerOptions but write-only. It was assigned to resolvedOpts in createSeamlessAuthServer and never read anywhere. Once the silent-refresh path moved to the fixed M2M contract constants (iss: seamless-portal-api, aud: seamless-auth), the adopter-supplied value stopped reaching anything, so adopters were required to configure a string with no effect.

This removes it from SeamlessAuthServerOptions and ResolvedSeamlessAuthServerOptions, drops the assignment, and updates the test fixtures and README.

Scope of the issue as filed

Issue #77 originally proposed removing both issuer and audience. The correcting comment on the issue narrows that: #80 (audience binding, closing #63) landed in parallel and made audience load-bearing. It is now read by seven handlers and threaded into verifySignedAuthResponse as the audience check, so removing it would reopen the cross-relying-party token acceptance gap. audience is untouched here.

Repurposing issuer was also considered and rejected. Every consumer passes its own app origin, so reinterpreting that value as the auth server's expected iss would never match, and verifySignedAuthResponse fails closed, so every login would break with an opaque error.

What is deliberately kept

The core-level issuer plumbing carries the "seamless-portal-api" contract constant and is still reachable. Verified before touching anything:

  • packages/express/src/middleware/ensureCookies.ts receives the constant from createServer.ts
  • packages/core/src/ensureCookies.ts, createServiceToken.ts, refreshAccessToken.ts
  • packages/core/src/verifySignedAuthResponse.ts (issuer: authServerUrl), behavior unchanged

Test fixtures were split accordingly: issuer was removed only from createSeamlessAuthServer(...) call sites, and left in place for createEnsureCookiesMiddleware(...) and the core-level tests.

Docs

Added a note to the adapter README, near the configuration section, documenting a constraint that currently fails opaquely: verifySignedAuthResponse requires iss === authServerUrl, while the auth API stamps iss from its own ISSUER env var. If the adapter dials the API on an internal address while the API's ISSUER is a public URL, every login fails with only a generic [SeamlessAuth] Failed to verify signed auth response. log line. Docs only, no change to the verification code.

The README configuration table and the options block no longer list issuer as required.

Versioning

Changeset is minor, not major. Both packages are pre-1.0 (core 0.7.0, express 0.8.0), and major would bump to 1.0.0 and declare API stability, which is not intended. This matches the precedent of #89 and #92.

Downstream impact

Not changed in this PR, but these each pass issuer today and will need to drop that line when they upgrade:

  • seamless-portal-api (src/app.ts)
  • seamless-review-api (src/app.ts)
  • seamless-templates (templates/api/express/src/index.ts)

The migration is deleting one line; no replacement option is needed.

Verification

pnpm build at the workspace root: both packages build clean.

pnpm test at the workspace root:

  • core: 15 suites passed, 60 tests passed
  • express: 21 suites passed, 84 tests passed

`issuer` was required on `SeamlessAuthServerOptions` but write-only: it was
assigned to `resolvedOpts` and never read. Once the silent-refresh path moved
to the fixed M2M contract constants, the adopter-supplied value stopped
reaching anything, so adopters were required to configure a string that had no
effect.

Remove it from the public and resolved option types and from the test fixtures
that passed it. Core-level `issuer` plumbing is left alone: it carries the
"seamless-portal-api" contract constant and is still in use.

Also document that `authServerUrl` must match the auth server's `ISSUER`, since
signed responses are verified with `iss === authServerUrl` and the check fails
closed with only a generic error.

Closes #77
@Bccorb
Bccorb merged commit 072d65a into main Jul 20, 2026
1 of 2 checks passed
@Bccorb
Bccorb deleted the refactor/remove-dead-issuer-option branch July 20, 2026 03:03
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.

Remove or repurpose the unused issuer option on SeamlessAuthServerOptions

1 participant