Repository: auth0/nextjs-auth0
Pull request #861 (2022-10-13 15:11:13)

move encoding methods
### 📋 Changes

When doing some testing on Vercel I had to move the `TextDecoder` Node dependency out of `hooks/get-login-state` since this is required by `middleware` (via `config`) and not available on Vercel's Edge Runtime.

(It didn't fail in testing because the middlware that comes bundled with Next didn't have an issue with it.)

### 📎 References

<img width="1284" alt="image" src="https://user-images.githubusercontent.com/1299658/195635697-aab033b6-44cd-4911-8c7c-0430fa299f34.png">




Patch:
diff --git a/src/auth0-session/handlers/callback.ts b/src/auth0-session/handlers/callback.ts
index d0447be1..650734a5 100644
--- a/src/auth0-session/handlers/callback.ts
+++ b/src/auth0-session/handlers/callback.ts
@@ -5,7 +5,7 @@ import { errors } from 'openid-client';
 import { AuthorizationParameters, Config } from '../config';
 import { ClientFactory } from '../client';
 import TransientStore from '../transient-store';
-import { decodeState } from '../hooks/get-login-state';
+import { decodeState } from '../utils/encoding';
 import { SessionCache } from '../session-cache';
 import { htmlSafe } from '../../utils/errors';
 import {
diff --git a/src/auth0-session/handlers/login.ts b/src/auth0-session/handlers/login.ts
index bb605f59..4af549dd 100644
--- a/src/auth0-session/handlers/login.ts
+++ b/src/auth0-session/handlers/login.ts
@@ -3,7 +3,7 @@ import urlJoin from 'url-join';
 import { strict as assert } from 'assert';
 import { Config, LoginOptions } from '../config';
 import TransientStore, { StoreOptions } from '../transient-store';
-import { encodeState } from '../hooks/get-login-state';
+import { encodeState } from '../utils/encoding';
 import { ClientFactory } from '../client';
 import createDebug from '../utils/debug';
 import { htmlSafe } from '../../utils/errors';
diff --git a/src/auth0-session/hooks/get-login-state.ts b/src/auth0-session/hooks/get-login-state.ts
index 07df627b..aade6b1e 100644
--- a/src/auth0-session/hooks/get-login-state.ts
+++ b/src/auth0-session/hooks/get-login-state.ts
@@ -1,7 +1,5 @@
-import * as jose from 'jose';
 import createDebug from '../utils/debug';
 import { GetLoginState } from '../config';
-import { TextDecoder } from 'util';
 
 const debug = createDebug('get-login-state');
 
@@ -20,33 +18,3 @@ export const getLoginState: GetLoginState = (_req, options) => {
   debug('adding default state %O', state);
   return state;
 };
-
-/**
- * Prepare a state object to send.
- *
- * @param {object} stateObject
- *
- * @return {string}
- */
-export function encodeState(stateObject: { [key: string]: any }): string {
-  // This filters out nonce, code_verifier, and max_age from the state object so that the values are
-  // only stored in its dedicated transient cookie.
-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const { nonce, code_verifier, max_age, ...filteredState } = stateObject;
-  return jose.base64url.encode(JSON.stringify(filteredState));
-}
-
-/**
- * Decode a state value.
- *
- * @param {string} stateValue
- *
- * @return {object|undefined}
- */
-export function decodeState(stateValue?: string): { [key: string]: any } | undefined {
-  try {
-    return JSON.parse(new TextDecoder().decode(jose.base64url.decode(stateValue as string)));
-  } catch (e) {
-    return undefined;
-  }
-}
diff --git a/src/auth0-session/utils/encoding.ts b/src/auth0-session/utils/encoding.ts
new file mode 100644
index 00000000..aa335450
--- /dev/null
+++ b/src/auth0-session/utils/encoding.ts
@@ -0,0 +1,32 @@
+import * as jose from 'jose';
+import { TextDecoder } from 'util';
+
+/**
+ * Prepare a state object to send.
+ *
+ * @param {object} stateObject
+ *
+ * @return {string}
+ */
+export function encodeState(stateObject: { [key: string]: any }): string {
+  // This filters out nonce, code_verifier, and max_age from the state object so that the values are
+  // only stored in its dedicated transient cookie.
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  const { nonce, code_verifier, max_age, ...filteredState } = stateObject;
+  return jose.base64url.encode(JSON.stringify(filteredState));
+}
+
+/**
+ * Decode a state value.
+ *
+ * @param {string} stateValue
+ *
+ * @return {object|undefined}
+ */
+export function decodeState(stateValue?: string): { [key: string]: any } | undefined {
+  try {
+    return JSON.parse(new TextDecoder().decode(jose.base64url.decode(stateValue as string)));
+  } catch (e) {
+    return undefined;
+  }
+}


Test patch:
diff --git a/tests/auth0-session/handlers/callback.test.ts b/tests/auth0-session/handlers/callback.test.ts
index 4bedf882..a819b344 100644
--- a/tests/auth0-session/handlers/callback.test.ts
+++ b/tests/auth0-session/handlers/callback.test.ts
@@ -2,7 +2,7 @@ import nock from 'nock';
 import { CookieJar } from 'tough-cookie';
 import * as jose from 'jose';
 import { signing as deriveKey } from '../../../src/auth0-session/utils/hkdf';
-import { encodeState } from '../../../src/auth0-session/hooks/get-login-state';
+import { encodeState } from '../../../src/auth0-session/utils/encoding';
 import { SessionResponse, setup, teardown } from '../fixtures/server';
 import { makeIdToken } from '../fixtures/cert';
 import { toSignedCookieJar, get, post, defaultConfig } from '../fixtures/helpers';
diff --git a/tests/auth0-session/handlers/login.test.ts b/tests/auth0-session/handlers/login.test.ts
index c6d0fa6a..22fd6bf5 100644
--- a/tests/auth0-session/handlers/login.test.ts
+++ b/tests/auth0-session/handlers/login.test.ts
@@ -2,7 +2,7 @@ import { parse } from 'url';
 import { CookieJar } from 'tough-cookie';
 import { setup, teardown } from '../fixtures/server';
 import { defaultConfig, fromCookieJar, get, getCookie } from '../fixtures/helpers';
-import { decodeState, encodeState } from '../../../src/auth0-session/hooks/get-login-state';
+import { decodeState, encodeState } from '../../../src/auth0-session/utils/encoding';
 import { LoginOptions } from '../../../src/auth0-session';
 import { IncomingMessage } from 'http';
 
diff --git a/tests/auth0-session/handlers/logout.test.ts b/tests/auth0-session/handlers/logout.test.ts
index 3aa2c5f8..12ec82cb 100644
--- a/tests/auth0-session/handlers/logout.test.ts
+++ b/tests/auth0-session/handlers/logout.test.ts
@@ -3,7 +3,7 @@ import { CookieJar } from 'tough-cookie';
 import { SessionResponse, setup, teardown } from '../fixtures/server';
 import { toSignedCookieJar, defaultConfig, get, post, fromCookieJar } from '../fixtures/helpers';
 import { makeIdToken } from '../fixtures/cert';
-import { encodeState } from '../../../src/auth0-session/hooks/get-login-state';
+import { encodeState } from '../../../src/auth0-session/utils/encoding';
 
 const login = async (baseURL: string): Promise<CookieJar> => {
   const nonce = '__test_nonce__';
diff --git a/tests/fixtures/setup.ts b/tests/fixtures/setup.ts
index e773b368..8a8c99dc 100644
--- a/tests/fixtures/setup.ts
+++ b/tests/fixtures/setup.ts
@@ -18,7 +18,7 @@ import {
 import { codeExchange, discovery, jwksEndpoint, userInfo } from './oidc-nocks';
 import { jwks, makeIdToken } from '../auth0-session/fixtures/cert';
 import { start, stop } from './server';
-import { encodeState } from '../../src/auth0-session/hooks/get-login-state';
+import { encodeState } from '../../src/auth0-session/utils/encoding';
 import { post, toSignedCookieJar } from '../auth0-session/fixtures/helpers';
 import { HandleLogin, HandleLogout, HandleCallback, HandleProfile } from '../../src';
 
diff --git a/tests/handlers/callback.test.ts b/tests/handlers/callback.test.ts
index 0ab11f32..178e045d 100644
--- a/tests/handlers/callback.test.ts
+++ b/tests/handlers/callback.test.ts
@@ -4,7 +4,7 @@ import timekeeper from 'timekeeper';
 import { withApi, withoutApi } from '../fixtures/default-settings';
 import { makeIdToken } from '../auth0-session/fixtures/cert';
 import { defaultConfig, get, post, toSignedCookieJar } from '../auth0-session/fixtures/helpers';
-import { encodeState } from '../../src/auth0-session/hooks/get-login-state';
+import { encodeState } from '../../src/auth0-session/utils/encoding';
 import { defaultOnError, setup, teardown } from '../fixtures/setup';
 import { Session, AfterCallback, MissingStateCookieError } from '../../src';
 import nock from 'nock';
diff --git a/tests/handlers/login.test.ts b/tests/handlers/login.test.ts
index d799316d..5cbaae62 100644
--- a/tests/handlers/login.test.ts
+++ b/tests/handlers/login.test.ts
@@ -1,6 +1,6 @@
 import { parse as urlParse } from 'url';
 import { withoutApi, withApi } from '../fixtures/default-settings';
-import { decodeState } from '../../src/auth0-session/hooks/get-login-state';
+import { decodeState } from '../../src/auth0-session/utils/encoding';
 import { setup, teardown } from '../fixtures/setup';
 import { get, getCookie } from '../auth0-session/fixtures/helpers';
 import { Cookie, CookieJar } from 'tough-cookie';