packages/authentication-oauth/src/utils.ts
import type { RequestHandler } from 'express'
import type { Middleware, Application as KoaApplication } from '@feathersjs/koa'
import type { ServiceOptions } from '@feathersjs/feathers'
import '@feathersjs/koa'
import '@feathersjs/express'
import expressCookieSession from 'cookie-session'
import koaCookieSession from 'koa-session'
import { AuthenticationService } from '@feathersjs/authentication'
import { GrantConfig } from 'grant'
export interface OauthSetupSettings {
linkStrategy: string
authService?: string
expressSession?: RequestHandler
koaSession?: Middleware
}
export const getGrantConfig = (service: AuthenticationService): GrantConfig => {
const {
app,
configuration: { oauth }
} = service
// Set up all the defaults
const port = app.get('port')
let host = app.get('host')
let protocol = 'https'
// Development environments commonly run on HTTP with an extended port
if (process.env.NODE_ENV !== 'production') {
protocol = 'http'
if (String(port) !== '80') {
host += `:${port}`
}
}
// omit 'redirect' and 'origins' from oauth
const { redirect, origins, ...oauthConfig } = oauth
const grant: GrantConfig = {
...oauthConfig,
defaults: {
prefix: '/oauth',
origin: `${protocol}://${host}`,
transport: 'state',
response: ['tokens', 'raw', 'profile'],
...oauthConfig.defaults
}
}
const getUrl = (url: string) => {
const { defaults } = grant
return `${defaults.origin}${defaults.prefix}/${url}`
}
// iterate over grant object with key and value
for (const [name, value] of Object.entries(grant)) {
if (name !== 'defaults') {
value.redirect_uri = value.redirect_uri || getUrl(`${name}/callback`)
}
}
return grant
}
export const setExpressParams: RequestHandler = (req, res, next) => {
req.session.destroy ||= () => {
req.session = null
}
req.feathers = {
...req.feathers,
session: req.session,
state: res.locals
}
next()
}
export const setKoaParams: Middleware = async (ctx, next) => {
ctx.session.destroy ||= () => {
ctx.session = null
}
ctx.feathers = {
...ctx.feathers,
session: ctx.session,
state: ctx.state
} as any
await next()
}
export const authenticationServiceOptions = (
service: AuthenticationService,
settings: OauthSetupSettings
): ServiceOptions => {
const { secret } = service.configuration
const koaApp = service.app as KoaApplication
if (koaApp.context) {
koaApp.keys = [secret]
const { koaSession = koaCookieSession({ key: 'feathers.oauth' }, koaApp as any) } = settings
return {
koa: {
before: [koaSession, setKoaParams]
}
}
}
const {
expressSession = expressCookieSession({
name: 'feathers.oauth',
keys: [secret]
})
} = settings
return {
express: {
before: [expressSession, setExpressParams]
}
}
}