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

cloudflare-auth

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cloudflare-auth - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0

demo/.dev.vars

3

demo/functions/dash/_middleware.ts

@@ -1,4 +0,3 @@

import { authConfig } from 'lib/constants';
import { middlewareGuard } from 'cloudflare-auth';
export const onRequest = [middlewareGuard(authConfig)];
export const onRequest = [middlewareGuard];
import { html, htmlResponse } from 'cloudflare-htmx';
import { getJWTPayload, logout } from 'cloudflare-auth';
import { authConfig } from '@lib/constants';
import { getJWTPayload, logout, Env } from 'cloudflare-auth';
export const onRequestPost: PagesFunction = async ({ request }) => {
return logout(authConfig);
export const onRequestPost: PagesFunction<Env> = async ({ env }) => {
return logout(env, '/');
};
export const onRequestGet: PagesFunction = async ({ request }) => {
const payload = await getJWTPayload(authConfig, request);
export const onRequestGet: PagesFunction<Env> = async ({ request, env }) => {
const payload = await getJWTPayload(request, env);
return htmlResponse(

@@ -12,0 +11,0 @@ html`

import { Env, loginWithToken } from 'cloudflare-auth';
import Toast from '@components/Toast';
import { html, htmlResponse } from 'cloudflare-htmx';
import { authConfig } from '@lib/constants';

@@ -14,3 +13,3 @@ export const onRequestPost: PagesFunction<Env> = async ({ request, env }) => {

try {
const magicLink = await loginWithToken(email, env, url.origin, authConfig);
const magicLink = await loginWithToken(email, env, url.origin, true);
return htmlResponse(Toast(html` <a class="link text-primary" href="${magicLink}">Click here to login</a> `, 'alert-success', false));

@@ -17,0 +16,0 @@ } catch (e) {

@@ -1,7 +0,6 @@

import { authConfig } from '@lib/constants';
import { isAuthorised, Env } from 'cloudflare-auth';
import { html, htmlResponse } from 'cloudflare-htmx';
export const onRequestGet: PagesFunction<Env> = async ({ request }) => {
const authorised = await isAuthorised(authConfig, request);
export const onRequestGet: PagesFunction<Env> = async ({ request, env }) => {
const authorised = await isAuthorised(request, env);
if (authorised) {

@@ -8,0 +7,0 @@ return htmlResponse(html`<h1 class="text-3xl text-primary">You are authorised!</h1>`);

@@ -1,2 +0,1 @@

import { authConfig } from '@lib/constants';
import { verify, Env } from 'cloudflare-auth';

@@ -8,3 +7,3 @@

try {
return await verify(token!, env, authConfig);
return await verify(token!, env, '/dash');
} catch {

@@ -11,0 +10,0 @@ return Response.redirect(url.origin, 301);

@@ -9,3 +9,4 @@ {

"tailwind": "tailwindcss build -i ./tailwind.css -o ./static/css/output.css --watch",
"db:init": "wrangler d1 execute auth --local --file=./schema.sql"
"db:init:local": "wrangler d1 execute auth --local --file=./schema.sql",
"db:init": "wrangler d1 execute auth --file=./schema.sql"
},

@@ -12,0 +13,0 @@ "devDependencies": {

@@ -1,4 +0,2 @@

import { AuthConfig } from 'cloudflare-auth';
export const authConfig: AuthConfig = {
export const authConfig = {
secretKey: 'this_is_your_secretKey',

@@ -5,0 +3,0 @@ issuer: 'urn:continuata:issuer',

{
"name": "cloudflare-auth",
"version": "1.3.1",
"version": "1.4.0",
"description": "JWT implementation for Cloudflare using D1",

@@ -5,0 +5,0 @@ "main": "src/index.ts",

@@ -16,5 +16,3 @@ # cloudflare-auth - Simple Auth for Cloudflare Pages

import { AuthConfig } from 'cloudflare-auth';
export const authConfig: AuthConfig = {
export const authConfig = {
secretKey: 'this_is_your_secretKey',

@@ -21,0 +19,0 @@ issuer: 'urn:continuata:issuer',

import { Env } from './interfaces';
import type { AuthConfig } from './interfaces';

@@ -38,4 +37,3 @@ export const sendEmail = async (urlOrigin: string, payload: any) => {

link: string,
env: Env,
config: AuthConfig
env: Env
) => {

@@ -52,4 +50,4 @@ return await sendEmail(urlOrigin, {

from: {
email: config.adminEmail,
name: config.adminName,
email: env.ADMIN_EMAIL,
name: env.ADMIN_NAME,
},

@@ -70,4 +68,3 @@ subject: 'Verify your email address',

link: string,
env: Env,
config: AuthConfig
env: Env
) => {

@@ -84,4 +81,4 @@ return await sendEmail(urlOrigin, {

from: {
email: config.adminEmail,
name: config.adminName,
email: env.ADMIN_EMAIL,
name: env.ADMIN_NAME,
},

@@ -88,0 +85,0 @@ subject: 'Confirm login',

import * as jose from 'jose';
export type UserRole = 'user' | 'admin' | 'super';
export interface Env {

@@ -8,4 +10,11 @@ DB: D1Database;

DKIM_PRIVATE_KEY: string;
COOKIE_NAME: string;
SECRET_KEY: string;
ISSUER: string;
AUDIENCE: string;
EXPIRY: string;
ADMIN_EMAIL: string;
ADMIN_NAME: string;
SALT: string;
}
export interface UserToken {

@@ -23,3 +32,3 @@ email: string;

created_at?: string;
role: 'user' | 'admin' | 'super';
role: UserRole;
active?: 0 | 1;

@@ -34,16 +43,2 @@ verified?: 0 | 1;

export interface AuthConfig {
secretKey: string;
issuer: string;
audience: string;
expiry: string;
cookieName: string;
redirectTo: string;
loginPath: string;
allowUserSignup: boolean;
salt: string;
adminEmail: string;
adminName: string;
}
export interface JWTPayload extends jose.JWTPayload {

@@ -50,0 +45,0 @@ uid: string;

@@ -11,4 +11,3 @@ import { Kysely } from 'kysely';

password: string,
env: CloudflareAuth.Env,
config: CloudflareAuth.AuthConfig
env: CloudflareAuth.Env
) => {

@@ -26,3 +25,3 @@ const db = new Kysely<CloudflareAuth.Database>({

}
const hashedPassword = await hashPassword(password, config);
const hashedPassword = await hashPassword(password, env);
if (hashedPassword !== users_row.password) {

@@ -38,3 +37,3 @@ throw new Error('Invalid password');

urlOrigin: string,
config: CloudflareAuth.AuthConfig
allowUserSignup = false
) => {

@@ -49,3 +48,3 @@ const db = new Kysely<CloudflareAuth.Database>({

.executeTakeFirst();
if (!users_row && !config.allowUserSignup) {
if (!users_row && !allowUserSignup) {
throw new Error('User not found');

@@ -55,3 +54,3 @@ }

const magicLink = `${urlOrigin}/verify?token=${token}`;
await sendLoginMagicLinkEmail(urlOrigin, email, magicLink, env, config);
await sendLoginMagicLinkEmail(urlOrigin, email, magicLink, env);
return magicLink;

@@ -63,3 +62,3 @@ };

env: CloudflareAuth.Env,
config: CloudflareAuth.AuthConfig
redirectTo: string
): Promise<Response> => {

@@ -88,8 +87,8 @@ const db = new Kysely<CloudflareAuth.Database>({

const jwt = await generateJWT(user.uid, email, config);
const accessCookie = `${config.cookieName}=${jwt}; path=/; max-age=${config.expiry}; SameSite=Lax; HttpOnly; Secure`;
const jwt = await generateJWT(user.uid, email, env);
const accessCookie = `${env.COOKIE_NAME}=${jwt}; path=/; max-age=${env.EXPIRY}; SameSite=Lax; HttpOnly; Secure`;
return new Response(null, {
status: 301,
headers: {
Location: config.redirectTo,
Location: redirectTo,
'Set-Cookie': accessCookie,

@@ -101,9 +100,10 @@ },

export const logout = async (
config: CloudflareAuth.AuthConfig
env: CloudflareAuth.Env,
loginPath: string
): Promise<Response> => {
const accessCookie = `${config.cookieName}=''; path=/; max-age=-1; SameSite=Lax; HttpOnly; Secure`;
const accessCookie = `${env.COOKIE_NAME}=''; path=/; max-age=-1; SameSite=Lax; HttpOnly; Secure`;
return new Response(null, {
status: 301,
headers: {
Location: config.loginPath,
Location: loginPath,
'Set-Cookie': accessCookie,

@@ -110,0 +110,0 @@ },

@@ -11,4 +11,3 @@ import { Kysely } from 'kysely';

password: string,
env: CloudflareAuth.Env,
config: CloudflareAuth.AuthConfig
env: CloudflareAuth.Env
) => {

@@ -18,3 +17,3 @@ const db = new Kysely<CloudflareAuth.Database>({

});
const hashedPassword = await hashPassword(password, config);
const hashedPassword = await hashPassword(password, env);
const uid = uuid();

@@ -31,3 +30,3 @@ await db

env: CloudflareAuth.Env,
config: CloudflareAuth.AuthConfig
redirectTo: string
): Promise<Response> => {

@@ -62,8 +61,8 @@ const db = new Kysely<CloudflareAuth.Database>({

const jwt = await generateJWT(user.uid, email, config);
const accessCookie = `${config.cookieName}=${jwt}; path=/; max-age=${config.expiry}; SameSite=Lax; HttpOnly; Secure`;
const jwt = await generateJWT(user.uid, email, env);
const accessCookie = `${env.COOKIE_NAME}=${jwt}; path=/; max-age=${env.EXPIRY}; SameSite=Lax; HttpOnly; Secure`;
return new Response(null, {
status: 301,
headers: {
Location: config.redirectTo,
Location: redirectTo,
'Set-Cookie': accessCookie,

@@ -70,0 +69,0 @@ },

@@ -11,3 +11,3 @@ import * as jose from 'jose';

env: CloudflareAuth.Env,
role: string = 'user'
role: CloudflareAuth.UserRole = 'user'
) => {

@@ -38,3 +38,3 @@ const token = uuid();

.insertInto('users')
.values({ uid, email, verified: 1, role: 'user' })
.values({ uid, email, verified: 1, role })
.execute();

@@ -48,5 +48,5 @@ }

email: string,
config: CloudflareAuth.AuthConfig
env: CloudflareAuth.Env
) => {
const secret = new TextEncoder().encode(config.secretKey);
const secret = new TextEncoder().encode(env.SECRET_KEY);
const alg = 'HS256';

@@ -56,5 +56,5 @@ return await new jose.SignJWT({ uid, email })

.setIssuedAt()
.setIssuer(config.issuer)
.setAudience(config.audience)
.setExpirationTime(config.expiry)
.setIssuer(env.ISSUER)
.setAudience(env.AUDIENCE)
.setExpirationTime(env.EXPIRY)
.sign(secret);

@@ -65,3 +65,3 @@ };

password: string,
config: CloudflareAuth.AuthConfig
env: CloudflareAuth.Env
) => {

@@ -72,5 +72,5 @@ const hashedPassword = await crypto.subtle.digest(

},
new TextEncoder().encode(password + config.salt)
new TextEncoder().encode(password + env.SALT)
);
return String(hashedPassword);
};

@@ -6,31 +6,33 @@ import * as jose from 'jose';

export const middlewareGuard =
(authConfig: CloudflareAuth.AuthConfig): PagesFunction =>
async ({ request, next }) => {
const cookie = parse(request.headers.get('Cookie') || '');
const jwt = cookie[authConfig.cookieName];
const secret = new TextEncoder().encode(authConfig.secretKey);
try {
await jose.jwtVerify(jwt, secret, {
issuer: authConfig.issuer,
audience: authConfig.audience,
});
return next();
} catch {
const url = new URL(request.url);
return Response.redirect(url.origin, 301);
}
};
export const middlewareGuard: PagesFunction<CloudflareAuth.Env> = async ({
request,
next,
env,
}) => {
const cookie = parse(request.headers.get('Cookie') || '');
const jwt = cookie[env.COOKIE_NAME];
const secret = new TextEncoder().encode(env.SECRET_KEY);
try {
await jose.jwtVerify(jwt, secret, {
issuer: env.ISSUER,
audience: env.AUDIENCE,
});
return next();
} catch {
const url = new URL(request.url);
return Response.redirect(url.origin, 301);
}
};
export const isAuthorised = async (
authConfig: CloudflareAuth.AuthConfig,
request: Request
request: Request,
env: CloudflareAuth.Env
): Promise<boolean> => {
const cookie = parse(request.headers.get('Cookie') || '');
const jwt = cookie[authConfig.cookieName];
const secret = new TextEncoder().encode(authConfig.secretKey);
const jwt = cookie[env.COOKIE_NAME];
const secret = new TextEncoder().encode(env.SECRET_KEY);
try {
await jose.jwtVerify(jwt, secret, {
issuer: authConfig.issuer,
audience: authConfig.audience,
issuer: env.ISSUER,
audience: env.AUDIENCE,
});

@@ -44,8 +46,8 @@ return true;

export const getJWTPayload = async (
authConfig: CloudflareAuth.AuthConfig,
request: Request
request: Request,
env: CloudflareAuth.Env
): Promise<CloudflareAuth.JWTPayload> => {
const cookie = parse(request.headers.get('Cookie') || '');
const jwt = cookie[authConfig.cookieName];
const jwt = cookie[env.COOKIE_NAME];
return jose.decodeJwt(jwt) as CloudflareAuth.JWTPayload;
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc