New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@a-type/auth

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@a-type/auth - npm Package Compare versions

Comparing version

to
0.2.0

67

dist/esm/handlers.js
import { RETURN_TO_COOKIE } from './returnTo.js';
import { getOrCreateSession } from './session.js';
import * as z from 'zod';
export function createHandlers({ providers, db, defaultReturnTo = '/', email: emailService, createSession, }) {
export function createHandlers({ providers, db, defaultReturnTo = '/', email: emailService, sessions, }) {
const supportsEmail = !!db.insertVerificationCode &&

@@ -76,13 +75,8 @@ !!db.getUserByEmailAndPassword &&

}
const res = new Response(null, {
const session = await sessions.createSession(userId);
const sessionHeaders = await sessions.updateSession(session);
return new Response(null, {
status: 302,
headers: {
location: (_d = url.searchParams.get('returnTo')) !== null && _d !== void 0 ? _d : defaultReturnTo,
},
headers: Object.assign(Object.assign({}, sessionHeaders), { location: (_d = url.searchParams.get('returnTo')) !== null && _d !== void 0 ? _d : defaultReturnTo }),
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(userId);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -93,11 +87,6 @@ async function handleLogoutRequest(req) {

const returnTo = (_a = url.searchParams.get('returnTo')) !== null && _a !== void 0 ? _a : defaultReturnTo;
const res = new Response(null, {
return new Response(null, {
status: 302,
headers: {
location: returnTo,
},
headers: Object.assign(Object.assign({}, sessions.clearSession()), { location: returnTo }),
});
const session = await getOrCreateSession(req, res);
session.destroy();
return res;
}

@@ -131,2 +120,8 @@ async function handleSendEmailVerificationRequest(req) {

}));
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: {
'content-type': 'application/json',
},
});
}

@@ -170,13 +165,7 @@ async function handleVerifyEmailRequest(req) {

}));
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
location: (_c = url.searchParams.get('returnTo')) !== null && _c !== void 0 ? _c : defaultReturnTo,
},
headers: Object.assign(Object.assign({}, (await sessions.updateSession(session))), { location: (_c = url.searchParams.get('returnTo')) !== null && _c !== void 0 ? _c : defaultReturnTo }),
});
const session = await getOrCreateSession(req, res);
const sessionDetails = createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -200,13 +189,7 @@ async function handleEmailLoginRequest(req) {

}
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
location: (_b = params.returnTo) !== null && _b !== void 0 ? _b : defaultReturnTo,
},
headers: Object.assign(Object.assign({}, (await sessions.updateSession(session))), { location: (_b = params.returnTo) !== null && _b !== void 0 ? _b : defaultReturnTo }),
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -258,13 +241,7 @@ async function handleResetPasswordRequest(req) {

}
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
location: (_b = url.searchParams.get('returnTo')) !== null && _b !== void 0 ? _b : defaultReturnTo,
},
headers: Object.assign(Object.assign({}, (await sessions.updateSession(session))), { location: (_b = url.searchParams.get('returnTo')) !== null && _b !== void 0 ? _b : defaultReturnTo }),
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -271,0 +248,0 @@ return {

@@ -1,20 +0,77 @@

import { getIronSession } from 'iron-session';
const SESSION_COOKIE = 'lg-session';
const SESSION_SECRET = process.env.SESSION_SECRET;
if (!SESSION_SECRET) {
throw new Error('SESSION_SECRET must be set');
}
export async function getLiveSession(req, res) {
const rawSession = await getOrCreateSession(req, res);
if (!rawSession.userId) {
return null;
import { SignJWT, jwtVerify } from 'jose';
export const defaultShortNames = {
userId: 'sub',
};
export class SessionManager {
constructor(options) {
this.options = options;
this.createSession = async (userId) => {
return this.options.createSession(userId);
};
this.getSession = async (req) => {
var _a;
const cookie = (_a = req.headers.get('cookie')) !== null && _a !== void 0 ? _a : '';
const match = cookie.match(new RegExp(`${this.options.cookieName}=([^;]+)`));
if (!match) {
return null;
}
const cookieValue = match[1];
// read the JWT from the cookie
const jwt = await jwtVerify(cookieValue, this.secret);
// convert the JWT claims to a session object
const session = Object.fromEntries(Object.entries(jwt).map(([key, value]) => [this.getLongName(key), value]));
// in dev mode, validate session has the right keys
if (this.options.mode === 'development') {
const keys = Object.keys(session);
const expectedKeys = Object.keys(this.options.shortNames);
if (keys.length !== expectedKeys.length) {
throw new Error('Session has the wrong number of keys');
}
for (const key of keys) {
if (!expectedKeys.includes(key)) {
throw new Error(`Session has unexpected key: ${key}`);
}
}
}
return session;
};
this.updateSession = async (session) => {
const builder = new SignJWT(Object.fromEntries(Object.entries(session).map(([key, value]) => [
this.getShortName(key),
value,
])))
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('1h');
if (this.options.issuer) {
builder.setIssuer(this.options.issuer);
}
if (this.options.audience) {
builder.setAudience(this.options.audience);
}
const jwt = builder.sign(this.secret);
return {
'Set-Cookie': `${this.options.cookieName}=${jwt}; Path=/; HttpOnly; SameSite=Strict`,
};
};
this.clearSession = () => {
return {
'Set-Cookie': `${this.options.cookieName}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`,
};
};
this.getShortName = (key) => {
return this.options.shortNames[key];
};
this.getLongName = (shortName) => {
return this.shortNamesBackwards[shortName];
};
this.secret = new TextEncoder().encode(options.secret);
this.shortNamesBackwards = Object.fromEntries(Object.entries(options.shortNames).map(([key, value]) => [value, key]));
// validate shortnames don't repeat
const values = Object.values(options.shortNames);
if (new Set(values).size !== values.length) {
throw new Error('Short names must be unique');
}
}
return rawSession;
}
export function getOrCreateSession(req, res) {
return getIronSession(req, res, {
cookieName: SESSION_COOKIE,
password: SESSION_SECRET,
});
}
//# sourceMappingURL=session.js.map
import { AuthDB } from './db.js';
import { Email } from './email.js';
import { AuthProvider } from './providers/types.js';
import { Session } from './session.js';
export declare function createHandlers({ providers, db, defaultReturnTo, email: emailService, createSession, }: {
import { SessionManager } from './session.js';
export declare function createHandlers({ providers, db, defaultReturnTo, email: emailService, sessions, }: {
providers: Record<string, AuthProvider>;

@@ -10,3 +10,3 @@ db: AuthDB;

email?: Email;
createSession: (userId: string) => Promise<Session>;
sessions: SessionManager;
}): {

@@ -20,3 +20,3 @@ handleOAuthLoginRequest: (req: Request, opts: {

handleLogoutRequest: (req: Request) => Promise<Response>;
handleSendEmailVerificationRequest: (req: Request) => Promise<void>;
handleSendEmailVerificationRequest: (req: Request) => Promise<Response>;
handleVerifyEmailRequest: (req: Request) => Promise<Response>;

@@ -23,0 +23,0 @@ handleEmailLoginRequest: (req: Request) => Promise<Response>;

export interface Session {
userId: string;
}
export declare function getLiveSession(req: Request, res: Response): Promise<Session | null>;
export declare function getOrCreateSession(req: Request, res: Response): Promise<import("iron-session").IronSession<Partial<Session>>>;
export type ShortNames = {
[key in keyof Session]: string;
};
export declare const defaultShortNames: {
userId: string;
};
export declare class SessionManager {
private options;
private secret;
private shortNamesBackwards;
constructor(options: {
secret: string;
cookieName: string;
shortNames: ShortNames;
mode?: 'production' | 'development';
createSession: (userId: string) => Promise<Session>;
issuer?: string;
audience?: string;
});
createSession: (userId: string) => Promise<Session>;
getSession: (req: Request) => Promise<Session | null>;
updateSession: (session: Session) => Promise<HeadersInit>;
clearSession: () => HeadersInit;
private getShortName;
private getLongName;
}
{
"name": "@a-type/auth",
"version": "0.1.4",
"version": "0.2.0",
"description": "My personal auth request handlers",

@@ -20,3 +20,3 @@ "module": "dist/esm/index.js",

"googleapis": "^129.0.0",
"iron-session": "^8.0.1",
"jose": "^5.2.2",
"nodemailer": "^6.9.8",

@@ -23,0 +23,0 @@ "zod": "^3.22.4"

@@ -5,3 +5,3 @@ import { AuthDB } from './db.js';

import { RETURN_TO_COOKIE } from './returnTo.js';
import { Session, getOrCreateSession } from './session.js';
import { SessionManager } from './session.js';
import * as z from 'zod';

@@ -14,3 +14,3 @@

email: emailService,
createSession,
sessions,
}: {

@@ -21,3 +21,3 @@ providers: Record<string, AuthProvider>;

email?: Email;
createSession: (userId: string) => Promise<Session>;
sessions: SessionManager;
}) {

@@ -109,13 +109,11 @@ const supportsEmail =

const res = new Response(null, {
const session = await sessions.createSession(userId);
const sessionHeaders = await sessions.updateSession(session);
return new Response(null, {
status: 302,
headers: {
...sessionHeaders,
location: url.searchParams.get('returnTo') ?? defaultReturnTo,
},
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(userId);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -126,11 +124,9 @@

const returnTo = url.searchParams.get('returnTo') ?? defaultReturnTo;
const res = new Response(null, {
return new Response(null, {
status: 302,
headers: {
...sessions.clearSession(),
location: returnTo,
},
});
const session = await getOrCreateSession(req, res);
session.destroy();
return res;
}

@@ -167,2 +163,9 @@

});
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: {
'content-type': 'application/json',
},
});
}

@@ -206,13 +209,10 @@

});
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
...(await sessions.updateSession(session)),
location: url.searchParams.get('returnTo') ?? defaultReturnTo,
},
});
const session = await getOrCreateSession(req, res);
const sessionDetails = createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -242,13 +242,10 @@

}
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
...(await sessions.updateSession(session)),
location: params.returnTo ?? defaultReturnTo,
},
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -303,13 +300,10 @@

}
const res = new Response(null, {
const session = await sessions.createSession(user.id);
return new Response(null, {
status: 302,
headers: {
...(await sessions.updateSession(session)),
location: url.searchParams.get('returnTo') ?? defaultReturnTo,
},
});
const session = await getOrCreateSession(req, res);
const sessionDetails = await createSession(user.id);
Object.assign(session, sessionDetails);
await session.save();
return res;
}

@@ -316,0 +310,0 @@

@@ -1,10 +0,3 @@

import { getIronSession } from 'iron-session';
import { SignJWT, jwtVerify } from 'jose';
const SESSION_COOKIE = 'lg-session';
const SESSION_SECRET = process.env.SESSION_SECRET!;
if (!SESSION_SECRET) {
throw new Error('SESSION_SECRET must be set');
}
export interface Session {

@@ -14,18 +7,109 @@ userId: string;

export async function getLiveSession(
req: Request,
res: Response,
): Promise<Session | null> {
const rawSession = await getOrCreateSession(req, res);
if (!rawSession.userId) {
return null;
export type ShortNames = {
[key in keyof Session]: string;
};
export const defaultShortNames = {
userId: 'sub',
};
export class SessionManager {
private secret;
private shortNamesBackwards: Record<string, keyof Session>;
constructor(
private options: {
secret: string;
cookieName: string;
shortNames: ShortNames;
mode?: 'production' | 'development';
createSession: (userId: string) => Promise<Session>;
issuer?: string;
audience?: string;
},
) {
this.secret = new TextEncoder().encode(options.secret);
this.shortNamesBackwards = Object.fromEntries(
Object.entries(options.shortNames).map(([key, value]) => [value, key]),
) as any;
// validate shortnames don't repeat
const values = Object.values(options.shortNames);
if (new Set(values).size !== values.length) {
throw new Error('Short names must be unique');
}
}
return rawSession as Session;
}
export function getOrCreateSession(req: Request, res: Response) {
return getIronSession<Partial<Session>>(req, res, {
cookieName: SESSION_COOKIE,
password: SESSION_SECRET,
});
createSession = async (userId: string): Promise<Session> => {
return this.options.createSession(userId);
};
getSession = async (req: Request) => {
const cookie = req.headers.get('cookie') ?? '';
const match = cookie.match(
new RegExp(`${this.options.cookieName}=([^;]+)`),
);
if (!match) {
return null;
}
const cookieValue = match[1];
// read the JWT from the cookie
const jwt = await jwtVerify(cookieValue, this.secret);
// convert the JWT claims to a session object
const session: Session = Object.fromEntries(
Object.entries(jwt).map(([key, value]) => [this.getLongName(key), value]),
) as any;
// in dev mode, validate session has the right keys
if (this.options.mode === 'development') {
const keys = Object.keys(session);
const expectedKeys = Object.keys(this.options.shortNames);
if (keys.length !== expectedKeys.length) {
throw new Error('Session has the wrong number of keys');
}
for (const key of keys) {
if (!expectedKeys.includes(key)) {
throw new Error(`Session has unexpected key: ${key}`);
}
}
}
return session;
};
updateSession = async (session: Session): Promise<HeadersInit> => {
const builder = new SignJWT(
Object.fromEntries(
Object.entries(session).map(([key, value]) => [
this.getShortName(key),
value,
]),
) as any,
)
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setExpirationTime('1h');
if (this.options.issuer) {
builder.setIssuer(this.options.issuer);
}
if (this.options.audience) {
builder.setAudience(this.options.audience);
}
const jwt = builder.sign(this.secret);
return {
'Set-Cookie': `${this.options.cookieName}=${jwt}; Path=/; HttpOnly; SameSite=Strict`,
};
};
clearSession = (): HeadersInit => {
return {
'Set-Cookie': `${this.options.cookieName}=; Path=/; HttpOnly; SameSite=Strict; Max-Age=0`,
};
};
private getShortName = (key: string) => {
return (this.options.shortNames as any)[key];
};
private getLongName = (shortName: string) => {
return this.shortNamesBackwards[shortName];
};
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet