Dearest Community
I have an increasing amount of serverless functions, most of them requiring auth. I found myself repeating the following code to check if the user is authenticated in each of the functions:
const { user } = context.clientContext;
if (!user) {
return {
statusCode: 401,
body: JSON.stringify({ ok: false, msg: "Unauthorized" }),
};
}
as you can see, I’m just returning a 401 error with some json if there is no user in the clientContext - no rocket science going on here.
I was wondering and searching for a “nice-ish” way to call this piece of code like a middleware, but all my search results pointed me in the direction of using express with serverless…which, to my understanding, is not really the point of serverless “functions” right!?!
Anyway - I stumbled across the MDN documentation on Proxy (handler.apply() - JavaScript | MDN) which led me to come up with something like this:
const decline_orders = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
ok: true,
data: "bonjour",
}),
};
}
const handler = {
apply: (target, thisArg, argumentsList) => {
const { user } = argumentsList[1].clientContext
if (!user) {
return {
statusCode: 401,
body: JSON.stringify({ ok: false, msg: "Unauthorized" }),
};
}
return target(argumentsList[0], argumentsList[1])
}
}
const useAuth = new Proxy(decline_orders, handler)
exports.handler = (event, context) => useAuth(event, context)
Now, the two questions I have are, 1) am I going to be disowned by the JS/Netlify community for attempting such a thing and 2) is there a simpler way (apart from calling a function inside every serverless-function) to achieve this nice feeling of middleware encapsulation.
Any help, advice or feedback is greatly appreciated
Cheers, Ben
UPDATE
Here’s an usage example (/.netlify/functions/middleware/auth.js):
const withAuth = func => (a, b) => {
const handler = {
apply: (target, thisArg, args) => {
const { user } = args[1].clientContext
if (!user) {
return {
statusCode: 401,
body: JSON.stringify({ ok: false, msg: "Unauthorized" }),
};
}
return target(args[0], args[1])
}
}
const proxy = new Proxy(func, handler)
return proxy.apply(this, [a, b])
}
module.exports = withAuth;
and can be used like this (/.netlify/functions/foo.js):
const withAuth = require("./middleware/auth")
const decline_orders = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
ok: true,
data: "bonjour",
}),
};
}
exports.handler = (event, context) => withAuth(decline_orders)(event, context);