Skip to content

Commit

Permalink
Add jwt verify (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
likui628 authored Sep 24, 2024
1 parent 6c92e42 commit 9431669
Show file tree
Hide file tree
Showing 9 changed files with 259 additions and 11 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text eol=lf
190 changes: 189 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,21 @@
"dotenv": "^16.4.5",
"express": "^4.21.0",
"helmet": "^7.1.0",
"jsonwebtoken": "^9.0.2",
"morgan": "^1.10.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/jest": "^29.5.13",
"@types/jsonwebtoken": "^9.0.7",
"@types/morgan": "^1.9.9",
"@types/node": "^22.5.5",
"@types/passport": "^1.0.16",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.2",
"@typescript-eslint/eslint-plugin": "^8.6.0",
"@typescript-eslint/parser": "^8.6.0",
Expand Down
5 changes: 5 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import morgan from 'morgan'
import helmet from 'helmet'
import cors from 'cors'
import dotenv from 'dotenv'
import passport from 'passport'

import routes from './routes/v1'
import { errorHandler, notFound } from './middlewares'
import { jwtStrategy } from './config/passport'

dotenv.config()

const app = express()

app.use(passport.initialize())
passport.use('jwt', jwtStrategy)

app.use(morgan('dev'))
app.use(helmet())
app.use(cors())
Expand Down
28 changes: 28 additions & 0 deletions src/config/passport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
Strategy as JwtStrategy,
ExtractJwt,
StrategyOptions,
} from 'passport-jwt'
import { prisma } from '../utils'

const options: StrategyOptions = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.JWT_SECRET || 'your_jwt_secret',
}

export const jwtStrategy = new JwtStrategy(
options,
async (jwtPayload, done) => {
try {
const user = await prisma.user.findUnique({
where: { id: jwtPayload.id },
})
if (!user) {
throw new Error('User not found')
}
return done(null, user)
} catch (error) {
return done(error, false)
}
},
)
24 changes: 24 additions & 0 deletions src/middlewares/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { NextFunction, Request, Response } from 'express'
import passport from 'passport'
import { errorResponse } from '../utils'

const verifyCallback =
(req: Request, res: Response, next: NextFunction) =>
async (err: unknown, user: Express.User | null) => {
if (err) {
return errorResponse(res, err, 500, 'Unauthorized')
}
if (!user) {
return errorResponse(res, err, 401, 'Unauthorized')
}
req.user = user
next()
}

export const auth = (req: Request, res: Response, next: NextFunction) => {
passport.authenticate(
'jwt',
{ session: false },
verifyCallback(req, res, next),
)(req, res, next)
}
14 changes: 5 additions & 9 deletions src/middlewares/error.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { NextFunction, Request, Response } from 'express'
import ErrorResponse from '../interfaces/error-response'
import { errorResponse } from '../utils'

export function notFound(req: Request, res: Response, next: NextFunction) {
res.status(404)
const error = new Error(`🔍 - Not Found - ${req.originalUrl}`)
next(error)
export function notFound(req: Request, res: Response, _next: NextFunction) {
const error = new Error(`Not Found - ${req.originalUrl}`)
return errorResponse(res, error, 404, 'Not Found')
}

export function errorHandler(
Expand All @@ -14,9 +14,5 @@ export function errorHandler(
_next: NextFunction,
) {
const statusCode = res.statusCode !== 200 ? res.statusCode : 500
res.status(statusCode)
res.json({
message: err.message,
stack: process.env.NODE_ENV === 'production' ? '' : err.stack,
})
return errorResponse(res, err.message, statusCode, 'Unhandled error')
}
Loading

0 comments on commit 9431669

Please sign in to comment.