63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import type { MiddlewareHandler } from 'hono'
|
|
import { getCookie, setCookie } from 'hono/cookie'
|
|
import { env } from 'hono/adapter'
|
|
import { HTTPException } from 'hono/http-exception'
|
|
|
|
import { getRandomState } from '../../utils/getRandomState'
|
|
import { AuthFlow } from './authFlow'
|
|
import type { LinkedInScope } from './types'
|
|
|
|
export function linkedinAuth(options: {
|
|
client_id?: string
|
|
client_secret?: string
|
|
scope?: LinkedInScope[]
|
|
appAuth?: boolean
|
|
}): MiddlewareHandler {
|
|
return async (c, next) => {
|
|
const newState = getRandomState()
|
|
// Create new Auth instance
|
|
const auth = new AuthFlow({
|
|
client_id: options.client_id || (env(c).LINKEDIN_ID as string),
|
|
client_secret: options.client_secret || (env(c).LINKEDIN_SECRET as string),
|
|
redirect_uri: c.req.url.split('?')[0],
|
|
scope: options.scope,
|
|
state: newState,
|
|
appAuth: options.appAuth || false,
|
|
code: c.req.query('code'),
|
|
})
|
|
|
|
// Avoid CSRF attack by checking state
|
|
if (c.req.url.includes('?')) {
|
|
const storedState = getCookie(c, 'state')
|
|
if (c.req.query('state') !== storedState) {
|
|
throw new HTTPException(401)
|
|
}
|
|
}
|
|
|
|
// Redirect to login dialog
|
|
if (!auth.code && !options.appAuth) {
|
|
setCookie(c, 'state', newState, {
|
|
maxAge: 60 * 10,
|
|
httpOnly: true,
|
|
path: '/',
|
|
// secure: true,
|
|
})
|
|
return c.redirect(auth.redirect())
|
|
}
|
|
|
|
if (options.appAuth) {
|
|
await auth.getAppToken()
|
|
} else {
|
|
await auth.getUserData()
|
|
}
|
|
|
|
// Set return info
|
|
c.set('token', auth.token)
|
|
c.set('refresh-token', auth.refresh_token)
|
|
c.set('user-linkedin', auth.user)
|
|
c.set('granted-scopes', auth.granted_scopes)
|
|
|
|
await next()
|
|
}
|
|
}
|