Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yellow-shrimps-destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@thirdweb-dev/auth": patch
---

Add support for next-auth
3 changes: 3 additions & 0 deletions packages/auth/next-auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"main": "dist/thirdweb-dev-auth-next-auth.cjs.js"
}
10 changes: 7 additions & 3 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"files": [
"dist/",
"next/",
"express/"
"express/",
"next-auth/"
],
"scripts": {
"build": "preconstruct build",
Expand All @@ -20,7 +21,8 @@
"preconstruct": {
"entrypoints": [
"next/index.ts",
"express/index.ts"
"express/index.ts",
"next-auth/index.ts"
]
},
"devDependencies": {
Expand All @@ -45,14 +47,16 @@
"ethers": ">=5.5.1",
"express": "^4.18.1",
"next": "12.2.0",
"next-auth": "^4.10.3",
"prettier": "^2.7.1",
"typescript": "^4.7.4"
},
"peerDependencies": {
"@thirdweb-dev/sdk": "*",
"ethers": ">=5.5.1",
"express": "^4.18.1",
"next": "12.2.0"
"next": "12.2.0",
"next-auth": "^4.10.3"
},
"dependencies": {
"cookie": "^0.5.0",
Expand Down
135 changes: 135 additions & 0 deletions packages/auth/src/next-auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { ThirdwebNextAuthConfig } from "./types";
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
import { serialize } from "cookie";
import { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from "next";
import NextAuth, { NextAuthOptions, Session, unstable_getServerSession } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export function ThirdwebNextAuth(cfg: ThirdwebNextAuthConfig) {
const sdk = ThirdwebSDK.fromPrivateKey(cfg.privateKey, "mainnet");

function ThirdwebProvider(res: GetServerSidePropsContext["res"]) {
return CredentialsProvider({
name: "ThirdwebAuth",
credentials: {
payload: {
label: "Payload",
type: "text",
placeholder: "",
},
},
async authorize({ payload }: any) {
try {
const parsed = JSON.parse(payload);
const token = await sdk.auth.generateAuthToken(
cfg.domain,
parsed
);
const address = await sdk.auth.authenticate(cfg.domain, token);

// Securely set httpOnly cookie on request to prevent XSS on frontend
// And set path to / to enable thirdweb_auth_token usage on all endpoints
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
})
);

return { address };
} catch (err) {
return null;
}
},
});
}

function nextOptions (
req: GetServerSidePropsContext["req"],
res: GetServerSidePropsContext["res"]
): NextAuthOptions {

async function session({ session }: { session: Session }) {
const token = req.cookies.thirdweb_auth_token || "";
try {
const address = await sdk.auth.authenticate(cfg.domain, token);
session.user = { ...session.user, address } as Session["user"];
return session;
} catch {
return session;
}
}

function signOut() {
res.setHeader(
"Set-Cookie",
serialize("thirdweb_auth_token", "", {
path: "/",
expires: new Date(Date.now() + 5 * 1000),
})
);
}

const providers: NextAuthOptions["providers"] = [
...cfg.nextOptions.providers,
ThirdwebProvider(res),
]

const configSession = cfg.nextOptions.callbacks?.session
const callbacks: NextAuthOptions["callbacks"] = {
...cfg.nextOptions.callbacks,
session: configSession
? async (params) => {
params.session = await session(params);
return configSession(params);
}
: session
};

const configSignOut = cfg.nextOptions.events?.signOut
const events: NextAuthOptions["events"] = {
...cfg.nextOptions.events,
signOut: configSignOut
? async (params) => {
signOut();
return configSignOut(params);
}
: signOut
};

return {
...cfg.nextOptions,
providers,
callbacks,
events,
};
};

async function getUser(
...args:
| [NextApiRequest, NextApiResponse]
| [GetServerSidePropsContext["req"], GetServerSidePropsContext["res"]]
) {
return unstable_getServerSession(args[0], args[1], nextOptions(args[0], args[1]));
}

function NextAuthHandler(
...args: [] | [NextApiRequest, NextApiResponse]
) {
if (args.length === 0) {
return (req: NextApiRequest, res: NextApiResponse) => {
return NextAuth(req, res, nextOptions(req, res));
}
}

return NextAuth(args[0], args[1], nextOptions(args[0], args[1]));
}

return {
NextAuthHandler,
getUser
}
}
7 changes: 7 additions & 0 deletions packages/auth/src/next-auth/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { NextAuthOptions } from "next-auth";

export type ThirdwebNextAuthConfig = {
privateKey: string;
domain: string;
nextOptions: NextAuthOptions;
}
2 changes: 1 addition & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
]
},
"auth#build": {
"outputs": ["dist/**", "express/**", "next/**"]
"outputs": ["dist/**", "express/**", "next/**", "next-auth/**"]
},
"test": {
"outputs": [],
Expand Down
66 changes: 64 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@
core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4"

"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.4":
"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.4":
version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
Expand Down Expand Up @@ -2436,6 +2436,11 @@
resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.5.tgz#131b0da1b71680d5a01569f916ae878229d326d3"
integrity sha512-A2gZAGB6kUvLx+kzM92HKuUF33F1FSe90L0TmkXkT2Hh0OKRpvWZURUSU2nghD2yC4DzfEZ3DftfeHGvZ2JTUw==

"@panva/hkdf@^1.0.1":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@panva/hkdf/-/hkdf-1.0.2.tgz#bab0f09d09de9fd83628220d496627681bc440d6"
integrity sha512-MSAs9t3Go7GUkMhpKC44T58DJ5KGk2vBo+h1cqQeqlMfdGkxaVB78ZWpv9gYi/g2fa4sopag9gJsNvS8XGgWJA==

"@pedrouid/environment@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec"
Expand Down Expand Up @@ -8220,6 +8225,11 @@ joi@^17.4.0:
"@sideway/formula" "^3.0.0"
"@sideway/pinpoint" "^2.0.0"

jose@^4.1.4, jose@^4.3.7:
version "4.9.1"
resolved "https://registry.yarnpkg.com/jose/-/jose-4.9.1.tgz#c1eef9f20f479d8aa55cdfd4bbc3d76322dd1b48"
integrity sha512-ETgCfJ2yxJavpJdVMgznN8ot3MJyZUiLyY2xiZ2sSNL/uEZh1EH74cmNYWhZgMSBwSdSz03ja5cMZU/9BSlqXg==

joycon@^3.0.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
Expand Down Expand Up @@ -9259,6 +9269,21 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0:
resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5"
integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==

next-auth@^4.10.3:
version "4.10.3"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.10.3.tgz#0a952dd5004fd2ac2ba414c990922cf9b33951a3"
integrity sha512-7zc4aXYc/EEln7Pkcsn21V1IevaTZsMLJwapfbnKA4+JY0+jFzWbt5p/ljugesGIrN4VOZhpZIw50EaFZyghJQ==
dependencies:
"@babel/runtime" "^7.16.3"
"@panva/hkdf" "^1.0.1"
cookie "^0.4.1"
jose "^4.3.7"
oauth "^0.9.15"
openid-client "^5.1.0"
preact "^10.6.3"
preact-render-to-string "^5.1.19"
uuid "^8.3.2"

next-tick@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
Expand Down Expand Up @@ -9419,11 +9444,21 @@ o3@^1.0.3:
dependencies:
capability "^0.2.5"

oauth@^0.9.15:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==

object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==

object-hash@^2.0.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==

object-inspect@^1.12.0, object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
Expand Down Expand Up @@ -9499,6 +9534,11 @@ [email protected]:
dependencies:
http-https "^1.0.0"

oidc-token-hash@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-5.0.1.tgz#ae6beec3ec20f0fd885e5400d175191d6e2f10c6"
integrity sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ==

[email protected]:
version "2.4.1"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
Expand Down Expand Up @@ -9529,6 +9569,16 @@ open@^8.4.0:
is-docker "^2.1.1"
is-wsl "^2.2.0"

openid-client@^5.1.0:
version "5.1.9"
resolved "https://registry.yarnpkg.com/openid-client/-/openid-client-5.1.9.tgz#6887e75ad3fa8d0c78d0ed693a5ea107d39b54de"
integrity sha512-o/11Xos2fRPpK1zQrPfSIhIusFrAkqGSPwkD0UlUB+CCuRzd7zrrBJwIjgnVv3VUSif9ZGXh2d3GSJNH2Koh5g==
dependencies:
jose "^4.1.4"
lru-cache "^6.0.0"
object-hash "^2.0.1"
oidc-token-hash "^5.0.1"

optionator@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
Expand Down Expand Up @@ -9884,12 +9934,19 @@ [email protected]:
picocolors "^1.0.0"
source-map-js "^1.0.1"

preact-render-to-string@^5.1.19:
version "5.2.2"
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.2.tgz#865174418f2e4e8e37fc40f1a20c5a23dfdc0971"
integrity sha512-ZBPfzWmHjasQIzysj72VYJ6oa2bphpxNvzLRdRj/XGFKyeTBJIDmoiKJlBGfxzU4TYL2CjpAWmcFIXcV+HQEBg==
dependencies:
pretty-format "^3.8.0"

[email protected]:
version "10.4.1"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431"
integrity sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q==

preact@^10.5.9:
preact@^10.5.9, preact@^10.6.3:
version "10.10.6"
resolved "https://registry.yarnpkg.com/preact/-/preact-10.10.6.tgz#1fe62aecf93974b64e6a42e09ba1f00f93207d14"
integrity sha512-w0mCL5vICUAZrh1DuHEdOWBjxdO62lvcO++jbzr8UhhYcTbFkpegLH9XX+7MadjTl/y0feoqwQ/zAnzkc/EGog==
Expand Down Expand Up @@ -9935,6 +9992,11 @@ pretty-format@^29.0.1:
ansi-styles "^5.0.0"
react-is "^18.0.0"

pretty-format@^3.8.0:
version "3.8.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385"
integrity sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==

process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
Expand Down