feat(magic-link): forward a redirect target to the auth API - #151
Merged
Conversation
seamless-auth-api now takes an optional redirectUri on GET /magic-link deciding where the emailed link lands. The adapters called that route with no query, so the feature was reachable only by a backend calling the API directly and not by a browser or mobile client, which was most of the point. RequestMagicLinkInput gains an optional redirectUri, built onto the URL with the existing buildUpstreamUrl helper. Both adapters read it from the body of their own POST /magic-link. Omit it and the upstream URL is byte for byte what it was. Forwarded rather than checked. The API validates against the configured origins and answers 400, and an allowlist kept in two places is one that eventually disagrees with itself. A non-string is dropped rather than coerced so it cannot become a query parameter meaning something the caller did not send. Covered on both adapters. Only the forwarding underneath is shared, since each reads its own request body, so the fastify side goes in the parity suite next to the express one.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to fells-code/seamless-auth-api#240, which added an optional
redirectUritoGET /magic-linkso a tenant's web and mobile clients can each receive a link that opens in the right place.Without this the feature is unreachable from a browser. The adapters called
${authServerUrl}/magic-linkwith no query, so only a backend calling the API directly could use it, and a browser or mobile client, which is the case the API change exists for, could not.What changed
RequestMagicLinkInputgains an optionalredirectUri, put on the URL with the existingbuildUpstreamUrlhelper rather than string-concatenated.POST /magic-linkand pass it through.Additive. Omit it and the upstream URL is byte for byte what it was, so no adopter has to change anything. Against an auth API that predates the parameter it is simply ignored and the link keeps the tenant-wide destination.
Forwarded, not validated
The adapters do not check the value. The API validates it against the configured origins and answers
400, and an allowlist kept in two places is one that eventually disagrees with itself. A refusal is passed back through the existingreadPassthroughFailurepath, which one of the core tests asserts.A value that is not a string is dropped rather than coerced, so an object or a number cannot become a query parameter meaning something the caller never sent.
Tests
Both adapters, because each reads its own request body and only the forwarding underneath them is shared:
Verified non-vacuous by reverting each side in turn: dropping the core forwarding fails 2, dropping the fastify read fails the parity case.
Verification
pnpm buildandpnpm testat the workspace root, per AGENTS.md:Changeset marks all three packages
minor.Order
The API side (fells-code/seamless-auth-api#240) should land first. This is harmless before it, since an API that does not know the parameter ignores it, but the feature only works once both are out.