Skip to content

Commit

Permalink
chore: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
atinux committed Sep 25, 2024
1 parent c7fbb75 commit 9918a13
Show file tree
Hide file tree
Showing 11 changed files with 265 additions and 67 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ Make sure to set the callback URL in your OAuth app settings as `<your-domain>/a

If the redirect URL mismatch in production, this means that the module cannot guess the right redirect URL. You can set the `NUXT_OAUTH_<PROVIDER>_REDIRECT_URL` env variable to overwrite the default one.

### Password Utils

Nuxt Auth Utils provides a `hashPassword` and `verifyPassword` function to hash and verify passwords by using [scrypt](https://en.wikipedia.org/wiki/Scrypt) as it is supported in many JS runtime.

```ts
const hashedPassword = await hashPassword('user_password')

if (await verifyPassword(hashedPassword, 'user_password')) {
// Password is valid
}
```

You can configure the scrypt options in your `nuxt.config.ts`:

```ts
export default defineNuxtConfig({
modules: ['nuxt-auth-utils'],
auth: {
hash: {
scrypt: {
// See https://github.com/adonisjs/hash/blob/94637029cd526783ac0a763ec581306d98db2036/src/types.ts#L144
}
}
}
})
```


### Extend Session

We leverage hooks to let you extend the session data with your own data or log when the user clears the session.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"test:watch": "vitest watch"
},
"dependencies": {
"@adonisjs/hash": "^9.0.5",
"@nuxt/kit": "^3.13.0",
"defu": "^6.1.4",
"hookable": "^5.5.3",
Expand Down
6 changes: 0 additions & 6 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ export default defineNuxtConfig({
extends: ['@nuxt/ui-pro'],
modules: ['nuxt-auth-utils', '@nuxt/ui'],
auth: {},
ui: {
icons: ['simple-icons', 'gravity-ui'],
},
devtools: { enabled: true },
imports: {
autoImport: true,
Expand All @@ -19,9 +16,6 @@ export default defineNuxtConfig({
database: true,
},
},
runtimeConfig: {
passwordHashRounds: 12,
},
routeRules: {
'/': {
// prerender: true,
Expand Down
3 changes: 2 additions & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
},
"dependencies": {
"nuxt": "^3.13.2",
"nuxt-auth-utils": "latest"
"nuxt-auth-utils": "latest",
"zod": "^3.23.8"
},
"devDependencies": {
"@iconify-json/gravity-ui": "^1.2.1",
Expand Down
15 changes: 8 additions & 7 deletions playground/server/api/login.post.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { HashedPassword } from "#auth-utils"
import { z } from 'zod'

interface DBUser {
id: number
email: string
password: HashedPassword
password: string
}

export default defineLazyEventHandler(async () => {
Expand All @@ -18,17 +18,18 @@ export default defineLazyEventHandler(async () => {
})

return defineEventHandler(async (event) => {
const body = await readBody(event)
const { email, password } = await readValidatedBody(event, z.object({
email: z.string().email(),
password: z.string().min(8),
}).parse)

const email = body.email

const user = await db.sql<{ rows: DBUser[] }>`SELECT * FROM users WHERE email = ${email}`.then((result) => result.rows[0])
const user = await db.sql<{ rows: DBUser[] }>`SELECT * FROM users WHERE email = ${email}`.then(result => result.rows[0])

if (!user) {
throw invalidCredentialsError
}

if(!comparePassword(user.password, body.password)) {
if (!(await verifyPassword(user.password, password))) {
throw invalidCredentialsError
}

Expand Down
14 changes: 8 additions & 6 deletions playground/server/api/register.post.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { z } from 'zod'

export default defineLazyEventHandler(async () => {
const db = useDatabase()

await db.sql`CREATE TABLE IF NOT EXISTS users ("id" INTEGER PRIMARY KEY AUTOINCREMENT, "email" TEXT UNIQUE NOT NULL, "password" TEXT NOT NULL)`

return defineEventHandler(async (event) => {
const runtimeConfig = useRuntimeConfig(event)

const body = await readBody(event)
const { email, password } = await readValidatedBody(event, z.object({
email: z.string().email(),
password: z.string().min(8),
}).parse)

const email = body.email
const password = hashPassword(body.password, { rounds: runtimeConfig.passwordHashRounds })
const hashedPassword = await hashPassword(password)

await db.sql`INSERT INTO users(email, password) VALUES (${email}, ${password})`
await db.sql`INSERT INTO users(email, password) VALUES (${email}, ${hashedPassword})`

// In real applications, you should send a confirmation email to the user before logging them in.

Expand Down
Loading

0 comments on commit 9918a13

Please sign in to comment.