naystack 1.8.5 → 1.8.6

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.
@@ -33,6 +33,7 @@ __export(auth_exports, {
33
33
  AuthFetch: () => AuthFetch,
34
34
  AuthWrapper: () => AuthWrapper,
35
35
  checkAuthStatus: () => checkAuthStatus,
36
+ getAuthorizationHandoff: () => getAuthorizationHandoff,
36
37
  getContext: () => getContext,
37
38
  getInstagramAuthorizationURL: () => getInstagramAuthorizationURL,
38
39
  getRefreshToken: () => getRefreshToken,
@@ -575,9 +576,28 @@ function setupGoogleAuth(props) {
575
576
  }
576
577
 
577
578
  // src/auth/instagram/route.ts
578
- var import_server8 = require("next/server");
579
+ var import_server9 = require("next/server");
579
580
 
580
581
  // src/auth/instagram/utils.ts
582
+ var import_server7 = require("next/server");
583
+ function getAuthorizationHandoff(authorizationURL) {
584
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
585
+ /</g,
586
+ "\\u003c"
587
+ );
588
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
589
+ return new import_server7.NextResponse(
590
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
591
+ {
592
+ headers: {
593
+ "content-type": "text/html; charset=utf-8",
594
+ "cache-control": "no-store",
595
+ // The token is in the URL; keep it off the provider's referer log.
596
+ "referrer-policy": "no-referrer"
597
+ }
598
+ }
599
+ );
600
+ }
581
601
  async function getRefreshedInstagramAccessToken(token) {
582
602
  const request = await fetch(
583
603
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -640,7 +660,7 @@ var getInstagramUser = (token, id, fields) => {
640
660
  };
641
661
 
642
662
  // src/socials/meta-webhook.ts
643
- var import_server7 = require("next/server");
663
+ var import_server8 = require("next/server");
644
664
 
645
665
  // src/auth/instagram/route.ts
646
666
  var getInstagramRoute = ({
@@ -648,7 +668,7 @@ var getInstagramRoute = ({
648
668
  errorRedirectURL,
649
669
  onUser
650
670
  }) => {
651
- const handleError2 = (message) => import_server8.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
671
+ const handleError2 = (message) => import_server9.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
652
672
  return async (req) => {
653
673
  const accessCode = req.nextUrl.searchParams.get("code");
654
674
  const error = req.nextUrl.searchParams.get("error");
@@ -656,7 +676,7 @@ var getInstagramRoute = ({
656
676
  if (error) return handleError2(error);
657
677
  if (!accessCode) {
658
678
  if (!stateToken) return handleError2("Invalid request");
659
- return import_server8.NextResponse.redirect(getInstagramAuthorizationURL(stateToken), 302);
679
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
660
680
  }
661
681
  if (!stateToken) return handleError2("Invalid request");
662
682
  const instagramData = await getLongLivedToken(
@@ -676,7 +696,7 @@ var getInstagramRoute = ({
676
696
  instagramData.accessToken
677
697
  );
678
698
  if (errorMessage) return handleError2(errorMessage);
679
- return import_server8.NextResponse.redirect(redirectURL);
699
+ return import_server9.NextResponse.redirect(redirectURL);
680
700
  };
681
701
  };
682
702
 
@@ -698,6 +718,7 @@ async function getRefreshToken() {
698
718
  AuthFetch,
699
719
  AuthWrapper,
700
720
  checkAuthStatus,
721
+ getAuthorizationHandoff,
701
722
  getContext,
702
723
  getInstagramAuthorizationURL,
703
724
  getRefreshToken,
@@ -5,7 +5,7 @@ export { getRefreshToken } from './utils/token.mjs';
5
5
  export { AuthFetch, AuthWrapper } from './email/next.mjs';
6
6
  export { checkAuthStatus, getTokenizedResponse } from './email/token.mjs';
7
7
  export { getContext } from './email/utils.mjs';
8
- export { getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './instagram/utils.mjs';
8
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './instagram/utils.mjs';
9
9
  import 'next/server';
10
10
  import './email/types.mjs';
11
11
  import './types.mjs';
@@ -5,7 +5,7 @@ export { getRefreshToken } from './utils/token.js';
5
5
  export { AuthFetch, AuthWrapper } from './email/next.js';
6
6
  export { checkAuthStatus, getTokenizedResponse } from './email/token.js';
7
7
  export { getContext } from './email/utils.js';
8
- export { getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './instagram/utils.js';
8
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './instagram/utils.js';
9
9
  import 'next/server';
10
10
  import './email/types.js';
11
11
  import './types.js';
@@ -533,9 +533,28 @@ function setupGoogleAuth(props) {
533
533
  }
534
534
 
535
535
  // src/auth/instagram/route.ts
536
- import { NextResponse as NextResponse7 } from "next/server";
536
+ import { NextResponse as NextResponse8 } from "next/server";
537
537
 
538
538
  // src/auth/instagram/utils.ts
539
+ import { NextResponse as NextResponse6 } from "next/server";
540
+ function getAuthorizationHandoff(authorizationURL) {
541
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
542
+ /</g,
543
+ "\\u003c"
544
+ );
545
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
546
+ return new NextResponse6(
547
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
548
+ {
549
+ headers: {
550
+ "content-type": "text/html; charset=utf-8",
551
+ "cache-control": "no-store",
552
+ // The token is in the URL; keep it off the provider's referer log.
553
+ "referrer-policy": "no-referrer"
554
+ }
555
+ }
556
+ );
557
+ }
539
558
  async function getRefreshedInstagramAccessToken(token) {
540
559
  const request = await fetch(
541
560
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -598,7 +617,7 @@ var getInstagramUser = (token, id, fields) => {
598
617
  };
599
618
 
600
619
  // src/socials/meta-webhook.ts
601
- import { NextResponse as NextResponse6 } from "next/server";
620
+ import { NextResponse as NextResponse7 } from "next/server";
602
621
 
603
622
  // src/auth/instagram/route.ts
604
623
  var getInstagramRoute = ({
@@ -606,7 +625,7 @@ var getInstagramRoute = ({
606
625
  errorRedirectURL,
607
626
  onUser
608
627
  }) => {
609
- const handleError2 = (message) => NextResponse7.redirect(`${errorRedirectURL}?error=${message}`);
628
+ const handleError2 = (message) => NextResponse8.redirect(`${errorRedirectURL}?error=${message}`);
610
629
  return async (req) => {
611
630
  const accessCode = req.nextUrl.searchParams.get("code");
612
631
  const error = req.nextUrl.searchParams.get("error");
@@ -614,7 +633,7 @@ var getInstagramRoute = ({
614
633
  if (error) return handleError2(error);
615
634
  if (!accessCode) {
616
635
  if (!stateToken) return handleError2("Invalid request");
617
- return NextResponse7.redirect(getInstagramAuthorizationURL(stateToken), 302);
636
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
618
637
  }
619
638
  if (!stateToken) return handleError2("Invalid request");
620
639
  const instagramData = await getLongLivedToken(
@@ -634,7 +653,7 @@ var getInstagramRoute = ({
634
653
  instagramData.accessToken
635
654
  );
636
655
  if (errorMessage) return handleError2(errorMessage);
637
- return NextResponse7.redirect(redirectURL);
656
+ return NextResponse8.redirect(redirectURL);
638
657
  };
639
658
  };
640
659
 
@@ -655,6 +674,7 @@ export {
655
674
  AuthFetch,
656
675
  AuthWrapper,
657
676
  checkAuthStatus,
677
+ getAuthorizationHandoff,
658
678
  getContext,
659
679
  getInstagramAuthorizationURL,
660
680
  getRefreshToken,
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/auth/instagram/index.ts
21
21
  var instagram_exports = {};
22
22
  __export(instagram_exports, {
23
+ getAuthorizationHandoff: () => getAuthorizationHandoff,
23
24
  getInstagramAuthorizationURL: () => getInstagramAuthorizationURL,
24
25
  getRefreshedInstagramAccessToken: () => getRefreshedInstagramAccessToken,
25
26
  setupInstagramAuth: () => setupInstagramAuth
@@ -27,7 +28,7 @@ __export(instagram_exports, {
27
28
  module.exports = __toCommonJS(instagram_exports);
28
29
 
29
30
  // src/auth/instagram/route.ts
30
- var import_server3 = require("next/server");
31
+ var import_server4 = require("next/server");
31
32
 
32
33
  // src/auth/email/token.ts
33
34
  var import_bcryptjs = require("bcryptjs");
@@ -101,6 +102,25 @@ function getUserIdFromAccessToken(accessToken) {
101
102
  }
102
103
 
103
104
  // src/auth/instagram/utils.ts
105
+ var import_server2 = require("next/server");
106
+ function getAuthorizationHandoff(authorizationURL) {
107
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
108
+ /</g,
109
+ "\\u003c"
110
+ );
111
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
112
+ return new import_server2.NextResponse(
113
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
114
+ {
115
+ headers: {
116
+ "content-type": "text/html; charset=utf-8",
117
+ "cache-control": "no-store",
118
+ // The token is in the URL; keep it off the provider's referer log.
119
+ "referrer-policy": "no-referrer"
120
+ }
121
+ }
122
+ );
123
+ }
104
124
  async function getRefreshedInstagramAccessToken(token) {
105
125
  const request = await fetch(
106
126
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -163,7 +183,7 @@ var getInstagramUser = (token, id, fields) => {
163
183
  };
164
184
 
165
185
  // src/socials/meta-webhook.ts
166
- var import_server2 = require("next/server");
186
+ var import_server3 = require("next/server");
167
187
 
168
188
  // src/auth/instagram/route.ts
169
189
  var getInstagramRoute = ({
@@ -171,7 +191,7 @@ var getInstagramRoute = ({
171
191
  errorRedirectURL,
172
192
  onUser
173
193
  }) => {
174
- const handleError = (message) => import_server3.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
194
+ const handleError = (message) => import_server4.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
175
195
  return async (req) => {
176
196
  const accessCode = req.nextUrl.searchParams.get("code");
177
197
  const error = req.nextUrl.searchParams.get("error");
@@ -179,7 +199,7 @@ var getInstagramRoute = ({
179
199
  if (error) return handleError(error);
180
200
  if (!accessCode) {
181
201
  if (!stateToken) return handleError("Invalid request");
182
- return import_server3.NextResponse.redirect(getInstagramAuthorizationURL(stateToken), 302);
202
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
183
203
  }
184
204
  if (!stateToken) return handleError("Invalid request");
185
205
  const instagramData = await getLongLivedToken(
@@ -199,7 +219,7 @@ var getInstagramRoute = ({
199
219
  instagramData.accessToken
200
220
  );
201
221
  if (errorMessage) return handleError(errorMessage);
202
- return import_server3.NextResponse.redirect(redirectURL);
222
+ return import_server4.NextResponse.redirect(redirectURL);
203
223
  };
204
224
  };
205
225
 
@@ -211,6 +231,7 @@ function setupInstagramAuth(props) {
211
231
  }
212
232
  // Annotate the CommonJS export names for ESM import in node:
213
233
  0 && (module.exports = {
234
+ getAuthorizationHandoff,
214
235
  getInstagramAuthorizationURL,
215
236
  getRefreshedInstagramAccessToken,
216
237
  setupInstagramAuth
@@ -1,5 +1,5 @@
1
1
  import * as next_server from 'next/server';
2
- export { getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './utils.mjs';
2
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './utils.mjs';
3
3
  import { InstagramUser } from '../../socials/instagram/types.mjs';
4
4
 
5
5
  /**
@@ -22,7 +22,9 @@ interface SetupInstagramAuthOptions {
22
22
  * Mount the GET handler on your Instagram auth route (e.g. `app/api/(auth)/instagram/route.ts`).
23
23
  *
24
24
  * The single GET handler serves both the OAuth callback (`?code`) and the connect
25
- * entry point (`?state` with no code → server 302 to Instagram's authorize URL).
25
+ * entry point (`?state` with no code → an HTML page that jumps to Instagram's
26
+ * authorize URL client-side, so mobile browsers don't universal-link the flow into
27
+ * the Instagram app; see {@link getAuthorizationHandoff}).
26
28
  *
27
29
  * Requires env vars: `INSTAGRAM_CLIENT_ID` (server-only), `INSTAGRAM_CLIENT_SECRET`, `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`.
28
30
  *
@@ -1,5 +1,5 @@
1
1
  import * as next_server from 'next/server';
2
- export { getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './utils.js';
2
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getRefreshedInstagramAccessToken } from './utils.js';
3
3
  import { InstagramUser } from '../../socials/instagram/types.js';
4
4
 
5
5
  /**
@@ -22,7 +22,9 @@ interface SetupInstagramAuthOptions {
22
22
  * Mount the GET handler on your Instagram auth route (e.g. `app/api/(auth)/instagram/route.ts`).
23
23
  *
24
24
  * The single GET handler serves both the OAuth callback (`?code`) and the connect
25
- * entry point (`?state` with no code → server 302 to Instagram's authorize URL).
25
+ * entry point (`?state` with no code → an HTML page that jumps to Instagram's
26
+ * authorize URL client-side, so mobile browsers don't universal-link the flow into
27
+ * the Instagram app; see {@link getAuthorizationHandoff}).
26
28
  *
27
29
  * Requires env vars: `INSTAGRAM_CLIENT_ID` (server-only), `INSTAGRAM_CLIENT_SECRET`, `NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT`.
28
30
  *
@@ -1,5 +1,5 @@
1
1
  // src/auth/instagram/route.ts
2
- import { NextResponse as NextResponse3 } from "next/server";
2
+ import { NextResponse as NextResponse4 } from "next/server";
3
3
 
4
4
  // src/auth/email/token.ts
5
5
  import { compare } from "bcryptjs";
@@ -73,6 +73,25 @@ function getUserIdFromAccessToken(accessToken) {
73
73
  }
74
74
 
75
75
  // src/auth/instagram/utils.ts
76
+ import { NextResponse as NextResponse2 } from "next/server";
77
+ function getAuthorizationHandoff(authorizationURL) {
78
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
79
+ /</g,
80
+ "\\u003c"
81
+ );
82
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
83
+ return new NextResponse2(
84
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
85
+ {
86
+ headers: {
87
+ "content-type": "text/html; charset=utf-8",
88
+ "cache-control": "no-store",
89
+ // The token is in the URL; keep it off the provider's referer log.
90
+ "referrer-policy": "no-referrer"
91
+ }
92
+ }
93
+ );
94
+ }
76
95
  async function getRefreshedInstagramAccessToken(token) {
77
96
  const request = await fetch(
78
97
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -135,7 +154,7 @@ var getInstagramUser = (token, id, fields) => {
135
154
  };
136
155
 
137
156
  // src/socials/meta-webhook.ts
138
- import { NextResponse as NextResponse2 } from "next/server";
157
+ import { NextResponse as NextResponse3 } from "next/server";
139
158
 
140
159
  // src/auth/instagram/route.ts
141
160
  var getInstagramRoute = ({
@@ -143,7 +162,7 @@ var getInstagramRoute = ({
143
162
  errorRedirectURL,
144
163
  onUser
145
164
  }) => {
146
- const handleError = (message) => NextResponse3.redirect(`${errorRedirectURL}?error=${message}`);
165
+ const handleError = (message) => NextResponse4.redirect(`${errorRedirectURL}?error=${message}`);
147
166
  return async (req) => {
148
167
  const accessCode = req.nextUrl.searchParams.get("code");
149
168
  const error = req.nextUrl.searchParams.get("error");
@@ -151,7 +170,7 @@ var getInstagramRoute = ({
151
170
  if (error) return handleError(error);
152
171
  if (!accessCode) {
153
172
  if (!stateToken) return handleError("Invalid request");
154
- return NextResponse3.redirect(getInstagramAuthorizationURL(stateToken), 302);
173
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
155
174
  }
156
175
  if (!stateToken) return handleError("Invalid request");
157
176
  const instagramData = await getLongLivedToken(
@@ -171,7 +190,7 @@ var getInstagramRoute = ({
171
190
  instagramData.accessToken
172
191
  );
173
192
  if (errorMessage) return handleError(errorMessage);
174
- return NextResponse3.redirect(redirectURL);
193
+ return NextResponse4.redirect(redirectURL);
175
194
  };
176
195
  };
177
196
 
@@ -182,6 +201,7 @@ function setupInstagramAuth(props) {
182
201
  };
183
202
  }
184
203
  export {
204
+ getAuthorizationHandoff,
185
205
  getInstagramAuthorizationURL,
186
206
  getRefreshedInstagramAccessToken,
187
207
  setupInstagramAuth
@@ -23,7 +23,7 @@ __export(route_exports, {
23
23
  getInstagramRoute: () => getInstagramRoute
24
24
  });
25
25
  module.exports = __toCommonJS(route_exports);
26
- var import_server3 = require("next/server");
26
+ var import_server4 = require("next/server");
27
27
 
28
28
  // src/auth/email/token.ts
29
29
  var import_bcryptjs = require("bcryptjs");
@@ -97,6 +97,25 @@ function getUserIdFromAccessToken(accessToken) {
97
97
  }
98
98
 
99
99
  // src/auth/instagram/utils.ts
100
+ var import_server2 = require("next/server");
101
+ function getAuthorizationHandoff(authorizationURL) {
102
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
103
+ /</g,
104
+ "\\u003c"
105
+ );
106
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
107
+ return new import_server2.NextResponse(
108
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
109
+ {
110
+ headers: {
111
+ "content-type": "text/html; charset=utf-8",
112
+ "cache-control": "no-store",
113
+ // The token is in the URL; keep it off the provider's referer log.
114
+ "referrer-policy": "no-referrer"
115
+ }
116
+ }
117
+ );
118
+ }
100
119
  async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
101
120
  const formData = new FormData();
102
121
  formData.set("client_id", clientId);
@@ -152,7 +171,7 @@ var getInstagramUser = (token, id, fields) => {
152
171
  };
153
172
 
154
173
  // src/socials/meta-webhook.ts
155
- var import_server2 = require("next/server");
174
+ var import_server3 = require("next/server");
156
175
 
157
176
  // src/auth/instagram/route.ts
158
177
  var getInstagramRoute = ({
@@ -160,7 +179,7 @@ var getInstagramRoute = ({
160
179
  errorRedirectURL,
161
180
  onUser
162
181
  }) => {
163
- const handleError = (message) => import_server3.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
182
+ const handleError = (message) => import_server4.NextResponse.redirect(`${errorRedirectURL}?error=${message}`);
164
183
  return async (req) => {
165
184
  const accessCode = req.nextUrl.searchParams.get("code");
166
185
  const error = req.nextUrl.searchParams.get("error");
@@ -168,7 +187,7 @@ var getInstagramRoute = ({
168
187
  if (error) return handleError(error);
169
188
  if (!accessCode) {
170
189
  if (!stateToken) return handleError("Invalid request");
171
- return import_server3.NextResponse.redirect(getInstagramAuthorizationURL(stateToken), 302);
190
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
172
191
  }
173
192
  if (!stateToken) return handleError("Invalid request");
174
193
  const instagramData = await getLongLivedToken(
@@ -188,7 +207,7 @@ var getInstagramRoute = ({
188
207
  instagramData.accessToken
189
208
  );
190
209
  if (errorMessage) return handleError(errorMessage);
191
- return import_server3.NextResponse.redirect(redirectURL);
210
+ return import_server4.NextResponse.redirect(redirectURL);
192
211
  };
193
212
  };
194
213
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,5 +1,5 @@
1
1
  // src/auth/instagram/route.ts
2
- import { NextResponse as NextResponse3 } from "next/server";
2
+ import { NextResponse as NextResponse4 } from "next/server";
3
3
 
4
4
  // src/auth/email/token.ts
5
5
  import { compare } from "bcryptjs";
@@ -73,6 +73,25 @@ function getUserIdFromAccessToken(accessToken) {
73
73
  }
74
74
 
75
75
  // src/auth/instagram/utils.ts
76
+ import { NextResponse as NextResponse2 } from "next/server";
77
+ function getAuthorizationHandoff(authorizationURL) {
78
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
79
+ /</g,
80
+ "\\u003c"
81
+ );
82
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
83
+ return new NextResponse2(
84
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
85
+ {
86
+ headers: {
87
+ "content-type": "text/html; charset=utf-8",
88
+ "cache-control": "no-store",
89
+ // The token is in the URL; keep it off the provider's referer log.
90
+ "referrer-policy": "no-referrer"
91
+ }
92
+ }
93
+ );
94
+ }
76
95
  async function getLongLivedToken(code, redirectURL, clientId, clientSecret) {
77
96
  const formData = new FormData();
78
97
  formData.set("client_id", clientId);
@@ -128,7 +147,7 @@ var getInstagramUser = (token, id, fields) => {
128
147
  };
129
148
 
130
149
  // src/socials/meta-webhook.ts
131
- import { NextResponse as NextResponse2 } from "next/server";
150
+ import { NextResponse as NextResponse3 } from "next/server";
132
151
 
133
152
  // src/auth/instagram/route.ts
134
153
  var getInstagramRoute = ({
@@ -136,7 +155,7 @@ var getInstagramRoute = ({
136
155
  errorRedirectURL,
137
156
  onUser
138
157
  }) => {
139
- const handleError = (message) => NextResponse3.redirect(`${errorRedirectURL}?error=${message}`);
158
+ const handleError = (message) => NextResponse4.redirect(`${errorRedirectURL}?error=${message}`);
140
159
  return async (req) => {
141
160
  const accessCode = req.nextUrl.searchParams.get("code");
142
161
  const error = req.nextUrl.searchParams.get("error");
@@ -144,7 +163,7 @@ var getInstagramRoute = ({
144
163
  if (error) return handleError(error);
145
164
  if (!accessCode) {
146
165
  if (!stateToken) return handleError("Invalid request");
147
- return NextResponse3.redirect(getInstagramAuthorizationURL(stateToken), 302);
166
+ return getAuthorizationHandoff(getInstagramAuthorizationURL(stateToken));
148
167
  }
149
168
  if (!stateToken) return handleError("Invalid request");
150
169
  const instagramData = await getLongLivedToken(
@@ -164,7 +183,7 @@ var getInstagramRoute = ({
164
183
  instagramData.accessToken
165
184
  );
166
185
  if (errorMessage) return handleError(errorMessage);
167
- return NextResponse3.redirect(redirectURL);
186
+ return NextResponse4.redirect(redirectURL);
168
187
  };
169
188
  };
170
189
  export {
@@ -20,11 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/auth/instagram/utils.ts
21
21
  var utils_exports = {};
22
22
  __export(utils_exports, {
23
+ getAuthorizationHandoff: () => getAuthorizationHandoff,
23
24
  getInstagramAuthorizationURL: () => getInstagramAuthorizationURL,
24
25
  getLongLivedToken: () => getLongLivedToken,
25
26
  getRefreshedInstagramAccessToken: () => getRefreshedInstagramAccessToken
26
27
  });
27
28
  module.exports = __toCommonJS(utils_exports);
29
+ var import_server = require("next/server");
28
30
 
29
31
  // src/env.ts
30
32
  var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
@@ -77,6 +79,24 @@ function getEnv(key, skipCheck) {
77
79
  }
78
80
 
79
81
  // src/auth/instagram/utils.ts
82
+ function getAuthorizationHandoff(authorizationURL) {
83
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
84
+ /</g,
85
+ "\\u003c"
86
+ );
87
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
88
+ return new import_server.NextResponse(
89
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
90
+ {
91
+ headers: {
92
+ "content-type": "text/html; charset=utf-8",
93
+ "cache-control": "no-store",
94
+ // The token is in the URL; keep it off the provider's referer log.
95
+ "referrer-policy": "no-referrer"
96
+ }
97
+ }
98
+ );
99
+ }
80
100
  async function getRefreshedInstagramAccessToken(token) {
81
101
  const request = await fetch(
82
102
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -117,6 +137,7 @@ var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/a
117
137
  )}&response_type=code&enable_fb_login=0&force_authentication=1&scope=instagram_business_basic&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}`;
118
138
  // Annotate the CommonJS export names for ESM import in node:
119
139
  0 && (module.exports = {
140
+ getAuthorizationHandoff,
120
141
  getInstagramAuthorizationURL,
121
142
  getLongLivedToken,
122
143
  getRefreshedInstagramAccessToken
@@ -1,3 +1,27 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Builds the interstitial document that carries the browser from our origin to a
5
+ * provider's authorization page.
6
+ *
7
+ * Mobile browsers match universal links (iOS) and app links (Android) against the
8
+ * final URL of a *user-initiated* navigation — following redirects — so both a
9
+ * tapped `<a href="https://www.instagram.com/…">` and a server 302 to the same
10
+ * place can be intercepted by the provider's native app, which has no idea what to
11
+ * do with an OAuth flow. A navigation issued from a freshly loaded document has no
12
+ * gesture token behind it and is never intercepted, so this page loads and
13
+ * immediately replaces itself with `authorizationURL`.
14
+ *
15
+ * `location.replace` keeps the interstitial out of session history, so Back from
16
+ * the provider returns to the page that started the flow. The `noscript` meta
17
+ * refresh is a fallback, not the primary path.
18
+ *
19
+ * @param authorizationURL - Provider authorization URL to hand the browser off to
20
+ * @returns HTML response that redirects client-side
21
+ *
22
+ * @category Auth
23
+ */
24
+ declare function getAuthorizationHandoff(authorizationURL: string): NextResponse<unknown>;
1
25
  /**
2
26
  * Exchanges a long-lived Instagram token for a refreshed token.
3
27
  * @param token - Current long-lived access token
@@ -33,14 +57,16 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
33
57
  *
34
58
  * @example
35
59
  * ```ts
36
- * // In a server route handler:
37
- * import { getInstagramAuthorizationURL } from "naystack/auth";
60
+ * // In a server route handler. Hand off with `getAuthorizationHandoff` rather
61
+ * // than `NextResponse.redirect` a 302 onto instagram.com is still matched as a
62
+ * // universal/app link and opens the Instagram app mid-flow.
63
+ * import { getAuthorizationHandoff, getInstagramAuthorizationURL } from "naystack/auth";
38
64
  *
39
- * return NextResponse.redirect(getInstagramAuthorizationURL(state), 302);
65
+ * return getAuthorizationHandoff(getInstagramAuthorizationURL(state));
40
66
  * ```
41
67
  *
42
68
  * @category Auth
43
69
  */
44
70
  declare const getInstagramAuthorizationURL: (token: string) => string;
45
71
 
46
- export { getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
72
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
@@ -1,3 +1,27 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Builds the interstitial document that carries the browser from our origin to a
5
+ * provider's authorization page.
6
+ *
7
+ * Mobile browsers match universal links (iOS) and app links (Android) against the
8
+ * final URL of a *user-initiated* navigation — following redirects — so both a
9
+ * tapped `<a href="https://www.instagram.com/…">` and a server 302 to the same
10
+ * place can be intercepted by the provider's native app, which has no idea what to
11
+ * do with an OAuth flow. A navigation issued from a freshly loaded document has no
12
+ * gesture token behind it and is never intercepted, so this page loads and
13
+ * immediately replaces itself with `authorizationURL`.
14
+ *
15
+ * `location.replace` keeps the interstitial out of session history, so Back from
16
+ * the provider returns to the page that started the flow. The `noscript` meta
17
+ * refresh is a fallback, not the primary path.
18
+ *
19
+ * @param authorizationURL - Provider authorization URL to hand the browser off to
20
+ * @returns HTML response that redirects client-side
21
+ *
22
+ * @category Auth
23
+ */
24
+ declare function getAuthorizationHandoff(authorizationURL: string): NextResponse<unknown>;
1
25
  /**
2
26
  * Exchanges a long-lived Instagram token for a refreshed token.
3
27
  * @param token - Current long-lived access token
@@ -33,14 +57,16 @@ declare function getLongLivedToken(code: string, redirectURL: string, clientId:
33
57
  *
34
58
  * @example
35
59
  * ```ts
36
- * // In a server route handler:
37
- * import { getInstagramAuthorizationURL } from "naystack/auth";
60
+ * // In a server route handler. Hand off with `getAuthorizationHandoff` rather
61
+ * // than `NextResponse.redirect` a 302 onto instagram.com is still matched as a
62
+ * // universal/app link and opens the Instagram app mid-flow.
63
+ * import { getAuthorizationHandoff, getInstagramAuthorizationURL } from "naystack/auth";
38
64
  *
39
- * return NextResponse.redirect(getInstagramAuthorizationURL(state), 302);
65
+ * return getAuthorizationHandoff(getInstagramAuthorizationURL(state));
40
66
  * ```
41
67
  *
42
68
  * @category Auth
43
69
  */
44
70
  declare const getInstagramAuthorizationURL: (token: string) => string;
45
71
 
46
- export { getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
72
+ export { getAuthorizationHandoff, getInstagramAuthorizationURL, getLongLivedToken, getRefreshedInstagramAccessToken };
@@ -1,3 +1,6 @@
1
+ // src/auth/instagram/utils.ts
2
+ import { NextResponse } from "next/server";
3
+
1
4
  // src/env.ts
2
5
  var EXTRA_ENV = globalThis.__NAYSTACK_ENV__ || (globalThis.__NAYSTACK_ENV__ = {});
3
6
  var getEnvValue = (key) => {
@@ -49,6 +52,24 @@ function getEnv(key, skipCheck) {
49
52
  }
50
53
 
51
54
  // src/auth/instagram/utils.ts
55
+ function getAuthorizationHandoff(authorizationURL) {
56
+ const scriptSafeURL = JSON.stringify(authorizationURL).replace(
57
+ /</g,
58
+ "\\u003c"
59
+ );
60
+ const attributeSafeURL = authorizationURL.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/"/g, "&quot;");
61
+ return new NextResponse(
62
+ `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><title>Connecting\u2026</title><script>location.replace(${scriptSafeURL})</script><noscript><meta http-equiv="refresh" content="0;url=${attributeSafeURL}"></noscript></head><body></body></html>`,
63
+ {
64
+ headers: {
65
+ "content-type": "text/html; charset=utf-8",
66
+ "cache-control": "no-store",
67
+ // The token is in the URL; keep it off the provider's referer log.
68
+ "referrer-policy": "no-referrer"
69
+ }
70
+ }
71
+ );
72
+ }
52
73
  async function getRefreshedInstagramAccessToken(token) {
53
74
  const request = await fetch(
54
75
  `https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token=${token}`
@@ -88,6 +109,7 @@ var getInstagramAuthorizationURL = (token) => `https://www.instagram.com/oauth/a
88
109
  "INSTAGRAM_CLIENT_ID" /* INSTAGRAM_CLIENT_ID */
89
110
  )}&response_type=code&enable_fb_login=0&force_authentication=1&scope=instagram_business_basic&state=${token}&redirect_uri=${getEnv("NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT" /* NEXT_PUBLIC_INSTAGRAM_AUTH_ENDPOINT */)}`;
90
111
  export {
112
+ getAuthorizationHandoff,
91
113
  getInstagramAuthorizationURL,
92
114
  getLongLivedToken,
93
115
  getRefreshedInstagramAccessToken
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "naystack",
3
- "version": "1.8.5",
3
+ "version": "1.8.6",
4
4
  "description": "A stack built with Next + GraphQL + S3 + Auth",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",