2022-10-31 16:07:56 +01:00
|
|
|
import type { MiddlewareHandler } from '../../types.ts'
|
2022-07-02 08:09:45 +02:00
|
|
|
import { Jwt } from '../../utils/jwt/index.ts'
|
|
|
|
import type { AlgorithmTypes } from '../../utils/jwt/types.ts'
|
|
|
|
|
2022-09-14 01:17:20 +02:00
|
|
|
export const jwt = (options: {
|
|
|
|
secret: string
|
|
|
|
cookie?: string
|
|
|
|
alg?: string
|
|
|
|
}): MiddlewareHandler => {
|
2022-07-02 08:09:45 +02:00
|
|
|
if (!options) {
|
|
|
|
throw new Error('JWT auth middleware requires options for "secret')
|
|
|
|
}
|
|
|
|
|
2022-07-16 03:26:14 +02:00
|
|
|
if (!crypto.subtle || !crypto.subtle.importKey) {
|
|
|
|
throw new Error('`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.')
|
|
|
|
}
|
|
|
|
|
2022-09-14 01:17:20 +02:00
|
|
|
return async (ctx, next) => {
|
2022-07-02 08:09:45 +02:00
|
|
|
const credentials = ctx.req.headers.get('Authorization')
|
2022-08-03 04:24:51 +02:00
|
|
|
let token
|
|
|
|
if (credentials) {
|
|
|
|
const parts = credentials.split(/\s+/)
|
|
|
|
if (parts.length !== 2) {
|
2022-10-19 13:24:43 +02:00
|
|
|
return new Response('Unauthorized', {
|
2022-08-03 04:24:51 +02:00
|
|
|
status: 401,
|
|
|
|
headers: {
|
|
|
|
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_request",error_description="invalid credentials structure"`,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
token = parts[1]
|
|
|
|
}
|
|
|
|
} else if (options.cookie) {
|
|
|
|
token = ctx.req.cookie(options.cookie)
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
|
|
|
|
2022-08-03 04:24:51 +02:00
|
|
|
if (!token) {
|
2022-10-19 13:24:43 +02:00
|
|
|
return new Response('Unauthorized', {
|
2022-07-02 08:09:45 +02:00
|
|
|
status: 401,
|
|
|
|
headers: {
|
|
|
|
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_request",error_description="no authorization included in request"`,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
let authorized = false
|
|
|
|
let msg = ''
|
|
|
|
try {
|
2022-08-03 04:24:51 +02:00
|
|
|
authorized = await Jwt.verify(token, options.secret, options.alg as AlgorithmTypes)
|
2022-07-02 08:09:45 +02:00
|
|
|
} catch (e) {
|
|
|
|
msg = `${e}`
|
|
|
|
}
|
|
|
|
if (!authorized) {
|
2022-10-19 13:24:43 +02:00
|
|
|
return new Response('Unauthorized', {
|
2022-07-02 08:09:45 +02:00
|
|
|
status: 401,
|
|
|
|
statusText: msg,
|
|
|
|
headers: {
|
|
|
|
'WWW-Authenticate': `Bearer realm="${ctx.req.url}",error="invalid_token",error_description="token verification failure"`,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
await next()
|
|
|
|
}
|
|
|
|
}
|