From 5a73f95d37a324524ca656b83bf274f82ffea6fd Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Fri, 21 Jul 2023 23:02:58 -0600 Subject: [PATCH 01/13] WIP working when redirected from web browser --- console/src/routes/+layout.svelte | 199 ------------------------------ console/src/services/jsdb.ts | 2 +- sdk/package-lock.json | 50 +------- sdk/src/index.ts | 50 ++++++-- server/http/auth.js | 20 +++ server/http/base.js | 2 +- server/package.json | 1 + server/runtimes/node/index.js | 104 ++++++++++++++-- 8 files changed, 156 insertions(+), 272 deletions(-) delete mode 100644 console/src/routes/+layout.svelte diff --git a/console/src/routes/+layout.svelte b/console/src/routes/+layout.svelte deleted file mode 100644 index 235b8ab..0000000 --- a/console/src/routes/+layout.svelte +++ /dev/null @@ -1,199 +0,0 @@ - - -{#if $auth?.token} - - -{:else} - -
-
-

JavascriptDB Console

-
- -
-
-
-
- -
- -
-
- -
- -
- -
-
- - - -
- -
-
- - -
-
-
-{/if} - diff --git a/console/src/services/jsdb.ts b/console/src/services/jsdb.ts index 9a52b74..72ce73a 100644 --- a/console/src/services/jsdb.ts +++ b/console/src/services/jsdb.ts @@ -1,3 +1,3 @@ import {initApp} from "@jsdb/sdk"; -export const {auth, db} = await initApp({serverUrl: 'http://localhost:3001', connector: 'HTTP'}) \ No newline at end of file +export const {auth, db} = await initApp({serverUrl: 'http://localhost:3001', connector: 'HTTP'}) diff --git a/sdk/package-lock.json b/sdk/package-lock.json index 8c1b624..d545623 100644 --- a/sdk/package-lock.json +++ b/sdk/package-lock.json @@ -1,17 +1,13 @@ { "name": "@jsdb/sdk", - "version": "0.0.42", + "version": "0.0.45", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@jsdb/sdk", - "version": "0.0.42", + "version": "0.0.45", "license": "MIT", - "dependencies": { - "isomorphic-ws": "^4.0.1", - "ws": "^8.5.0" - }, "devDependencies": { "@size-limit/preset-small-lib": "^7.0.8", "@types/lodash-es": "^4.17.6", @@ -22,7 +18,7 @@ "typescript": "^3.9.10" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/@ampproject/remapping": { @@ -6901,14 +6897,6 @@ "node": ">=0.10.0" } }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "peerDependencies": { - "ws": "*" - } - }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -12236,26 +12224,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -17386,12 +17354,6 @@ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true }, - "isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "requires": {} - }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -21626,12 +21588,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "requires": {} - }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 18f2875..476fc64 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -161,19 +161,47 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con this.set({}); }; + async signInWithProvider(provider: string) { + const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { + method: "get", + mode: 'cors', + }) + const { csrfToken } = await csrfTokenResp.json() + const callbackUrl = window.location.origin; + const signInResp = await fetch(baseUrl + `/auth/signin/${provider}`, { + method: "post", + mode: 'cors', + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: new URLSearchParams({ + csrfToken, + callbackUrl + }), + }) + console.log(signInResp) + + // debugger + // // const data = await signInResp.json() + // // window.location.href = data.url ?? callbackUrl + // console.log(signInResp) + } + signIn = async (credentials: { email: string, password: string }) => { - try { - const {token, userId} = await request('/auth/signin', {...credentials}); - this.set({token, userId}); - if (typeof process !== 'object') { - localStorage.token = this.value.token; - localStorage.userId = this.value.userId; + try { + location.href = baseUrl + '/auth/signin'; + console.log(credentials) + // this.set({token, userId}) + // if (typeof process !== 'object') { + // localStorage.token = this.value.token; + // localStorage.userId = this.value.userId; + // } + // return true; + } catch (e) { + console.error(e); + throw new Error(`Error logging in, verify email and password`); } - return true; - } catch (e) { - throw new Error(`Error logging in, verify email and password`); - } - }; + } createAccount = async (credentials: { email: string, password: string }) => { try { diff --git a/server/http/auth.js b/server/http/auth.js index e69de29..51b700b 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -0,0 +1,20 @@ +/* +import { Auth } from "@auth/core" + + + +async function main() { + const url = new URL('https://example.com/api/auth/signin') + const request = new Request(url); + const response = await Auth(request, optionsEnvVar) + + const { status = 200 } = response + const data = await response.json() + + if (!data || !Object.keys(data).length) return null + if (status === 200) return data + throw new Error(data.message) +} +main().then(() => console.log('done')) + +*/ diff --git a/server/http/base.js b/server/http/base.js index 93f69f2..eb6ab0a 100644 --- a/server/http/base.js +++ b/server/http/base.js @@ -19,4 +19,4 @@ export async function route(path, body, user, skipSecurityRules, skipTrigger) { } else if (module === 'storage') { return routeStorage(operation, body); } -} \ No newline at end of file +} diff --git a/server/package.json b/server/package.json index c75a36f..9db5425 100644 --- a/server/package.json +++ b/server/package.json @@ -11,6 +11,7 @@ "author": "jpcapdevila", "license": "SSPL", "dependencies": { + "@auth/core": "^0.9.0", "@jsdb/sdk": "file:../sdk", "acorn": "^8.7.1", "aws4fetch": "^1.0.17", diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index af3da86..0464166 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -4,27 +4,105 @@ import {route} from '../../http/base.js'; import {parseData, readStreamToPromise} from '../../utils.js'; import jwt from 'jsonwebtoken'; import {getEventStore} from '../../ws/ws.js'; +import {Auth} from '@auth/core'; +import GitHub from '@auth/core/providers/github'; const wsServer = new WebSocketServer({noServer: true}); -const hostname = '0.0.0.0'; +const hostname = 'localhost' const port = process.env.PORT || 3001; +const optionsEnvVar = { + // Configure one or more authentication providers + providers: [ + GitHub({ + clientId: '8a9219d06d63a95bf1af', + clientSecret: '746ce3dd62cfbd400289e7647063ecc907ffab17', + }), + ], + trustHost: true, + secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687' +} +async function getBody(request) { + return new Promise((resolve) => { + const bodyParts = []; + let body; + request.on('data', (chunk) => { + bodyParts.push(chunk); + }).on('end', () => { + body = Buffer.concat(bodyParts).toString(); + resolve(body) + }); + }); +} + +async function convertIncomingMessageToRequest(req){ + var headers = new Headers(); + for (var key in req.headers) { + if (req.headers[key]) headers.append(key, req.headers[key]); + } + const url = new URL(req.url, `http://${req.headers.host}`); + const body = req.method === 'POST' ? await getBody(req) : null; + let request = new Request(url, { + method: req.method, + body, + headers, + }) + return request +} + + const server = http.createServer(async (req, res) => { - if (req.method === 'POST') { - const bodyString = await readStreamToPromise(req); - const body = parseData(bodyString); - const result = await route(req.url, body); - if (result?.error) { - res.statusCode = result.statusCode || 500; - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(result.error)); + try { + // req.url is /auth/signin + // Auth.js library expects http://localhost:3001/auth/signin + + const headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET', + 'Access-Control-Allow-Headers': '*', + }; + if (req.method === 'OPTIONS') { + res.writeHead(204, headers); + res.end(); + return; + } + const request = await convertIncomingMessageToRequest(req) + const auth = await Auth(request, optionsEnvVar); + + if(req.url.includes('/auth/signin/') && request.method === 'POST' && auth.status === 302 && auth.headers.get('location')) { + headers.Location = auth.headers.get('location') + res.writeHead(302, headers); + console.log('here') + // res.writeHead(200, headers); + return res.end(); } else { - res.statusCode = 200; - res.setHeader('Content-Type', 'application/json'); - res.end(JSON.stringify(result ?? null)); + const text = await auth.text() + headers['Content-Type'] = 'text/html' + res.writeHead(200, headers); + res.write(text) + return res.end(); } + + } catch (e) { + console.log(e) + return res.end(); } + // if (req.method === 'POST') { + // const bodyString = await readStreamToPromise(req); + // const body = parseData(bodyString); + // const result = await route(req.url, body); + // if (result?.error) { + // res.statusCode = result.statusCode || 500; + // res.setHeader('Content-Type', 'application/json'); + // res.end(JSON.stringify(result.error)); + // } else { + // res.statusCode = 200; + // res.setHeader('Content-Type', 'application/json'); + // res.end(JSON.stringify(result ?? null)); + // } + // } + // res.end(); }); server.listen(port, hostname, () => { @@ -78,4 +156,4 @@ wsServer.on('connection', socket => { } } }); -}); \ No newline at end of file +}); From 879cd334d4dcc24b08bf05b32dadeeea492fcf74 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 22 Jul 2023 16:19:05 -0600 Subject: [PATCH 02/13] WIP from signin fnc, redirection not allowed --- sdk/src/index.ts | 62 +++++++++++++++++------------------ server/runtimes/node/index.js | 29 ++++++++++++---- 2 files changed, 54 insertions(+), 37 deletions(-) diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 476fc64..c47ea3c 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -155,37 +155,37 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con } } - signOut = () => { - delete localStorage.token; - delete localStorage.userId; - this.set({}); - }; - - async signInWithProvider(provider: string) { - const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { - method: "get", - mode: 'cors', - }) - const { csrfToken } = await csrfTokenResp.json() - const callbackUrl = window.location.origin; - const signInResp = await fetch(baseUrl + `/auth/signin/${provider}`, { - method: "post", - mode: 'cors', - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - body: new URLSearchParams({ - csrfToken, - callbackUrl - }), - }) - console.log(signInResp) - - // debugger - // // const data = await signInResp.json() - // // window.location.href = data.url ?? callbackUrl - // console.log(signInResp) - } + signOut = () => { + delete localStorage.token; + delete localStorage.userId; + this.set({}) + } + async signInWithProvider(provider: string) { + const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { + credentials: "include", + method: "get", + mode: 'cors', + }) + const { csrfToken } = await csrfTokenResp.json() + const callbackUrl = window.location.origin; + const signInResp = await fetch(baseUrl + `/auth/signin/${provider}`, { + method: "post", + credentials: "include", + mode: 'cors', + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + body: new URLSearchParams({ + csrfToken, + callbackUrl + }), + }) + + const data = await signInResp.json() + debugger + window.location.href = data.url ?? callbackUrl + console.log(provider , csrfToken, callbackUrl, signInResp) + } signIn = async (credentials: { email: string, password: string }) => { try { diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index 0464166..7eaec2d 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -41,9 +41,9 @@ async function convertIncomingMessageToRequest(req){ for (var key in req.headers) { if (req.headers[key]) headers.append(key, req.headers[key]); } - const url = new URL(req.url, `http://${req.headers.host}`); const body = req.method === 'POST' ? await getBody(req) : null; - let request = new Request(url, { + const baseUrl = req.headers.origin || `http://${req.headers.host}` + let request = new Request(new URL(req.url, baseUrl), { method: req.method, body, headers, @@ -58,23 +58,40 @@ const server = http.createServer(async (req, res) => { // Auth.js library expects http://localhost:3001/auth/signin const headers = { - 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET', 'Access-Control-Allow-Headers': '*', }; + headers['Access-Control-Allow-Credentials'] = true + if(req.headers.origin) { + headers['Access-Control-Allow-Origin'] = req.headers.origin + } if (req.method === 'OPTIONS') { res.writeHead(204, headers); res.end(); return; } + // pre-flight does not allow + const request = await convertIncomingMessageToRequest(req) - const auth = await Auth(request, optionsEnvVar); - if(req.url.includes('/auth/signin/') && request.method === 'POST' && auth.status === 302 && auth.headers.get('location')) { + const auth = await Auth(request, optionsEnvVar); + for (const headerName of auth.headers.keys()) { + const header = auth.headers.get(headerName); + headers[headerName]= header + } + if(req.url === '/auth/csrf' && req.headers.origin) { + const body = await auth.json(); + console.log('1'+body.csrfToken) + headers['access-control-expose-headers'] = 'set-cookie' + // headers['Set-Cookie']= `next-auth.csrf-token=${body.csrfToken}; next-auth.callback-url=${req.headers.origin}` + // headers['Set-Cookie'] = auth.headers.get('set-cookie') + res.writeHead(200, headers); + res.write(JSON.stringify(body)) + return res.end(); + } else if(req.url.includes('/auth/signin/') && request.method === 'POST' && auth.status === 302 && auth.headers.get('location')) { headers.Location = auth.headers.get('location') res.writeHead(302, headers); console.log('here') - // res.writeHead(200, headers); return res.end(); } else { const text = await auth.text() From 0666a412d79990a6c6e92bd3dead97736f37a3b2 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 22 Jul 2023 23:53:47 -0600 Subject: [PATCH 03/13] Working with both default page and custom method, just until the github landing, todo OAUTH flow --- sdk/src/index.ts | 11 +++++------ server/runtimes/node/index.js | 27 +++++++++++++++------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/sdk/src/index.ts b/sdk/src/index.ts index c47ea3c..7c5172c 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -168,10 +168,11 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con }) const { csrfToken } = await csrfTokenResp.json() const callbackUrl = window.location.origin; - const signInResp = await fetch(baseUrl + `/auth/signin/${provider}`, { + const resp = await fetch(baseUrl + `/auth/signin/${provider}`, { method: "post", credentials: "include", mode: 'cors', + redirect: 'follow', headers: { "Content-Type": "application/x-www-form-urlencoded", }, @@ -180,11 +181,9 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con callbackUrl }), }) - - const data = await signInResp.json() - debugger - window.location.href = data.url ?? callbackUrl - console.log(provider , csrfToken, callbackUrl, signInResp) + const link = await resp.text(); + console.log(link) + window.location.href = link } signIn = async (credentials: { email: string, password: string }) => { diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index 7eaec2d..890b8e7 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -60,8 +60,8 @@ const server = http.createServer(async (req, res) => { const headers = { 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET', 'Access-Control-Allow-Headers': '*', + 'Access-Control-Allow-Credentials': true }; - headers['Access-Control-Allow-Credentials'] = true if(req.headers.origin) { headers['Access-Control-Allow-Origin'] = req.headers.origin } @@ -70,29 +70,32 @@ const server = http.createServer(async (req, res) => { res.end(); return; } - // pre-flight does not allow - const request = await convertIncomingMessageToRequest(req) - const auth = await Auth(request, optionsEnvVar); + for (const headerName of auth.headers.keys()) { const header = auth.headers.get(headerName); headers[headerName]= header } if(req.url === '/auth/csrf' && req.headers.origin) { const body = await auth.json(); - console.log('1'+body.csrfToken) headers['access-control-expose-headers'] = 'set-cookie' - // headers['Set-Cookie']= `next-auth.csrf-token=${body.csrfToken}; next-auth.callback-url=${req.headers.origin}` - // headers['Set-Cookie'] = auth.headers.get('set-cookie') res.writeHead(200, headers); res.write(JSON.stringify(body)) return res.end(); - } else if(req.url.includes('/auth/signin/') && request.method === 'POST' && auth.status === 302 && auth.headers.get('location')) { - headers.Location = auth.headers.get('location') - res.writeHead(302, headers); - console.log('here') - return res.end(); + } else if( + req.url.includes('/auth/signin/') && + request.method === 'POST' && + auth.status === 302 && + auth.headers.get('location')) { + if(req.headers.origin === process.env.SERVER_URL) { + res.writeHead(302, headers); + return res.end(); + } else { + res.writeHead(200, headers) + res.write(auth.headers.get('location')) + return res.end(); + } } else { const text = await auth.text() headers['Content-Type'] = 'text/html' From 63b5f4192045590e2e57ea8972b3ca9b305b6ef0 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Mon, 24 Jul 2023 13:08:05 -0600 Subject: [PATCH 04/13] Working with both default page and custom method, just until the github landing, todo OAUTH flow --- server/http/auth.js | 71 +++++++++++++++----- server/runtimes/node/index.js | 118 ++++++++++------------------------ server/utils.js | 11 +++- 3 files changed, 99 insertions(+), 101 deletions(-) diff --git a/server/http/auth.js b/server/http/auth.js index 51b700b..bef13eb 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -1,20 +1,57 @@ -/* -import { Auth } from "@auth/core" +import {Auth} from '@auth/core'; +import GitHub from '@auth/core/providers/github'; - - -async function main() { - const url = new URL('https://example.com/api/auth/signin') - const request = new Request(url); - const response = await Auth(request, optionsEnvVar) - - const { status = 200 } = response - const data = await response.json() - - if (!data || !Object.keys(data).length) return null - if (status === 200) return data - throw new Error(data.message) +const optionsEnvVar = { + // Configure one or more authentication providers + providers: [ + GitHub({ + clientId: '8a9219d06d63a95bf1af', + clientSecret: '746ce3dd62cfbd400289e7647063ecc907ffab17', + }), + ], + trustHost: true, + secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687' +} +// Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API needed by Auth.js +export async function AuthModule(request) { + let headers = new Headers(); + const url = new URL(request.url) + if (url.pathname.split('/')[1] === 'auth') { + // req.url is /auth/signin + // Auth.js library expects http://localhost:3001/auth/signin + headers.set('Access-Control-Allow-Methods', 'OPTIONS, POST, GET') + headers.set('Access-Control-Allow-Headers', '*') + headers.set('Access-Control-Allow-Credentials', true) + if (request.headers.get('origin')) { + headers.set('Access-Control-Allow-Origin', request.headers.get('origin')) + } + if (request.method === 'OPTIONS') { + return new Response(null, {headers, status: 204}); + } + } + const auth = await Auth(request, optionsEnvVar); + for (const headerName of auth.headers.keys()) { + const header = auth.headers.get(headerName); + headers.set(headerName, header) + } + if (url.pathname === '/auth/csrf' && request.headers.get('origin')) { + const body = await auth.json(); + headers.set('access-control-expose-headers', 'set-cookie') + return new Response(JSON.stringify(body), {headers, status: 302}); + } else if ( + url.pathname.includes('/auth/signin') && + request.method === 'POST' && + auth.status === 302 && + auth.headers.get('location')) { + if (request.headers.get('origin') === process.env.SERVER_URL) { + return new Response(null, {headers, status: 302}); + } else { + return new Response(auth.headers.get('location'), {headers, status: 200}); + } + } else { + const text = await auth.text() + headers.set('Content-Type', 'text/html') + return new Response(text, {headers, status: 200}); + } } -main().then(() => console.log('done')) -*/ diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index 890b8e7..5caa0b1 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -1,28 +1,16 @@ import * as http from 'http'; import {WebSocketServer} from 'ws'; import {route} from '../../http/base.js'; -import {parseData, readStreamToPromise} from '../../utils.js'; +import {parseData, readReadableStream, readStreamToPromise} from '../../utils.js'; import jwt from 'jsonwebtoken'; import {getEventStore} from '../../ws/ws.js'; -import {Auth} from '@auth/core'; -import GitHub from '@auth/core/providers/github'; +import {AuthModule} from '../../http/auth.js'; const wsServer = new WebSocketServer({noServer: true}); const hostname = 'localhost' const port = process.env.PORT || 3001; -const optionsEnvVar = { - // Configure one or more authentication providers - providers: [ - GitHub({ - clientId: '8a9219d06d63a95bf1af', - clientSecret: '746ce3dd62cfbd400289e7647063ecc907ffab17', - }), - ], - trustHost: true, - secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687' -} async function getBody(request) { return new Promise((resolve) => { const bodyParts = []; @@ -35,13 +23,13 @@ async function getBody(request) { }); }); } - async function convertIncomingMessageToRequest(req){ - var headers = new Headers(); + const headers = new Headers(); for (var key in req.headers) { if (req.headers[key]) headers.append(key, req.headers[key]); } const body = req.method === 'POST' ? await getBody(req) : null; + // TODO remove hardcoded http const baseUrl = req.headers.origin || `http://${req.headers.host}` let request = new Request(new URL(req.url, baseUrl), { method: req.method, @@ -50,79 +38,43 @@ async function convertIncomingMessageToRequest(req){ }) return request } - +async function convertResponseToServerResponse(response, serverResponse) { + const headers = {}; + for (const headerName of response.headers.keys()) { + const header = response.headers.get(headerName); + headers[headerName] = header + } + serverResponse.writeHead(response.status, headers) + if(response.body) { + const body = await readReadableStream(response.body) + serverResponse.write(body) + } +} const server = http.createServer(async (req, res) => { - try { - // req.url is /auth/signin - // Auth.js library expects http://localhost:3001/auth/signin - - const headers = { - 'Access-Control-Allow-Methods': 'OPTIONS, POST, GET', - 'Access-Control-Allow-Headers': '*', - 'Access-Control-Allow-Credentials': true - }; - if(req.headers.origin) { - headers['Access-Control-Allow-Origin'] = req.headers.origin - } - if (req.method === 'OPTIONS') { - res.writeHead(204, headers); - res.end(); - return; - } - const request = await convertIncomingMessageToRequest(req) - const auth = await Auth(request, optionsEnvVar); + const request = await convertIncomingMessageToRequest(req) + const authResp = await AuthModule(request); + if(authResp) { + await convertResponseToServerResponse(authResp, res); + // Todo, remove this return and see if the user is auth or not + return res.end() + } - for (const headerName of auth.headers.keys()) { - const header = auth.headers.get(headerName); - headers[headerName]= header - } - if(req.url === '/auth/csrf' && req.headers.origin) { - const body = await auth.json(); - headers['access-control-expose-headers'] = 'set-cookie' - res.writeHead(200, headers); - res.write(JSON.stringify(body)) - return res.end(); - } else if( - req.url.includes('/auth/signin/') && - request.method === 'POST' && - auth.status === 302 && - auth.headers.get('location')) { - if(req.headers.origin === process.env.SERVER_URL) { - res.writeHead(302, headers); - return res.end(); - } else { - res.writeHead(200, headers) - res.write(auth.headers.get('location')) - return res.end(); - } + if (req.method === 'POST') { + const bodyString = await readStreamToPromise(req); + const body = parseData(bodyString); + const result = await route(req.url, body); + if (result?.error) { + res.statusCode = result.statusCode || 500; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result.error)); } else { - const text = await auth.text() - headers['Content-Type'] = 'text/html' - res.writeHead(200, headers); - res.write(text) - return res.end(); + res.statusCode = 200; + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(result ?? null)); } - - } catch (e) { - console.log(e) - return res.end(); } - // if (req.method === 'POST') { - // const bodyString = await readStreamToPromise(req); - // const body = parseData(bodyString); - // const result = await route(req.url, body); - // if (result?.error) { - // res.statusCode = result.statusCode || 500; - // res.setHeader('Content-Type', 'application/json'); - // res.end(JSON.stringify(result.error)); - // } else { - // res.statusCode = 200; - // res.setHeader('Content-Type', 'application/json'); - // res.end(JSON.stringify(result ?? null)); - // } - // } - // res.end(); + res.end(); }); server.listen(port, hostname, () => { diff --git a/server/utils.js b/server/utils.js index 34d7ca7..dd369ab 100644 --- a/server/utils.js +++ b/server/utils.js @@ -1,3 +1,5 @@ +import { Buffer } from 'node:buffer'; + export function readStreamToPromise(stream) { return new Promise((resolve, reject) => { const chunks = []; @@ -17,4 +19,11 @@ export function parseData(dataString) { return value; } }); -} \ No newline at end of file +} +export async function readReadableStream(readableStream) { + const chunks = []; + for await (const chunk of readableStream) { + chunks.push(Buffer.from(chunk)); + } + return Buffer.concat(chunks).toString("utf-8"); +} From 1b2c46f05a96bd07bfbee5bbacc615c39288a795 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Mon, 24 Jul 2023 16:50:37 -0600 Subject: [PATCH 05/13] simplify logic --- server/http/auth.js | 29 ++++++++++------------------- server/runtimes/node/index.js | 8 +++++--- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/server/http/auth.js b/server/http/auth.js index bef13eb..acda482 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -17,8 +17,6 @@ export async function AuthModule(request) { let headers = new Headers(); const url = new URL(request.url) if (url.pathname.split('/')[1] === 'auth') { - // req.url is /auth/signin - // Auth.js library expects http://localhost:3001/auth/signin headers.set('Access-Control-Allow-Methods', 'OPTIONS, POST, GET') headers.set('Access-Control-Allow-Headers', '*') headers.set('Access-Control-Allow-Credentials', true) @@ -30,28 +28,21 @@ export async function AuthModule(request) { } } const auth = await Auth(request, optionsEnvVar); + headers.set('access-control-expose-headers', 'set-cookie') + // merge both auth and added headers for (const headerName of auth.headers.keys()) { const header = auth.headers.get(headerName); headers.set(headerName, header) } - if (url.pathname === '/auth/csrf' && request.headers.get('origin')) { - const body = await auth.json(); - headers.set('access-control-expose-headers', 'set-cookie') - return new Response(JSON.stringify(body), {headers, status: 302}); - } else if ( - url.pathname.includes('/auth/signin') && - request.method === 'POST' && - auth.status === 302 && - auth.headers.get('location')) { - if (request.headers.get('origin') === process.env.SERVER_URL) { - return new Response(null, {headers, status: 302}); - } else { - return new Response(auth.headers.get('location'), {headers, status: 200}); - } + for (const headerName of headers.keys()) { + const header = headers.get(headerName); + auth.headers.set(headerName, header) + } + // comes from sdk and all redirections needs to be triggered manually from the sdk + if (auth.status === 302 && request.headers.get('origin') !== process.env.SERVER_URL) { + return new Response(auth.headers.get('location'), {headers, status: 200}); } else { - const text = await auth.text() - headers.set('Content-Type', 'text/html') - return new Response(text, {headers, status: 200}); + return auth } } diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index 5caa0b1..1ebc5c8 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -31,11 +31,13 @@ async function convertIncomingMessageToRequest(req){ const body = req.method === 'POST' ? await getBody(req) : null; // TODO remove hardcoded http const baseUrl = req.headers.origin || `http://${req.headers.host}` - let request = new Request(new URL(req.url, baseUrl), { - method: req.method, + console.log((new URL(req.url, baseUrl)).pathname) + const reqObj = { + ...req, body, headers, - }) + } + let request = new Request(new URL(req.url, baseUrl), reqObj) return request } async function convertResponseToServerResponse(response, serverResponse) { From b0d80a1aa82b5fcf52121f568cbb42a2c7cd8dbc Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sun, 30 Jul 2023 15:39:03 -0600 Subject: [PATCH 06/13] default login working --- sdk/src/index.ts | 21 +++++++++++ server/http/auth.js | 88 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 7c5172c..227762a 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -185,6 +185,27 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con console.log(link) window.location.href = link } + async defaultSignIn() { + return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` + let timeout = setTimeout(() => { + reject({message:`signInWith timeout exceeded`}) + }, 10*60*1000) + let loginWindow: any; + const url = new URL('/auth/signin', baseUrl); + const uniqueWindowId = `authorizationJavascriptDatabase`; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; + clearTimeout(timeout); + loginWindow.close(); + window.removeEventListener('message', handleMessage) + resolve({token, user}); + } + window.addEventListener("message", handleMessage , false); + loginWindow = window.open(url.toString(), uniqueWindowId, params) + }) + } signIn = async (credentials: { email: string, password: string }) => { try { diff --git a/server/http/auth.js b/server/http/auth.js index acda482..979b681 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -10,13 +10,56 @@ const optionsEnvVar = { }), ], trustHost: true, - secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687' + secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687', + cookies: { + csrfToken: { + name: 'next-auth.csrf-token', + options: { + httpOnly: true, + sameSite: 'none', + path: '/', + secure: true + } + }, + pkceCodeVerifier: { + name: 'next-auth.pkce.code_verifier', + options: { + httpOnly: true, + sameSite: 'none', + path: '/', + secure: true + } + } + }, + callbacks: { + async signIn(args) { + // async signIn({user, account, profile, email, credentials}) { + console.log(`signIn callback: ${JSON.stringify(args)}`) + return true + }, + // async redirect({ url, baseUrl }) { + async redirect(args) { + console.log(`redirect callback: ${JSON.stringify(args)}`) + return null + //return baseUrl + }, + // async session({session, user, token}) { + async session(args) { + console.log(`session callback: ${JSON.stringify(args)}`) + return args.session + }, + // async jwt({token, user, account, profile, isNewUser}) { + async jwt(args) { + console.log(`jwt callback: ${JSON.stringify(args)}`) + return args.token + } + } } // Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API needed by Auth.js export async function AuthModule(request) { let headers = new Headers(); const url = new URL(request.url) - if (url.pathname.split('/')[1] === 'auth') { + if (['auth', 'db', 'functions'].includes(url.pathname.split('/')[1])) { headers.set('Access-Control-Allow-Methods', 'OPTIONS, POST, GET') headers.set('Access-Control-Allow-Headers', '*') headers.set('Access-Control-Allow-Credentials', true) @@ -26,23 +69,30 @@ export async function AuthModule(request) { if (request.method === 'OPTIONS') { return new Response(null, {headers, status: 204}); } + const auth = await Auth(request, optionsEnvVar); + headers.set('access-control-expose-headers', 'set-cookie') + // merge both auth and added headers + for (const headerName of auth.headers.keys()) { + const header = auth.headers.get(headerName); + headers.set(headerName, header) + } + for (const headerName of headers.keys()) { + const header = headers.get(headerName); + auth.headers.set(headerName, header) + } + if(url.pathname.includes('auth/callback') ) { + headers.set('Content-type', 'text/html') + return new Response(`window.close();`, {headers, status: 200}); + } + + // comes from sdk and all redirections needs to be triggered manually from the sdk + const origin = request.headers.get('origin') + if (auth.status === 302 && origin && origin !== process.env.SERVER_URL) { + return new Response(auth.headers.get('location'), {headers, status: 200}); + } else { + return auth + } } - const auth = await Auth(request, optionsEnvVar); - headers.set('access-control-expose-headers', 'set-cookie') - // merge both auth and added headers - for (const headerName of auth.headers.keys()) { - const header = auth.headers.get(headerName); - headers.set(headerName, header) - } - for (const headerName of headers.keys()) { - const header = headers.get(headerName); - auth.headers.set(headerName, header) - } - // comes from sdk and all redirections needs to be triggered manually from the sdk - if (auth.status === 302 && request.headers.get('origin') !== process.env.SERVER_URL) { - return new Response(auth.headers.get('location'), {headers, status: 200}); - } else { - return auth - } + return null } From f9058a15637ccf3163c36bd9528eec4710247640 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sun, 30 Jul 2023 16:09:09 -0600 Subject: [PATCH 07/13] fix double tag --- server/http/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/http/auth.js b/server/http/auth.js index 979b681..db727e1 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -82,7 +82,7 @@ export async function AuthModule(request) { } if(url.pathname.includes('auth/callback') ) { headers.set('Content-type', 'text/html') - return new Response(`window.close();`, {headers, status: 200}); + return new Response(``, {headers, status: 200}); } // comes from sdk and all redirections needs to be triggered manually from the sdk From b3dbe16174e4a8f717d61efbbb6cc06036ea2e6e Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sun, 30 Jul 2023 23:23:18 -0600 Subject: [PATCH 08/13] working signin with provider, needs custom url on client --- sdk/src/index.ts | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 227762a..9506a5a 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -160,14 +160,37 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con delete localStorage.userId; this.set({}) } + async singInCallback(link: string) { + const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { + method: "get", + mode: 'cors', + }) + const { csrfToken } = await csrfTokenResp.json() + const url = new URL(link); + const newUrl = new URL(url.pathname, baseUrl) + for(const name of url.searchParams.keys()) { + newUrl.searchParams.set(name, url.searchParams.get(name)) + } + newUrl.searchParams.set('csrfToken', csrfToken); + debugger + const resp = await fetch(newUrl.href, { + method: "get", + credentials: "include", + mode: 'cors', + redirect: 'follow', + }) + console.log('sucesss', resp) + } async signInWithProvider(provider: string) { + // do not modify const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { credentials: "include", method: "get", mode: 'cors', }) const { csrfToken } = await csrfTokenResp.json() - const callbackUrl = window.location.origin; + const callbackUrl = baseUrl; + console.log(callbackUrl) const resp = await fetch(baseUrl + `/auth/signin/${provider}`, { method: "post", credentials: "include", @@ -178,11 +201,10 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con }, body: new URLSearchParams({ csrfToken, - callbackUrl + callbackUrl, }), }) const link = await resp.text(); - console.log(link) window.location.href = link } async defaultSignIn() { From b2ccb3586d81258f0913d8454e8372c872b850d4 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 5 Aug 2023 15:03:12 -0600 Subject: [PATCH 09/13] customSign with popup --- sdk/src/index.ts | 121 ++++++++++++++-------------------- sdk/src/providerSignin.ts | 36 ++++++++++ server/http/auth.js | 17 ++++- server/runtimes/node/index.js | 2 +- 4 files changed, 100 insertions(+), 76 deletions(-) create mode 100644 sdk/src/providerSignin.ts diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 9506a5a..e9a76ce 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,3 +1,4 @@ +import {getSignInPopup} from './providerSignin' type document = { id: string, [key: string]: any } type fn = (v: any) => any @@ -155,79 +156,55 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con } } - signOut = () => { - delete localStorage.token; - delete localStorage.userId; - this.set({}) - } - async singInCallback(link: string) { - const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { - method: "get", - mode: 'cors', - }) - const { csrfToken } = await csrfTokenResp.json() - const url = new URL(link); - const newUrl = new URL(url.pathname, baseUrl) - for(const name of url.searchParams.keys()) { - newUrl.searchParams.set(name, url.searchParams.get(name)) + signOut = () => { + delete localStorage.token; + delete localStorage.userId; + this.set({}) + } + async signInWithProvider(provider: string) { + return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` + let timeout = setTimeout(() => { + reject({message:`signInWith timeout exceeded`}) + }, 60*60*1000) + let loginWindow: any; + const url = new URL('/', baseUrl); + const uniqueWindowId = `authorizationJavascriptDatabase`; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; + clearTimeout(timeout); + loginWindow.close(); + window.removeEventListener('message', handleMessage) + resolve({token, user}); } - newUrl.searchParams.set('csrfToken', csrfToken); - debugger - const resp = await fetch(newUrl.href, { - method: "get", - credentials: "include", - mode: 'cors', - redirect: 'follow', - }) - console.log('sucesss', resp) - } - async signInWithProvider(provider: string) { - // do not modify - const csrfTokenResp = await fetch(baseUrl + `/auth/csrf`, { - credentials: "include", - method: "get", - mode: 'cors', - }) - const { csrfToken } = await csrfTokenResp.json() - const callbackUrl = baseUrl; - console.log(callbackUrl) - const resp = await fetch(baseUrl + `/auth/signin/${provider}`, { - method: "post", - credentials: "include", - mode: 'cors', - redirect: 'follow', - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - body: new URLSearchParams({ - csrfToken, - callbackUrl, - }), - }) - const link = await resp.text(); - window.location.href = link - } - async defaultSignIn() { - return new Promise((resolve, reject) => { - const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; - let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` - let timeout = setTimeout(() => { - reject({message:`signInWith timeout exceeded`}) - }, 10*60*1000) - let loginWindow: any; - const url = new URL('/auth/signin', baseUrl); - const uniqueWindowId = `authorizationJavascriptDatabase`; - const handleMessage = (e: MessageEvent)=> { - const {token, user} = e.data; - clearTimeout(timeout); - loginWindow.close(); - window.removeEventListener('message', handleMessage) - resolve({token, user}); - } - window.addEventListener("message", handleMessage , false); - loginWindow = window.open(url.toString(), uniqueWindowId, params) - }) - } + window.addEventListener("message", handleMessage , false); + loginWindow = window.open(url.toString(), uniqueWindowId, params) + loginWindow.document.write(getSignInPopup(baseUrl, provider)); + }) + } + + async defaultSignIn() { + return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` + let timeout = setTimeout(() => { + reject({message:`signInWith timeout exceeded`}) + }, 60*60*1000) + let loginWindow: any; + const url = new URL('/auth/signin', baseUrl); + const uniqueWindowId = `authorizationJavascriptDatabase`; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; + clearTimeout(timeout); + loginWindow.close(); + window.removeEventListener('message', handleMessage) + resolve({token, user}); + } + window.addEventListener("message", handleMessage , false); + loginWindow = window.open(url.toString(), uniqueWindowId, params) + }) + } signIn = async (credentials: { email: string, password: string }) => { try { diff --git a/sdk/src/providerSignin.ts b/sdk/src/providerSignin.ts new file mode 100644 index 0000000..e1fb0fd --- /dev/null +++ b/sdk/src/providerSignin.ts @@ -0,0 +1,36 @@ +export function getSignInPopup(baseUrl: string, provider: string) { + return ` + + + + + + ` +} diff --git a/server/http/auth.js b/server/http/auth.js index db727e1..088e237 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -1,5 +1,6 @@ import {Auth} from '@auth/core'; import GitHub from '@auth/core/providers/github'; +import {readReadableStream} from '../utils.js'; const optionsEnvVar = { // Configure one or more authentication providers @@ -69,6 +70,16 @@ export async function AuthModule(request) { if (request.method === 'OPTIONS') { return new Response(null, {headers, status: 204}); } + if(url.pathname.includes('auth/signin/')) { + const body = await readReadableStream(request.clone().body) + const searchParams = new URLSearchParams(body); + if(searchParams?.get('customProviderSignin') === 'true') { + const pathname = (new URL(request.url)).pathname + const clone = new Request(new URL(pathname, process.env.SERVER_URL) , request) + request = clone + console.log('here') + } + } const auth = await Auth(request, optionsEnvVar); headers.set('access-control-expose-headers', 'set-cookie') // merge both auth and added headers @@ -84,10 +95,10 @@ export async function AuthModule(request) { headers.set('Content-type', 'text/html') return new Response(``, {headers, status: 200}); } - // comes from sdk and all redirections needs to be triggered manually from the sdk - const origin = request.headers.get('origin') - if (auth.status === 302 && origin && origin !== process.env.SERVER_URL) { + let origin = request.headers.get('origin') + if(origin) origin = new URL(origin); + if (auth.status === 302 && origin && origin.href !== process.env.SERVER_URL) { return new Response(auth.headers.get('location'), {headers, status: 200}); } else { return auth diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index 1ebc5c8..a135013 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -30,7 +30,7 @@ async function convertIncomingMessageToRequest(req){ } const body = req.method === 'POST' ? await getBody(req) : null; // TODO remove hardcoded http - const baseUrl = req.headers.origin || `http://${req.headers.host}` + const baseUrl = process.env.SERVER_URL console.log((new URL(req.url, baseUrl)).pathname) const reqObj = { ...req, From 30bb31d7fd5e30e3349de9d2d90ef471afc9d480 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 5 Aug 2023 15:58:55 -0600 Subject: [PATCH 10/13] Fix timeout seconds --- sdk/src/index.ts | 100 ++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/sdk/src/index.ts b/sdk/src/index.ts index e9a76ce..3bf2234 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -4,6 +4,7 @@ type fn = (v: any) => any const regexpIsoDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/; +const SECONDS_TIMEOUT_SIGNIN_WINDOW = 60; export async function initApp(config: { serverUrl?: string, apiKey?: string, connector: 'HTTP' | 'LOCAL' | 'WS', opHandlers?: any } = {connector: 'HTTP'}) { config = {...{connector: 'HTTP'}, ...config}; let baseUrl = ''; @@ -156,55 +157,56 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con } } - signOut = () => { - delete localStorage.token; - delete localStorage.userId; - this.set({}) - } - async signInWithProvider(provider: string) { - return new Promise((resolve, reject) => { - const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; - let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` - let timeout = setTimeout(() => { - reject({message:`signInWith timeout exceeded`}) - }, 60*60*1000) - let loginWindow: any; - const url = new URL('/', baseUrl); - const uniqueWindowId = `authorizationJavascriptDatabase`; - const handleMessage = (e: MessageEvent)=> { - const {token, user} = e.data; - clearTimeout(timeout); - loginWindow.close(); - window.removeEventListener('message', handleMessage) - resolve({token, user}); - } - window.addEventListener("message", handleMessage , false); - loginWindow = window.open(url.toString(), uniqueWindowId, params) - loginWindow.document.write(getSignInPopup(baseUrl, provider)); - }) - } - - async defaultSignIn() { - return new Promise((resolve, reject) => { - const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; - let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` - let timeout = setTimeout(() => { - reject({message:`signInWith timeout exceeded`}) - }, 60*60*1000) - let loginWindow: any; - const url = new URL('/auth/signin', baseUrl); - const uniqueWindowId = `authorizationJavascriptDatabase`; - const handleMessage = (e: MessageEvent)=> { - const {token, user} = e.data; - clearTimeout(timeout); - loginWindow.close(); - window.removeEventListener('message', handleMessage) - resolve({token, user}); - } - window.addEventListener("message", handleMessage , false); - loginWindow = window.open(url.toString(), uniqueWindowId, params) - }) - } + signOut = () => { + delete localStorage.token; + delete localStorage.userId; + this.set({}) + } + async signInWithProvider(provider: string) { + return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` + let timeout = setTimeout(() => { + loginWindow.close(); + reject({message:`signInWith timeout exceeded`}) + }, SECONDS_TIMEOUT_SIGNIN_WINDOW*1000) + let loginWindow: any; + const url = new URL('/', baseUrl); + const uniqueWindowId = `authorizationJavascriptDatabase`; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; + clearTimeout(timeout); + loginWindow.close(); + window.removeEventListener('message', handleMessage) + resolve({token, user}); + } + window.addEventListener("message", handleMessage , false); + loginWindow = window.open(url.toString(), uniqueWindowId, params) + loginWindow.document.write(getSignInPopup(baseUrl, provider)); + }) + } + async defaultSignIn() { + return new Promise((resolve, reject) => { + const width = 450, height = 550, left = (screen.width - width) / 2, top = (screen.height - height) / 2; + let params = `width=${width}, height=${height}, top=${top}, left=${left}, titlebar=no, location=yes` + let timeout = setTimeout(() => { + loginWindow.close(); + reject({message:`signInWith timeout exceeded`}); + }, SECONDS_TIMEOUT_SIGNIN_WINDOW*1000) + let loginWindow: any; + const url = new URL('/auth/signin', baseUrl); + const uniqueWindowId = `authorizationJavascriptDatabase`; + const handleMessage = (e: MessageEvent)=> { + const {token, user} = e.data; + clearTimeout(timeout); + loginWindow.close(); + window.removeEventListener('message', handleMessage) + resolve({token, user}); + } + window.addEventListener("message", handleMessage , false); + loginWindow = window.open(url.toString(), uniqueWindowId, params) + }) + } signIn = async (credentials: { email: string, password: string }) => { try { From 485fbfe6091f696fba25cf75b1084dc2677a2b4f Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Wed, 20 Sep 2023 20:27:39 -0600 Subject: [PATCH 11/13] Working login returning sessionToken --- sdk/package-lock.json | 134 ++++++++++++++++++++++++++++++++++++++ sdk/package.json | 4 +- sdk/src/index.ts | 4 +- sdk/src/providerSignin.ts | 6 +- server/http/auth.js | 38 ++++++++--- 5 files changed, 174 insertions(+), 12 deletions(-) diff --git a/sdk/package-lock.json b/sdk/package-lock.json index d545623..bcb41d9 100644 --- a/sdk/package-lock.json +++ b/sdk/package-lock.json @@ -8,6 +8,9 @@ "name": "@jsdb/sdk", "version": "0.0.45", "license": "MIT", + "dependencies": { + "@auth/core": "^0.9.0" + }, "devDependencies": { "@size-limit/preset-small-lib": "^7.0.8", "@types/lodash-es": "^4.17.6", @@ -34,6 +37,27 @@ "node": ">=6.0.0" } }, + "node_modules/@auth/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.9.0.tgz", + "integrity": "sha512-W2WO0WCBg1T3P8+yjQPzurTQhPv6ecBYfJ2oE3uvXPAX5ZLWAMSjKFAIa9oLZy5pwrB+YehJZPnlIxVilhrVcg==", + "dependencies": { + "@panva/hkdf": "^1.0.4", + "cookie": "0.5.0", + "jose": "^4.11.1", + "oauth4webapi": "^2.0.6", + "preact": "10.11.3", + "preact-render-to-string": "5.2.3" + }, + "peerDependencies": { + "nodemailer": "^6.8.0" + }, + "peerDependenciesMeta": { + "nodemailer": { + "optional": true + } + } + }, "node_modules/@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -2243,6 +2267,14 @@ "node": ">= 8" } }, + "node_modules/@panva/hkdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz", + "integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3919,6 +3951,14 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -7840,6 +7880,14 @@ "node": ">= 8.3" } }, + "node_modules/jose": { + "version": "4.14.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", + "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/jpjs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/jpjs/-/jpjs-1.2.1.tgz", @@ -8689,6 +8737,14 @@ "node": "*" } }, + "node_modules/oauth4webapi": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.3.0.tgz", + "integrity": "sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -9215,6 +9271,31 @@ "node": ">=0.10.0" } }, + "node_modules/preact": { + "version": "10.11.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", + "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/preact-render-to-string": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz", + "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==", + "dependencies": { + "pretty-format": "^3.8.0" + }, + "peerDependencies": { + "preact": ">=10" + } + }, + "node_modules/preact-render-to-string/node_modules/pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -12313,6 +12394,19 @@ "@jridgewell/trace-mapping": "^0.3.9" } }, + "@auth/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.9.0.tgz", + "integrity": "sha512-W2WO0WCBg1T3P8+yjQPzurTQhPv6ecBYfJ2oE3uvXPAX5ZLWAMSjKFAIa9oLZy5pwrB+YehJZPnlIxVilhrVcg==", + "requires": { + "@panva/hkdf": "^1.0.4", + "cookie": "0.5.0", + "jose": "^4.11.1", + "oauth4webapi": "^2.0.6", + "preact": "10.11.3", + "preact-render-to-string": "5.2.3" + } + }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -13919,6 +14013,11 @@ "fastq": "^1.6.0" } }, + "@panva/hkdf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.1.1.tgz", + "integrity": "sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==" + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -15208,6 +15307,11 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -18131,6 +18235,11 @@ "supports-color": "^7.0.0" } }, + "jose": { + "version": "4.14.4", + "resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz", + "integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==" + }, "jpjs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/jpjs/-/jpjs-1.2.1.tgz", @@ -18814,6 +18923,11 @@ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, + "oauth4webapi": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.3.0.tgz", + "integrity": "sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -19202,6 +19316,26 @@ "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", "dev": true }, + "preact": { + "version": "10.11.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz", + "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==" + }, + "preact-render-to-string": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz", + "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==", + "requires": { + "pretty-format": "^3.8.0" + }, + "dependencies": { + "pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" + } + } + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", diff --git a/sdk/package.json b/sdk/package.json index b05b8d6..38fd1d5 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -54,7 +54,9 @@ "tslib": "^2.4.0", "typescript": "^3.9.10" }, - "dependencies": {}, + "dependencies": { + "@auth/core": "^0.9.0" + }, "description": "Install ```shell npm i @jsdb/sdk ```", "directories": { "test": "test" diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 3bf2234..84abe76 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -174,6 +174,7 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con const url = new URL('/', baseUrl); const uniqueWindowId = `authorizationJavascriptDatabase`; const handleMessage = (e: MessageEvent)=> { + console.log('Message: ', e.data) const {token, user} = e.data; clearTimeout(timeout); loginWindow.close(); @@ -197,7 +198,8 @@ export async function initApp(config: { serverUrl?: string, apiKey?: string, con const url = new URL('/auth/signin', baseUrl); const uniqueWindowId = `authorizationJavascriptDatabase`; const handleMessage = (e: MessageEvent)=> { - const {token, user} = e.data; + const {token, user} = JSON.parse(e.data); + console.log('Message: ', e.data) clearTimeout(timeout); loginWindow.close(); window.removeEventListener('message', handleMessage) diff --git a/sdk/src/providerSignin.ts b/sdk/src/providerSignin.ts index e1fb0fd..cba5b2d 100644 --- a/sdk/src/providerSignin.ts +++ b/sdk/src/providerSignin.ts @@ -26,9 +26,11 @@ export function getSignInPopup(baseUrl: string, provider: string) { }), }) const link = await resp.text(); - window.location.href = link + window.location.assign(link) } - main(); + setTimeout(() => { + main(); + }, 1) diff --git a/server/http/auth.js b/server/http/auth.js index 088e237..7b3d70c 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -1,6 +1,8 @@ import {Auth} from '@auth/core'; import GitHub from '@auth/core/providers/github'; import {readReadableStream} from '../utils.js'; +import {decode} from '@auth/core/jwt'; +import {sdkDb} from './sdk.js'; const optionsEnvVar = { // Configure one or more authentication providers @@ -11,7 +13,7 @@ const optionsEnvVar = { }), ], trustHost: true, - secret: '280be61e650f6ca8476717130dc5c15ef5c75a1bf20764c991c6ad06dfea1687', + secret: process.env.JWT_SECRET, cookies: { csrfToken: { name: 'next-auth.csrf-token', @@ -35,26 +37,26 @@ const optionsEnvVar = { callbacks: { async signIn(args) { // async signIn({user, account, profile, email, credentials}) { - console.log(`signIn callback: ${JSON.stringify(args)}`) + // console.log(`signIn callback`) return true }, // async redirect({ url, baseUrl }) { async redirect(args) { - console.log(`redirect callback: ${JSON.stringify(args)}`) + //console.log(`redirect callback: ${JSON.stringify(args)}`) return null //return baseUrl }, // async session({session, user, token}) { async session(args) { - console.log(`session callback: ${JSON.stringify(args)}`) + //console.log(`session callback: ${JSON.stringify(args)}`) return args.session }, // async jwt({token, user, account, profile, isNewUser}) { async jwt(args) { - console.log(`jwt callback: ${JSON.stringify(args)}`) - return args.token + console.log(`jwt callback: ${JSON.stringify(args)}`) + return args.token; } - } + }, } // Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API needed by Auth.js export async function AuthModule(request) { @@ -86,6 +88,9 @@ export async function AuthModule(request) { for (const headerName of auth.headers.keys()) { const header = auth.headers.get(headerName); headers.set(headerName, header) + if (headerName === 'set-cookie') { + console.log(header) + } } for (const headerName of headers.keys()) { const header = headers.get(headerName); @@ -93,12 +98,29 @@ export async function AuthModule(request) { } if(url.pathname.includes('auth/callback') ) { headers.set('Content-type', 'text/html') - return new Response(``, {headers, status: 200}); + const codedSessionToken = headers.get('set-cookie') + ?.split(';') + ?.map(dirtyCookie => dirtyCookie.split(',')) + ?.flat() + ?.filter(keyValue => keyValue.includes('next-auth.session-token'))?.[0] + ?.split('=')?.[1]; + const decodedSessionToken = await decode({ + token: codedSessionToken, + secret: process.env.JWT_SECRET, + }) + + const resp = ` + +` + return new Response(resp, {headers, status: 200}); } // comes from sdk and all redirections needs to be triggered manually from the sdk let origin = request.headers.get('origin') if(origin) origin = new URL(origin); if (auth.status === 302 && origin && origin.href !== process.env.SERVER_URL) { + // custom provider signin return new Response(auth.headers.get('location'), {headers, status: 200}); } else { return auth From 0b16e54786bbf3c3d24ffcfbbfeda8946e75d7e6 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 23 Sep 2023 09:22:18 -0600 Subject: [PATCH 12/13] feat[authjs]: WIP sdk in db adapter --- server/http/auth.js | 106 +++++++++++++++++----------------- server/http/jsdbAdapter.js | 49 ++++++++++++++++ server/http/sdk.js | 6 ++ server/runtimes/node/index.js | 6 +- 4 files changed, 114 insertions(+), 53 deletions(-) create mode 100644 server/http/jsdbAdapter.js create mode 100644 server/http/sdk.js diff --git a/server/http/auth.js b/server/http/auth.js index 7b3d70c..cb0eaa5 100644 --- a/server/http/auth.js +++ b/server/http/auth.js @@ -3,63 +3,65 @@ import GitHub from '@auth/core/providers/github'; import {readReadableStream} from '../utils.js'; import {decode} from '@auth/core/jwt'; import {sdkDb} from './sdk.js'; +import jsdbAdapter from './jsdbAdapter.js'; -const optionsEnvVar = { - // Configure one or more authentication providers - providers: [ - GitHub({ - clientId: '8a9219d06d63a95bf1af', - clientSecret: '746ce3dd62cfbd400289e7647063ecc907ffab17', - }), - ], - trustHost: true, - secret: process.env.JWT_SECRET, - cookies: { - csrfToken: { - name: 'next-auth.csrf-token', - options: { - httpOnly: true, - sameSite: 'none', - path: '/', - secure: true +// Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API needed by Auth.js +export async function AuthModule(request) { + const optionsEnvVar = { + // Configure one or more authentication providers + providers: [ + GitHub({ + clientId: '8a9219d06d63a95bf1af', + clientSecret: '746ce3dd62cfbd400289e7647063ecc907ffab17', + }), + ], + trustHost: true, + secret: process.env.JWT_SECRET, + cookies: { + csrfToken: { + name: 'next-auth.csrf-token', + options: { + httpOnly: true, + sameSite: 'none', + path: '/', + secure: true + } + }, + pkceCodeVerifier: { + name: 'next-auth.pkce.code_verifier', + options: { + httpOnly: true, + sameSite: 'none', + path: '/', + secure: true + } } }, - pkceCodeVerifier: { - name: 'next-auth.pkce.code_verifier', - options: { - httpOnly: true, - sameSite: 'none', - path: '/', - secure: true + callbacks: { + async signIn(args) { + // async signIn({user, account, profile, email, credentials}) { + // console.log(`signIn callback`) + return true + }, + // async redirect({ url, baseUrl }) { + async redirect(args) { + //console.log(`redirect callback: ${JSON.stringify(args)}`) + return null + //return baseUrl + }, + // async session({session, user, token}) { + async session(args) { + //console.log(`session callback: ${JSON.stringify(args)}`) + return args.session + }, + // async jwt({token, user, account, profile, isNewUser}) { + async jwt(args) { + console.log(`jwt callback: ${JSON.stringify(args)}`) + return args.token; } - } - }, - callbacks: { - async signIn(args) { - // async signIn({user, account, profile, email, credentials}) { - // console.log(`signIn callback`) - return true - }, - // async redirect({ url, baseUrl }) { - async redirect(args) { - //console.log(`redirect callback: ${JSON.stringify(args)}`) - return null - //return baseUrl - }, - // async session({session, user, token}) { - async session(args) { - //console.log(`session callback: ${JSON.stringify(args)}`) - return args.session }, - // async jwt({token, user, account, profile, isNewUser}) { - async jwt(args) { - console.log(`jwt callback: ${JSON.stringify(args)}`) - return args.token; - } - }, -} -// Request https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API needed by Auth.js -export async function AuthModule(request) { + adapter: jsdbAdapter(sdkDb) + } let headers = new Headers(); const url = new URL(request.url) if (['auth', 'db', 'functions'].includes(url.pathname.split('/')[1])) { diff --git a/server/http/jsdbAdapter.js b/server/http/jsdbAdapter.js new file mode 100644 index 0000000..7f8d15e --- /dev/null +++ b/server/http/jsdbAdapter.js @@ -0,0 +1,49 @@ +export default function MyAdapter(dbSdk) { + return { + async createUser(user) { + console.log('here') + await dbSdk.set('test', user) + // dbSdk.set('hello', {test:true}) + return + }, + async getUser(id) { + return + }, + async getUserByEmail(email) { + return + }, + async getUserByAccount({ providerAccountId, provider }) { + return + }, + async updateUser(user) { + return + }, + async deleteUser(userId) { + return + }, + async linkAccount(account) { + return + }, + async unlinkAccount({ providerAccountId, provider }) { + return + }, + async createSession({ sessionToken, userId, expires }) { + return + }, + async getSessionAndUser(sessionToken) { + return + }, + async updateSession({ sessionToken }) { + return + }, + async deleteSession(sessionToken) { + return + }, + async createVerificationToken({ identifier, expires, token }) { + return + }, + async useVerificationToken({ identifier, token }) { + return + }, + } +} diff --git a/server/http/sdk.js b/server/http/sdk.js new file mode 100644 index 0000000..b3e8a41 --- /dev/null +++ b/server/http/sdk.js @@ -0,0 +1,6 @@ +import {initApp} from "@jsdb/sdk"; +export let sdkApp, sdkDb; +export async function initSdk() { + sdkApp = await initApp({serverUrl: process.env.SERVER_URL, connector: 'HTTP'}) + sdkDb = sdkApp.db; +} diff --git a/server/runtimes/node/index.js b/server/runtimes/node/index.js index a135013..078f0d7 100644 --- a/server/runtimes/node/index.js +++ b/server/runtimes/node/index.js @@ -5,6 +5,8 @@ import {parseData, readReadableStream, readStreamToPromise} from '../../utils.js import jwt from 'jsonwebtoken'; import {getEventStore} from '../../ws/ws.js'; import {AuthModule} from '../../http/auth.js'; +import {initSdk} from '../../http/sdk.js'; + const wsServer = new WebSocketServer({noServer: true}); @@ -79,8 +81,10 @@ const server = http.createServer(async (req, res) => { res.end(); }); -server.listen(port, hostname, () => { +server.listen(port, hostname, async () => { + await initSdk() console.log(`Server running at http://${hostname}:${port}/`); + }); server.on('upgrade', (request, socket, head) => { From 6ee08f7b66388ade921ea9ef7b79b40542c913a9 Mon Sep 17 00:00:00 2001 From: Diego Franco Date: Sat, 23 Sep 2023 11:57:32 -0600 Subject: [PATCH 13/13] feat[authjs]: Add gitignore to root --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e7c1d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.idea/