@wtfalch/auth 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/auth.js +27 -1
  2. package/package.json +1 -1
package/dist/auth.js CHANGED
@@ -503,7 +503,7 @@ export function createAuth(input) {
503
503
  const device = await requestDeviceAuthorization(options(), scopeFor(options().organizationId));
504
504
  const cookie = await sealQrTransaction(options(), { dc: device.deviceCode, iv: device.interval }, device.expiresIn);
505
505
  return {
506
- url: device.verificationUriComplete,
506
+ url: qrVerificationUrl(options(), device.verificationUriComplete),
507
507
  userCode: device.userCode,
508
508
  expiresIn: device.expiresIn,
509
509
  interval: device.interval,
@@ -694,3 +694,29 @@ function reasonOf(error) {
694
694
  return 'denied';
695
695
  return 'exchange';
696
696
  }
697
+ /**
698
+ * The issuer always builds `verification_uri_complete` on itself
699
+ * (`<issuer>/device?user_code=...`). A namespace with its own login host
700
+ * keeps that namespace's users, sessions and passkeys there, so the phone
701
+ * must land on the login host instead -- but only by rewriting a URL that is
702
+ * exactly what the issuer was expected to return; anything else is refused
703
+ * rather than sent somewhere unexpected.
704
+ */
705
+ function qrVerificationUrl(options, verificationUriComplete) {
706
+ const loginOrigin = options.namespace?.loginOrigin;
707
+ const issuerOrigin = new URL(options.issuer).origin;
708
+ if (!loginOrigin || loginOrigin === issuerOrigin)
709
+ return verificationUriComplete;
710
+ let url;
711
+ try {
712
+ url = new URL(verificationUriComplete);
713
+ }
714
+ catch {
715
+ throw new AuthError('request', 'the issuer returned an unusable device verification URL');
716
+ }
717
+ if (url.origin !== issuerOrigin || url.pathname !== '/device')
718
+ throw new AuthError('request', 'the issuer returned an unexpected device verification URL');
719
+ const rewritten = new URL(`${loginOrigin}/device`);
720
+ rewritten.search = url.search;
721
+ return rewritten.href;
722
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/auth",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Sign in against auth.wtfalch.dev: a server session for a Next.js app, and a browser client with silent single sign-on across subdomains.",
5
5
  "repository": {
6
6
  "type": "git",