mirror of
https://github.com/nestriness/nestri.git
synced 2025-12-12 08:45:38 +02:00
chore: Migrate auth to CF Workers
This commit is contained in:
16
bun.lock
16
bun.lock
@@ -61,6 +61,7 @@
|
|||||||
"@aws-sdk/client-s3": "^3.806.0",
|
"@aws-sdk/client-s3": "^3.806.0",
|
||||||
"@aws-sdk/client-sqs": "^3.806.0",
|
"@aws-sdk/client-sqs": "^3.806.0",
|
||||||
"@nestri/core": "workspace:",
|
"@nestri/core": "workspace:",
|
||||||
|
"@openauthjs/openauth": "catalog:",
|
||||||
"actor-core": "^0.8.0",
|
"actor-core": "^0.8.0",
|
||||||
"hono": "^4.7.8",
|
"hono": "^4.7.8",
|
||||||
"hono-openapi": "^0.4.8",
|
"hono-openapi": "^0.4.8",
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
"steamid": "^2.1.0",
|
"steamid": "^2.1.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@cloudflare/workers-types": "4.20250522.0",
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/steamcommunity": "^3.43.8",
|
"@types/steamcommunity": "^3.43.8",
|
||||||
},
|
},
|
||||||
@@ -178,8 +180,8 @@
|
|||||||
"@rocicorp/zero-sqlite3",
|
"@rocicorp/zero-sqlite3",
|
||||||
"protobufjs",
|
"protobufjs",
|
||||||
],
|
],
|
||||||
"overrides": {
|
"catalog": {
|
||||||
"@openauthjs/openauth": "0.4.3",
|
"@openauthjs/openauth": "0.0.0-20250322224806",
|
||||||
"steam-session": "1.9.3",
|
"steam-session": "1.9.3",
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
@@ -3517,6 +3519,10 @@
|
|||||||
|
|
||||||
"@multiformats/dns/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
"@multiformats/dns/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
|
||||||
|
|
||||||
|
"@nestri/functions/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20250522.0", "", {}, "sha512-9RIffHobc35JWeddzBguGgPa4wLDr5x5F94+0/qy7LiV6pTBQ/M5qGEN9VA16IDT3EUpYI0WKh6VpcmeVEtVtw=="],
|
||||||
|
|
||||||
|
"@nestri/functions/@openauthjs/openauth": ["@openauthjs/openauth@0.0.0-20250322224806", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-p5IWSRXvABcwocH2dNI0w8c1QJelIOFulwhKk+aLLFfUbs8u1pr7kQbYe8yCSM2+bcLHiwbogpUQc2ovrGwCuw=="],
|
||||||
|
|
||||||
"@npmcli/agent/agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
|
"@npmcli/agent/agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
|
||||||
|
|
||||||
"@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
"@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||||
@@ -3533,6 +3539,8 @@
|
|||||||
|
|
||||||
"@openauthjs/openevent/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
"@openauthjs/openevent/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
||||||
|
|
||||||
|
"@openauthjs/solid/@openauthjs/openauth": ["@openauthjs/openauth@0.4.2", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-8+Bia559iffrZXfQ0LWXrVVVriochS88pDtB8indyQ1S+40MQgDBu8aBzKt+fgSrTmoQGCTT+wlOXgbjc9qIcw=="],
|
||||||
|
|
||||||
"@opentelemetry/auto-instrumentations-node/@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
|
"@opentelemetry/auto-instrumentations-node/@opentelemetry/core": ["@opentelemetry/core@2.0.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-SLX36allrcnVaPYG3R78F/UZZsBsvbc7lMCLx37LyH5MJ1KAAZ2E3mW9OAD3zGz0G8q/BtoS5VUrjzDydhD6LQ=="],
|
||||||
|
|
||||||
"@opentelemetry/auto-instrumentations-node/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg=="],
|
"@opentelemetry/auto-instrumentations-node/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.200.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.200.0", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-pmPlzfJd+vvgaZd/reMsC8RWgTXn2WY1OWT5RT42m3aOn5532TozwXNDhg1vzqJ+jnvmkREcdLr27ebJEQt0Jg=="],
|
||||||
@@ -4435,6 +4443,10 @@
|
|||||||
|
|
||||||
"@multiformats/dns/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
"@multiformats/dns/buffer/ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
|
||||||
|
|
||||||
|
"@nestri/functions/@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
||||||
|
|
||||||
|
"@openauthjs/solid/@openauthjs/openauth/jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="],
|
||||||
|
|
||||||
"@opentelemetry/auto-instrumentations-node/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
|
"@opentelemetry/auto-instrumentations-node/@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
|
||||||
|
|
||||||
"@opentelemetry/auto-instrumentations-node/@opentelemetry/instrumentation-grpc/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
|
"@opentelemetry/auto-instrumentations-node/@opentelemetry/instrumentation-grpc/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.33.0", "", {}, "sha512-TIpZvE8fiEILFfTlfPnltpBaD3d9/+uQHVCyC3vfdh6WfCXKhNFzoP5RyDDIndfvZC5GrA4pyEDNyjPloJud+w=="],
|
||||||
|
|||||||
0
cloud/infra/auth.ts
Normal file
0
cloud/infra/auth.ts
Normal file
@@ -5,7 +5,8 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bun": "latest",
|
"@types/bun": "latest",
|
||||||
"@types/steamcommunity": "^3.43.8"
|
"@types/steamcommunity": "^3.43.8",
|
||||||
|
"@cloudflare/workers-types": "4.20250522.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
|
import { Select } from "./ui";
|
||||||
import { Resource } from "sst";
|
import { Resource } from "sst";
|
||||||
import { logger } from "hono/logger";
|
import { logger } from "hono/logger";
|
||||||
import { subjects } from "../subjects";
|
import { subjects } from "../subjects";
|
||||||
import { handle } from "hono/aws-lambda";
|
import { handleDiscord } from "./utils";
|
||||||
import { PasswordUI, Select } from "./ui";
|
import { DiscordAdapter } from "./adapters";
|
||||||
import { issuer } from "@openauthjs/openauth";
|
import { issuer } from "@openauthjs/openauth";
|
||||||
import { User } from "@nestri/core/user/index";
|
import { User } from "@nestri/core/user/index";
|
||||||
import { Email } from "@nestri/core/email/index";
|
|
||||||
import { patchLogger } from "../utils/patch-logger";
|
import { patchLogger } from "../utils/patch-logger";
|
||||||
import { handleDiscord, handleGithub } from "./utils";
|
import { CloudflareStorage } from "@openauthjs/openauth/storage/cloudflare";
|
||||||
import { DiscordAdapter, PasswordAdapter, GithubAdapter } from "./adapters";
|
|
||||||
|
interface Env {
|
||||||
|
AuthStorage: KVNamespace;
|
||||||
|
}
|
||||||
|
|
||||||
patchLogger();
|
patchLogger();
|
||||||
|
export default {
|
||||||
const app = issuer({
|
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
||||||
|
return issuer({
|
||||||
select: Select(),
|
select: Select(),
|
||||||
theme: {
|
theme: {
|
||||||
title: "Nestri | Auth",
|
title: "Nestri | Auth",
|
||||||
@@ -22,7 +26,7 @@ const app = issuer({
|
|||||||
favicon: "https://nestri.io/seo/favicon.ico",
|
favicon: "https://nestri.io/seo/favicon.ico",
|
||||||
background: {
|
background: {
|
||||||
light: "#F5F5F5",
|
light: "#F5F5F5",
|
||||||
dark: "#171717"
|
dark: "#171717",
|
||||||
},
|
},
|
||||||
radius: "lg",
|
radius: "lg",
|
||||||
font: {
|
font: {
|
||||||
@@ -31,34 +35,15 @@ const app = issuer({
|
|||||||
css: `@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap');`,
|
css: `@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap');`,
|
||||||
},
|
},
|
||||||
subjects,
|
subjects,
|
||||||
providers: {
|
storage: CloudflareStorage({
|
||||||
github: GithubAdapter({
|
namespace: env.AuthStorage,
|
||||||
clientID: Resource.GithubClientID.value,
|
|
||||||
clientSecret: Resource.GithubClientSecret.value,
|
|
||||||
scopes: ["user:email"]
|
|
||||||
}),
|
}),
|
||||||
|
providers: {
|
||||||
discord: DiscordAdapter({
|
discord: DiscordAdapter({
|
||||||
clientID: Resource.DiscordClientID.value,
|
clientID: Resource.DiscordClientID.value,
|
||||||
clientSecret: Resource.DiscordClientSecret.value,
|
clientSecret: Resource.DiscordClientSecret.value,
|
||||||
scopes: ["email", "identify"]
|
scopes: ["email", "identify"],
|
||||||
}),
|
}),
|
||||||
password: PasswordAdapter(
|
|
||||||
PasswordUI({
|
|
||||||
sendCode: async (email, code) => {
|
|
||||||
// Do not debug show code in production
|
|
||||||
if (Resource.App.stage != "production") {
|
|
||||||
console.log("email & code:", email, code)
|
|
||||||
}
|
|
||||||
await Email.send(
|
|
||||||
"auth",
|
|
||||||
email,
|
|
||||||
`Nestri code: ${code}`,
|
|
||||||
`Your Nestri login code is ${code}`,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
|
|
||||||
},
|
},
|
||||||
allow: async (input) => {
|
allow: async (input) => {
|
||||||
const url = new URL(input.redirectURI);
|
const url = new URL(input.redirectURI);
|
||||||
@@ -68,50 +53,11 @@ const app = issuer({
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
success: async (ctx, value, req) => {
|
success: async (ctx, value, req) => {
|
||||||
if (value.provider === "password") {
|
|
||||||
const email = value.email
|
|
||||||
const username = value.username
|
|
||||||
const matching = await User.fromEmail(email)
|
|
||||||
|
|
||||||
//Sign Up
|
|
||||||
if (username && !matching) {
|
|
||||||
const userID = await User.create({
|
|
||||||
name: username,
|
|
||||||
email,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!userID) throw new Error("Error creating user");
|
|
||||||
|
|
||||||
return ctx.subject("user", {
|
|
||||||
userID,
|
|
||||||
email
|
|
||||||
}, {
|
|
||||||
subject: userID
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (matching) {
|
|
||||||
await User.acknowledgeLogin(matching.id)
|
|
||||||
|
|
||||||
//Sign In
|
|
||||||
return ctx.subject("user", {
|
|
||||||
userID: matching.id,
|
|
||||||
email
|
|
||||||
}, {
|
|
||||||
subject: matching.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let user;
|
let user;
|
||||||
|
|
||||||
if (value.provider === "github") {
|
|
||||||
const access = value.tokenset.access;
|
|
||||||
user = await handleGithub(access)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.provider === "discord") {
|
if (value.provider === "discord") {
|
||||||
const access = value.tokenset.access
|
const access = value.tokenset.access;
|
||||||
user = await handleDiscord(access)
|
user = await handleDiscord(access);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -128,32 +74,26 @@ const app = issuer({
|
|||||||
|
|
||||||
if (!userID) throw new Error("Error creating user");
|
if (!userID) throw new Error("Error creating user");
|
||||||
|
|
||||||
return ctx.subject("user", {
|
return ctx.subject("user", userID, {
|
||||||
userID,
|
userID,
|
||||||
email: user.primary.email
|
email: user.primary.email,
|
||||||
}, {
|
|
||||||
subject: userID
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await User.acknowledgeLogin(matching.id)
|
await User.acknowledgeLogin(matching.id);
|
||||||
|
|
||||||
//Sign In
|
//Sign In
|
||||||
return await ctx.subject("user", {
|
return await ctx.subject("user", matching.id, {
|
||||||
userID: matching.id,
|
userID: matching.id,
|
||||||
email: user.primary.email
|
email: user.primary.email,
|
||||||
}, {
|
|
||||||
subject: matching.id
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("error registering the user", error)
|
console.error("error registering the user", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("Something went seriously wrong");
|
throw new Error("Something went seriously wrong");
|
||||||
},
|
},
|
||||||
}).use(logger())
|
}).use(logger());
|
||||||
|
},
|
||||||
export const handler = handle(app);
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"noUncheckedIndexedAccess": true
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"types": ["@cloudflare/workers-types", "node"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user