Rocky Balboa
Rocky Balboa

Reputation: 814

Nodejs authentication middleware not working

I am learning a new way to authenticate all my APIs using the application-level middleware. I looked into multiple examples. I tried the following code as one of the ways.

Below is my code, I am writing firebase function with the help of necessary fields already there. I use "firebase serve" to host my functions locally.

const express = require('express')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')()
const cors = require('cors')({ origin: true })
const app = express()
const router = express.Router()

app.use(cors)
app.use(cookieParser)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))

app.use(async (err, req, res, next) => {
    console.log('Middleware')
    try {
        const { authorization } = req.headers

        if (!authorization) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        if (!authorization.startsWith('Bearer')) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        const split = authorization.split('Bearer ')
        if (split.length !== 2) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        const token = split[1]
        const decodedToken = await admin.auth().verifyIdToken(token);
        res.setHeader("email", decodedToken.email)
        next()
    } catch (error) {
        console.log("END")
        next(error)
    }
});

router.get('/', (req, res) => {
    res.end(`${Date.now()}`)
})

router.post('/data', async (req, res, next) => {
    res.setHeader("Content-Type", "application/json")
    console.log('DATA')
    try {
        // my other logic goes here
        res.end()
    } catch (error) {
        next(error)
    }
})

app.use('/api', router)
app.use((err, req, res, next) => {
    if (err) {
        handleError(err, res);
    }
    console.log(JSON.stringify(req.body))
});

exports.app = functions.https.onRequest(app)

I have created a cloud function named app. I am using API like this:

http://localhost:5000/app/api/data

I have written a middleware for authorizing all my APIs that are coming. Middleware is fetching bearer token and token is being verified with the help of firebase.

But when I call "/api/data" this API from postman or web the middleware is not called. For debugging purpose I used console.log to check.

My current flow is POSTMAN -> DATA

What I want is:

POSTMAN -> MIDDLEWARE(if authenticated) -> DATA

POSTMAN -> MIDDLEWARE(if not authenticated) -> END

Please let me know what is the issue with my code is.

Upvotes: 1

Views: 2836

Answers (1)

Rahul Pal
Rahul Pal

Reputation: 488

Remove err parameter from the middleware, You are setting it as an error handler instead of a middleware, this is the reason the code is not getting executed, Below code will execute the handler every time you access the /api route


const express = require('express')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')()
const cors = require('cors')({ origin: true })
const app = express()
const router = express.Router()

app.use(cors)
app.use(cookieParser)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
 
app.use(async (req, res, next) => {
    console.log('Middleware')
    try {
        const { authorization } = req.headers

        if (!authorization) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        if (!authorization.startsWith('Bearer')) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        const split = authorization.split('Bearer ')
        if (split.length !== 2) {
            throw new ErrorHandler(401, "User is not unathorized")
        }

        const token = split[1]
        const decodedToken = await admin.auth().verifyIdToken(token);
        res.setHeader("email", decodedToken.email)
        next()
    } catch (error) {
        console.log("END")
        next(error)
    }
});

router.get('/', (req, res) => {
    res.end(`${Date.now()}`)
})

router.post('/data', async (req, res, next) => {
    res.setHeader("Content-Type", "application/json")
    console.log('DATA')
    try {
        // my other logic goes here
        res.end()
    } catch (error) {
        next(error)
    }
})

app.use('/api', router)
app.use((err, req, res, next) => {
    if (err) {
        handleError(err, res);
    }
    console.log(JSON.stringify(req.body))
});

exports.app = functions.https.onRequest(app)

Upvotes: 2

Related Questions