After looking into this further, and taking a hint from @ricka's answer, I have decided to implement an authentication check for my cloud function with a JWT token passed into the form of an Authorization
header access token.
Here's the implementation in JavaScript:
const client = jwksClient({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: "https://<auth0-account>.auth0.com/.well-known/jwks.json",
});
function verifyToken(token, cb) {
let decodedToken;
try {
decodedToken = jwt.decode(token, { complete: true });
} catch (e) {
console.error(e);
cb(e);
return;
}
client.getSigningKey(decodedToken.header.kid, function (err, key) {
if (err) {
console.error(err);
cb(err);
return;
}
const signingKey = key.publicKey || key.rsaPublicKey;
jwt.verify(token, signingKey, function (err, decoded) {
if (err) {
console.error(err);
cb(err);
return;
}
console.log(decoded);
cb(null, decoded);
});
});
}
function checkAuth(fn) {
return function (req, res) {
if (!req.headers || !req.headers.authorization) {
res.status(401).send("No authorization token found.");
return;
}
const parts = req.headers.authorization.split(" ");
if (parts.length != 2) {
res.status(401).send("Bad credential format.");
return;
}
const scheme = parts[0];
const credentials = parts[1];
if (!/^Bearer$/i.test(scheme)) {
res.status(401).send("Bad credential format.");
return;
}
verifyToken(credentials, function (err) {
if (err) {
res.status(401).send("Invalid token");
return;
}
fn(req, res);
});
};
}
I use jsonwebtoken
to verify the JWT token, and jwks-rsa
to retrieve the public key. I use Auth0, so jwks-rsa
reaches out to the list of public keys to retrieve them.
The checkAuth
function can then be used to safeguard the cloud function as:
exports.get = checkAuth(function (req, res) {
// do things safely here
});
You can see this change at my GitHub repository.
The JWT/access token can be retrieved in a number of ways. For Auth0, the API documentation can be found here.
Once this is in place, you can trigger the cloud function (if you have yours enabled with http trigger) like this:
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer access-token" \
-d '{"foo": "bar"}' \
"https://<cloud-function-endpoint>.cloudfunctions.net/get"