Skip to content

NodeJS

Feathers Cloud Auth requests can be verified in NodeJS with any framework.

HTTP

A NodeJS server using the node:http module without any framework can be implemented as follows.

Create an src/authenticate.ts file that validates an incoming request like this:

js
import { IncomingMessage } from 'node:http'
import { createVerifier } from '@featherscloud/auth'

const appId = '<your-app-id>'
const verifier = createVerifier({ appId })

/**
 * Authenticates a request using Feathers Cloud Auth.
 * Will throw an error if verification failed.
 * 
 * @param req The Express or NodeJS request object
 * @returns The authenticated request information like `user` and `token`
 */
export async function authenticateRequest(req: IncomingMessage) {
  const header = req.headers['authorization']
  
  return verifier.verifyHeader(header!)
}

Then implement an HTTP handler with basic CORS CORS (necessary to allow requests from any client framework) in src/app.ts like this:

js
import { createServer } from 'node:http'
import { authenticateRequest } from './authenticate.js'

// Basic headers for handling CORS
const defaultHeaders = {
  'Content-Type': 'application/json',
  'Access-Control-Allow-Headers': '*',
  'Access-Control-Allow-Methods': 'GET',
  'Access-Control-Allow-Origin': '*',
}

const server = createServer(async (req, res) => {
  try {
    if (req.method === 'OPTIONS') {
      res.writeHead(200, defaultHeaders)
      return res.end()
    } else if (req.url === '/message') {
      const { user } = await authenticateRequest(req)
      const response = {
        message: `Hello ${user!.email} from node:http!`,
      }

      res.writeHead(200, defaultHeaders)
      res.end(JSON.stringify(response))
    } else {
      throw new Error(`Not found ${req.url}`)
    }
  }
  catch (error: any) {
    res.writeHead(400, defaultHeaders)
    res.end(JSON.stringify({ error: error.message }))
  }
})

// Listen locally on port 3333
server.listen(3030, '127.0.0.1', () => {
  console.log(`NodeJS application listening on http://localhost:3030`)
})

The full NodeJS example server can be found here.

Express

For Express we can add our own authenticate middleware to authenticate incoming requests in src/authenticate.ts:

js
import { CloudAuthUser, createVerifier } from '@featherscloud/auth'
import type { Request, Response, NextFunction } from 'express'

const appId = '<your-app-id>'
const verifier = createVerifier({ appId })

// Augment the Express request object to include the authenticated user
declare global {
  namespace Express {
    interface Request {
      user?: CloudAuthUser | null
    }
  }
}

/**
 * Authenticates a request using Feathers Cloud Auth.
 * Will throw an error if verification failed.
 * 
 * @param req The Express or NodeJS request object
 * @returns The authenticated request information like `user` and `token`
 */
export async function authenticateRequest(req: Request) {
  const header = req.headers['authorization']
  
  return verifier.verifyHeader(header!)
}

/**
 * An Express middleware that authenticates a request using Feathers Cloud Auth.
 * If successful, the authenticated user is added as `req.user`.
 * 
 * @param req The Express request object
 * @param _res The Express response object
 * @param next Next handler
 */
export async function authenticate(req: Request, _res: Response, next: NextFunction) {
  try {
    const { user } = await authenticateRequest(req)

    // Add the authenticated user information to the request object
    req.user = user

    next()
  } catch (error: unknown) {
    // Pass the error to the Express error handler
    next(error)
  }
}

And then implement an Express application in src/app.ts like this:

js
import cors from 'cors'
import express, { Request, Response, NextFunction } from 'express'
import { authenticate } from './authenticate.js'

const app = express()

app.use(cors())
// On the /message route, require authentication and return a message for the authenticated user
app.get('/message', authenticate, (req, res) => {
  const response = {
    message: `Hello ${req.user!.email} from Express!`,
  }

  res.status(200).json(response)
})

// Handle any errors
app.use((error: Error, _req: Request, res: Response, _next: NextFunction) => {
  res.status(500).json({ message: error?.message || 'Unknown error' })
})

app.listen(3030, '127.0.0.1', () => {
  console.log(
    `Express application listening on http://localhost:3030`,
  )
})

The full Express example server can be found here.