@wtfalch/auth 0.4.1 → 0.5.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.
package/dist/auth.d.ts CHANGED
@@ -86,6 +86,26 @@ export interface Auth {
86
86
  verify(request: Request): Promise<Response>;
87
87
  /** GET {basePath}/link?sessionId=&code= : the sign-in link from an email, on any device. */
88
88
  link(request: Request): Promise<Response>;
89
+ /**
90
+ * The same link as data, for a caller that is not the browser holding it.
91
+ *
92
+ * `link` answers a browser: it redirects and sets a cookie. A client with no
93
+ * browser of its own -- a desktop app, a CLI -- cannot be signed in that way,
94
+ * and its server was otherwise left to call `link` and scrape `Set-Cookie`
95
+ * off the Response, which is reaching around this interface for something it
96
+ * should be able to ask for. `complete` and `resetPassword` already return
97
+ * the session this way; this is the third of the same shape.
98
+ *
99
+ * The cookies come back unset. Whoever calls this decides where the session
100
+ * goes, and for a headless client that is deliberately not the browser: the
101
+ * cookie name is fixed, so setting it would overwrite whatever website
102
+ * session the person already had in the tab they clicked from.
103
+ */
104
+ followLink(input: {
105
+ sessionId: string;
106
+ code: string;
107
+ next?: string;
108
+ }): Promise<SignedIn>;
89
109
  /** Emails a fresh verification link. Says nothing about whether the address exists. */
90
110
  resendVerification(email: string, next?: string): Promise<void>;
91
111
  /** Emails a password-reset link to {basePath}/reset?userId=&code=. Says nothing about whether the address exists. */
package/dist/auth.js CHANGED
@@ -258,20 +258,31 @@ export function createAuth(input) {
258
258
  return { ok: false, error: 'unavailable', message: 'the sign-in service did not answer' };
259
259
  }
260
260
  };
261
+ const followLink = async ({ sessionId, code, next, }) => {
262
+ try {
263
+ const flow = await serverFlow();
264
+ const completed = await finishOrHandoff(() => broker().followLink({ authRequestId: flow.id, sessionId, code }), flow, safeNextPath(next, options().afterLogin));
265
+ return { ok: true, ...completed };
266
+ }
267
+ catch (error) {
268
+ if (error instanceof BrokerError && error.status < 500) {
269
+ return { ok: false, error: 'invalid_code', message: error.detail ?? error.error };
270
+ }
271
+ return { ok: false, error: 'unavailable', message: 'the sign-in service did not answer' };
272
+ }
273
+ };
261
274
  const link = async (request) => {
262
275
  const params = new URL(request.url).searchParams;
263
276
  const sessionId = params.get('sessionId');
264
277
  const code = params.get('code');
265
278
  if (!sessionId || !code)
266
279
  return failed('link', []);
267
- try {
268
- const flow = await serverFlow();
269
- const { location, cookies } = await finishOrHandoff(() => broker().followLink({ authRequestId: flow.id, sessionId, code }), flow, safeNextPath(params.get('next'), options().afterLogin));
270
- return redirect(location, cookies);
271
- }
272
- catch {
273
- return failed('link', []);
274
- }
280
+ const result = await followLink({
281
+ sessionId,
282
+ code,
283
+ next: params.get('next') ?? undefined,
284
+ });
285
+ return result.ok ? redirect(result.location, result.cookies) : failed('link', []);
275
286
  };
276
287
  const signIn = async ({ authRequestId, email, password, }) => {
277
288
  try {
@@ -333,6 +344,7 @@ export function createAuth(input) {
333
344
  logout,
334
345
  verify,
335
346
  link,
347
+ followLink,
336
348
  resendVerification,
337
349
  requestPasswordReset,
338
350
  resetPassword,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/auth",
3
- "version": "0.4.1",
3
+ "version": "0.5.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",