@synqauth/nextjs 0.3.0 → 0.4.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/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/proxy.js +1 -1
- package/dist/{sites-JUnMBDbp.js → sites-BQ8NPcXw.js} +76 -9
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -109,7 +109,7 @@ interface SynqSignInError {
|
|
|
109
109
|
/** Signs in as someone else (`prompt=select_account`), back to the same page. */
|
|
110
110
|
readonly anotherAccountPath: string;
|
|
111
111
|
}
|
|
112
|
-
/** What a sign-in error code means, in plain words. */
|
|
112
|
+
/** What a sign-in error code means, in plain words: whose side it is on, and what to do. */
|
|
113
113
|
export declare function signInErrorMessage(code: string): string;
|
|
114
114
|
//#endregion
|
|
115
115
|
//#region src/index.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as signInErrorMessage, d as memorySessionStore, f as defineSynqPlugin, h as resolveConfig, i as SIGN_IN_ERROR_PARAM, l as createSynqCore, m as normalizePath, n as unknownHostError, o as signInErrorOf, r as unknownHostResponse, t as siteCores, u as keyValueSessionStore } from "./sites-
|
|
1
|
+
import { a as signInErrorMessage, d as memorySessionStore, f as defineSynqPlugin, h as resolveConfig, i as SIGN_IN_ERROR_PARAM, l as createSynqCore, m as normalizePath, n as unknownHostError, o as signInErrorOf, r as unknownHostResponse, t as siteCores, u as keyValueSessionStore } from "./sites-BQ8NPcXw.js";
|
|
2
2
|
import { defineSynqConfig } from "./define.js";
|
|
3
3
|
import { cookies, headers } from "next/headers.js";
|
|
4
4
|
import { cache } from "react";
|
package/dist/proxy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as withoutSignInError, h as resolveConfig, i as SIGN_IN_ERROR_PARAM, l as createSynqCore, m as normalizePath, o as signInErrorOf, p as requestJar, r as unknownHostResponse, s as signInErrorPage, t as siteCores } from "./sites-
|
|
1
|
+
import { c as withoutSignInError, h as resolveConfig, i as SIGN_IN_ERROR_PARAM, l as createSynqCore, m as normalizePath, o as signInErrorOf, p as requestJar, r as unknownHostResponse, s as signInErrorPage, t as siteCores } from "./sites-BQ8NPcXw.js";
|
|
2
2
|
import { NextResponse } from "next/server.js";
|
|
3
3
|
//#region src/proxy.ts
|
|
4
4
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SynqError, createSynqClient, isSynqError, memoryStorage, readMethodList, signInMethods } from "@synqauth/js";
|
|
1
|
+
import { SynqError, createSynqClient, isSynqError, memoryStorage, readMethodList, signInEndingOf, signInMethods } from "@synqauth/js";
|
|
2
2
|
//#region src/crypto.ts
|
|
3
3
|
const encoder = new TextEncoder();
|
|
4
4
|
const decoder = new TextDecoder();
|
|
@@ -380,7 +380,7 @@ function popupPage(result) {
|
|
|
380
380
|
...result
|
|
381
381
|
};
|
|
382
382
|
const data = JSON.stringify(message).replaceAll("<", "\\u003c");
|
|
383
|
-
const words = result.ok ? "You’re signed in. You can close this window." : "
|
|
383
|
+
const words = result.ok ? "You’re signed in. You can close this window." : "Sign-in didn’t finish. Close this window and try again from the app.";
|
|
384
384
|
const html = `<!doctype html>
|
|
385
385
|
<html lang="en">
|
|
386
386
|
<head>
|
|
@@ -1224,7 +1224,13 @@ function createSynqCore(config) {
|
|
|
1224
1224
|
try {
|
|
1225
1225
|
await client(handle.storage(config.primary, config.primary), config.primary, tx.storage).handleCallback(request.url);
|
|
1226
1226
|
} catch (error) {
|
|
1227
|
-
|
|
1227
|
+
const code = isSynqError(error) ? signInEndingOf(error.description) ?? error.code : "server_error";
|
|
1228
|
+
if (!QUIET_SIGN_IN_ERRORS.has(code)) console.error("@synqauth/nextjs: sign-in callback failed", {
|
|
1229
|
+
code,
|
|
1230
|
+
status: isSynqError(error) ? error.status : void 0,
|
|
1231
|
+
requestId: isSynqError(error) ? error.requestId : void 0
|
|
1232
|
+
});
|
|
1233
|
+
return failed(code);
|
|
1228
1234
|
}
|
|
1229
1235
|
if (tx.found.reauthenticate !== void 0) {
|
|
1230
1236
|
const refused = await reauthenticationRefused(jar, handle, tx.found.reauthenticate);
|
|
@@ -1737,7 +1743,10 @@ function createSynqCore(config) {
|
|
|
1737
1743
|
const rest = url.pathname.slice(prefix.length);
|
|
1738
1744
|
const [first = "", ...tail] = rest.split("/");
|
|
1739
1745
|
const jar = requestJar(request);
|
|
1740
|
-
if (!["GET", "HEAD"].includes(request.method) && !sameOrigin(request, config.appUrl))
|
|
1746
|
+
if (!["GET", "HEAD"].includes(request.method) && !sameOrigin(request, config.appUrl)) {
|
|
1747
|
+
reportOriginMismatch(request, config.appUrl);
|
|
1748
|
+
return problem(403, "origin_mismatch", "This change came from another address than the app's own pages (appUrl)");
|
|
1749
|
+
}
|
|
1741
1750
|
let response;
|
|
1742
1751
|
try {
|
|
1743
1752
|
if (rest === "sign-in" && request.method === "GET") response = await signIn(request, jar);
|
|
@@ -1760,6 +1769,12 @@ function createSynqCore(config) {
|
|
|
1760
1769
|
else if (!RESERVED.has(first)) response = await plugin(request, jar, first, tail.join("/"));
|
|
1761
1770
|
} catch (error) {
|
|
1762
1771
|
if (!isSynqError(error)) throw error;
|
|
1772
|
+
if (error.status === void 0 || error.status >= 500) console.error("@synqauth/nextjs: a route under the mount failed", {
|
|
1773
|
+
route: rest,
|
|
1774
|
+
code: error.code,
|
|
1775
|
+
status: error.status,
|
|
1776
|
+
requestId: error.requestId
|
|
1777
|
+
});
|
|
1763
1778
|
response = problem(error.status && error.status >= 400 ? 502 : 500, error.code, error.message);
|
|
1764
1779
|
}
|
|
1765
1780
|
response ??= problem(404, "not_found", "No such route under the mount");
|
|
@@ -1843,6 +1858,30 @@ function sameOrigin(request, appUrl) {
|
|
|
1843
1858
|
if (origin) return origin === appUrl.origin;
|
|
1844
1859
|
return request.headers.get("sec-fetch-site") === "same-origin";
|
|
1845
1860
|
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Sign-in errors that are the person's own doing or an expected step, which
|
|
1863
|
+
* no server log needs to hear of (AERO-2757).
|
|
1864
|
+
*/
|
|
1865
|
+
const QUIET_SIGN_IN_ERRORS = /* @__PURE__ */ new Set([
|
|
1866
|
+
"access_denied",
|
|
1867
|
+
"login_required",
|
|
1868
|
+
"interaction_required",
|
|
1869
|
+
"consent_required",
|
|
1870
|
+
"account_selection_required",
|
|
1871
|
+
"cancelled",
|
|
1872
|
+
"consent_denied",
|
|
1873
|
+
"token_gate_refused",
|
|
1874
|
+
"passkey_required",
|
|
1875
|
+
"unknown_state"
|
|
1876
|
+
]);
|
|
1877
|
+
let originMismatchReported = false;
|
|
1878
|
+
/** Says once per process which origin the mount refused, and what appUrl says (AERO-2757). */
|
|
1879
|
+
function reportOriginMismatch(request, appUrl) {
|
|
1880
|
+
if (originMismatchReported) return;
|
|
1881
|
+
originMismatchReported = true;
|
|
1882
|
+
const origin = request.headers.get("origin") ?? request.headers.get("sec-fetch-site") ?? "unknown";
|
|
1883
|
+
console.error(`@synqauth/nextjs: refused a change from ${origin}: appUrl is ${appUrl.origin}. Set appUrl (or SYNQ_APP_URL) to the origin people use.`);
|
|
1884
|
+
}
|
|
1846
1885
|
function withError(target, code) {
|
|
1847
1886
|
const url = new URL(target);
|
|
1848
1887
|
url.searchParams.set("synq_error", code);
|
|
@@ -1884,19 +1923,47 @@ const SIGN_IN_ERROR_PARAM = "synq_error";
|
|
|
1884
1923
|
/** An OAuth or SDK error code, as the route mount puts it there. */
|
|
1885
1924
|
const CODE = /^[a-z0-9_]{1,64}$/;
|
|
1886
1925
|
const MESSAGES = {
|
|
1887
|
-
access_denied: "
|
|
1926
|
+
access_denied: "This account can’t use this app, or the sign-in was canceled. Sign in again, or use another account.",
|
|
1927
|
+
cancelled: "You canceled signing in. Sign in when you’re ready.",
|
|
1928
|
+
consent_denied: "You didn’t allow this app to use your account. Sign in again to allow it.",
|
|
1929
|
+
token_gate_refused: "This account’s wallets don’t hold what this app asks for. Use another account, or add the wallet that holds it.",
|
|
1930
|
+
token_gate_unavailable: "We couldn’t check your wallets. That’s a problem on Synq’s side, not yours. Try again in a minute.",
|
|
1931
|
+
passkey_required: "This app needs you to sign in with a passkey.",
|
|
1932
|
+
unmet_authentication_requirements: "This app needs you to sign in with a passkey.",
|
|
1933
|
+
level_not_met: "This app needs you to sign in with a passkey.",
|
|
1888
1934
|
login_required: "You need to sign in to continue.",
|
|
1889
1935
|
interaction_required: "You need to sign in to continue.",
|
|
1890
1936
|
consent_required: "You need to allow this app to use your account to continue.",
|
|
1891
1937
|
account_selection_required: "Choose an account to continue.",
|
|
1892
|
-
temporarily_unavailable: "Signing in
|
|
1893
|
-
|
|
1938
|
+
temporarily_unavailable: "Signing in is down for a moment on Synq’s side. Try again in a minute.",
|
|
1939
|
+
server_error: "Synq had a problem finishing your sign-in. Try again in a minute.",
|
|
1940
|
+
invalid_grant: "This sign-in expired or was already used. Sign in again.",
|
|
1941
|
+
unknown_state: "This sign-in expired, or it finished in another tab. Sign in again.",
|
|
1894
1942
|
other_account: "That signed in to another account. Confirm with a way in of the account signed in here.",
|
|
1895
1943
|
not_signed_in: "You were signed out. Sign in again."
|
|
1896
1944
|
};
|
|
1897
|
-
/**
|
|
1945
|
+
/**
|
|
1946
|
+
* The app's own setup, which only its team can fix: retrying gets the same
|
|
1947
|
+
* answer, and nothing the person does changes it.
|
|
1948
|
+
*/
|
|
1949
|
+
const APP_SETUP = /* @__PURE__ */ new Set([
|
|
1950
|
+
"invalid_client",
|
|
1951
|
+
"unauthorized_client",
|
|
1952
|
+
"invalid_scope",
|
|
1953
|
+
"invalid_request",
|
|
1954
|
+
"invalid_response",
|
|
1955
|
+
"invalid_redirect_uri",
|
|
1956
|
+
"unsupported_response_type",
|
|
1957
|
+
"discovery_failed",
|
|
1958
|
+
"method_not_offered",
|
|
1959
|
+
"origin_mismatch"
|
|
1960
|
+
]);
|
|
1961
|
+
/** What a sign-in error code means, in plain words: whose side it is on, and what to do. */
|
|
1898
1962
|
function signInErrorMessage(code) {
|
|
1899
|
-
|
|
1963
|
+
const said = MESSAGES[code];
|
|
1964
|
+
if (said) return said;
|
|
1965
|
+
if (APP_SETUP.has(code)) return `This app’s sign-in isn’t set up right, so it can’t finish. It’s not something you did: tell the app’s team (code ${code}).`;
|
|
1966
|
+
return `Your sign-in didn’t finish (code ${code}). Try again, and if it keeps happening, tell the app’s team.`;
|
|
1900
1967
|
}
|
|
1901
1968
|
/** A path and query on the app, without `synq_error`: where the ways on come back to. */
|
|
1902
1969
|
function withoutSignInError(pathAndSearch) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synqauth/nextjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Synq for Next.js: a backend-for-frontend session, so the browser never holds a Synq token.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@synqauth/js": "0.
|
|
42
|
+
"@synqauth/js": "0.4.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"next": ">=16.0.0",
|