├── .gitignore ├── README.md ├── app ├── app.vue └── pages │ ├── index.vue │ └── scrypt.vue ├── eslint.config.mjs ├── nuxt.config.ts ├── package.json ├── pnpm-lock.yaml ├── public └── favicon.ico ├── server ├── api │ ├── env.ts │ ├── hash.post.ts │ ├── scrypt │ │ ├── hash.post.ts │ │ └── verify.post.ts │ └── verify.post.ts └── tsconfig.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | 26 | .wrangler -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt Bcrypt Edge 2 | 3 | A demo of hashing and verifying passwords with [bcrypt-edge](https://github.com/bruceharrison1984/bcrypt-edge) on [Cloudflare Workers](https://developers.cloudflare.com/workers/) with [Nuxt](https://nuxt.com) and [NuxtHub](https://hub.nuxt.com). 4 | 5 | https://bcrypt.nuxt.dev 6 | 7 | ## Features 8 | 9 | - Hash & verify a password with bcrypt-edge 10 | - Also works with Scrypt (no dependency needed) 11 | - Server-Side rendering on Cloudflare Workers 12 | 13 | ## Setup 14 | 15 | Make sure to install the dependencies with [pnpm](https://pnpm.io/installation#using-corepack): 16 | 17 | ```bash 18 | pnpm install 19 | ``` 20 | 21 | ## Development Server 22 | 23 | Start the development server on `http://localhost:3000`: 24 | 25 | ```bash 26 | pnpm dev 27 | ``` 28 | 29 | ## Hashing and Verifying 30 | 31 | Hashing the password [./server/api/hash.post.ts](./server/api/hash.post.ts): 32 | 33 | ```ts 34 | import { hashSync } from 'bcrypt-edge/dist/bcrypt-edge' 35 | 36 | export default defineEventHandler(async (event) => { 37 | const { password } = await readBody(event) 38 | 39 | const hash = hashSync(password, 10) 40 | 41 | return { hash } 42 | }); 43 | ``` 44 | 45 | Verifying the password [./server/api/verify.post.ts](./server/api/verify.post.ts): 46 | 47 | ```ts 48 | import { compareSync } from 'bcrypt-edge/dist/bcrypt-edge' 49 | 50 | export default defineEventHandler(async (event) => { 51 | const { hash, password } = await readBody(event) 52 | 53 | const isValid = compareSync(password, hash) 54 | 55 | return { isValid } 56 | }); 57 | ``` 58 | 59 | ## Production 60 | 61 | Build the application for production: 62 | 63 | ```bash 64 | pnpm build 65 | ``` 66 | 67 | ## Deploy 68 | 69 | 70 | Deploy the application on the Edge with [NuxtHub](https://hub.nuxt.com) on your Cloudflare account: 71 | 72 | ```bash 73 | npx nuxthub deploy 74 | ``` 75 | 76 | Then checkout your server logs, analaytics and more in the [NuxtHub Admin](https://admin.hub.nuxt.com). 77 | 78 | You can also deploy using [Cloudflare Pages CI](https://hub.nuxt.com/docs/getting-started/deploy#cloudflare-pages-ci). 79 | 80 | -------------------------------------------------------------------------------- /app/app.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /app/pages/index.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 78 | 79 | 101 | -------------------------------------------------------------------------------- /app/pages/scrypt.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 65 | 66 | 88 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import withNuxt from './.nuxt/eslint.config.mjs' 3 | 4 | export default withNuxt( 5 | // Your custom configs here 6 | ).overrideRules({ 7 | 'vue/max-attributes-per-line': ['warn', { singleline: 3 }], 8 | }) 9 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | compatibilityDate: '2024-07-30', 4 | // https://nuxt.com/docs/getting-started/upgrade#testing-nuxt-4 5 | future: { compatibilityVersion: 4 }, 6 | 7 | // https://nuxt.com/modules 8 | modules: ['@nuxthub/core', '@nuxt/eslint', 'nuxt-auth-utils'], 9 | 10 | // https://eslint.nuxt.com 11 | eslint: { 12 | config: { 13 | stylistic: { 14 | quotes: 'single' 15 | } 16 | } 17 | }, 18 | // https://devtools.nuxt.com 19 | devtools: { enabled: true } 20 | }) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview", 10 | "postinstall": "nuxt prepare", 11 | "lint": "eslint ." 12 | }, 13 | "dependencies": { 14 | "@adonisjs/hash": "^9.0.5", 15 | "@nuxt/eslint": "^0.5.7", 16 | "@nuxthub/core": "0.7.22", 17 | "bcrypt-edge": "^0.1.0", 18 | "nuxt": "^3.13.2", 19 | "nuxt-auth-utils": "^0.4.2", 20 | "vue": "^3.5.10", 21 | "vue-router": "^4.4.5" 22 | }, 23 | "devDependencies": { 24 | "@nuxt/eslint-config": "^0.5.7", 25 | "eslint": "^9.11.1", 26 | "vue-tsc": "^2.1.6", 27 | "wrangler": "^3.79.0" 28 | }, 29 | "packageManager": "pnpm@9.11.0" 30 | } 31 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atinux/nuxt-bcrypt-edge/4bb2fe185722240155a4e2e75c9dd3b5153f0fe9/public/favicon.ico -------------------------------------------------------------------------------- /server/api/env.ts: -------------------------------------------------------------------------------- 1 | export default eventHandler(async (event) => { 2 | return { 3 | test: true, 4 | projectKey: process.env.NUXT_HUB_PROJECT_KEY 5 | } 6 | }) -------------------------------------------------------------------------------- /server/api/hash.post.ts: -------------------------------------------------------------------------------- 1 | import { hashSync } from 'bcrypt-edge' 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { rounds, password } = await readBody(event) 5 | const sanitizedRounds = Math.max(4, Math.min(13, typeof rounds === 'number' ? Math.floor(rounds) : 10)) 6 | 7 | const hash = hashSync(password, sanitizedRounds) 8 | 9 | return { hash } 10 | }); -------------------------------------------------------------------------------- /server/api/scrypt/hash.post.ts: -------------------------------------------------------------------------------- 1 | export default defineEventHandler(async (event) => { 2 | const { password } = await readBody(event) 3 | const hash = await hashPassword(password) 4 | return { hash } 5 | }); -------------------------------------------------------------------------------- /server/api/scrypt/verify.post.ts: -------------------------------------------------------------------------------- 1 | export default defineEventHandler(async (event) => { 2 | const { hash, password } = await readBody(event) 3 | 4 | const isValid = await verifyPassword(hash, password) 5 | 6 | return { isValid } 7 | }); -------------------------------------------------------------------------------- /server/api/verify.post.ts: -------------------------------------------------------------------------------- 1 | import { compareSync } from 'bcrypt-edge' 2 | 3 | export default defineEventHandler(async (event) => { 4 | const { hash, password } = await readBody(event) 5 | 6 | const isValid = compareSync(password, hash) 7 | 8 | return { isValid } 9 | }); -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | --------------------------------------------------------------------------------