API Authentication with Auth0
If you need to authenticate machine-to-machine API calls you can roll your own or use an identity provider like Auth0.
If you need to authenticate machine-to-machine API calls you can roll your own or use an identity provider like Auth0.
This is an example of how to do that using Nodejs, Express, and cacheing the token using Redis.
Client Nodejs Application
First, on your client Nodejs project, create a directory called "auth" in the root of your project and cut and paste this code.
// Auth0 JWT Middleware to validate tokens
const { expressjwt: jwt } = require("express-jwt");
const jwks = require("jwks-rsa");
// Sets options and verfies JWT
const checkJwt = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
}),
audience: process.env.AUTH0_AUDIENCE,
issuer: `https://${process.env.AUTH0_DOMAIN}/`,
algorithms: ["RS256"],
});
module.exports = { checkJwt };
Next, create a "lib" folder in the root of you client Nodejs project and in that folder create a file called "redis.js" with the following content.
require("dotenv").config();
const express = require("express");
const app = express();
const fs = require("fs");
let redis = null;
module.exports = {
connect: () => {
let redisHost = process.env.redisHost ? process.env.redisHost : "127.0.0.1";
let redisPort = process.env.redisPort ? process.env.redisPort : 6379;
let redisOptions = {
host: redisHost,
port: redisPort,
};
redis = require("async-redis").createClient(redisOptions);
redis.on("connect", function (err) {
if (!err) {
console.log("Redis Connected");
console.log(redisHost);
console.log(redisPort);
}
});
redis.on("error", function (err) {
console.log("Error " + err);
});
return redis;
},
redisClient: () => redis,
};
Now you'll go to your Auth0 account, navigate to "Applications" > "APIs" and create a new "API".
Now, in the root of your client Nodejs project, create a .env file if one doesn't exist and add these varaibles and populate them with the values from the API you just created in Auth0. The easiest way to find the values is to click on the "Test" tab for you API and then select Nodejs and look at what the variables are.
REDIS_KEY=''
AUTH0_CLIENT_ID=''
AUTH0_SECRET=''
AUTH0_AUDIENCE=''
Next, create a file nameed "index.js" in the root of your project and paste the following code.
require("dotenv").config();
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const axios = require("axios");
const redis = require("./lib/redis").connect();
const auth0_service = require("./auth/auth0_service");
const PORT = process.env.PORT || 3000;
// auth0_service middleware returns Bearer token in res.apiBearer
app.get("/", auth0_service, async (req, res) => {
try {
const response = await axios.get("http://localhost:3008/sample_route", {
method: "GET",
headers: {
Authorization: `${res.apiBearer}`,
"Content-Type": "application/json",
},
});
const json = await response.data;
res.status(200).send(json);
} catch (err) {
console.log(err);
res.status(err.response.status).send(err.response.statusText);
}
});
redis.on("connect", function (error) {
if (error) {
console.log("Redis connection error:", error);
return false;
}
app.listen(PORT, () => {
console.log(`Listening @ http://localhost:${PORT}`);
});
});
Resource Nodejs Application
In you resource Nodejs application, or api, create a folder called "auth" and inside that folder create a file called auth0.js with the following code.
// Auth0 JWT Middleware to validate tokens
const { expressjwt: jwt } = require("express-jwt");
const jwks = require("jwks-rsa");
// Sets options and verfies JWT
const checkJwt = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json`,
}),
audience: process.env.AUTH0_AUDIENCE,
issuer: `https://${process.env.AUTH0_DOMAIN}/`,
algorithms: ["RS256"],
});
module.exports = { checkJwt };
Now create a file called index.js in the root of you resource/api application and add this code.
require("dotenv").config();
const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const { checkJwt } = require("./auth/auth0");
const PORT = process.env.PORT || 3008;
app.use("*", checkJwt, (err, req, res, next) => {
if (err.name === "UnauthorizedError") {
console.error("UnauthorizedError", new Error(err));
res.status(401).send({ Status: "This endpoint is private" });
}
});
// checkJwt middleware autheticates bearer token
app.get("/sample_route", (req, res) => {
res.send("You are authenticated");
});
app.listen(PORT, () => {
console.log(`Listening @ http://localhost:${PORT}`);
});
Create a file called .env in the root of your project and add these variables populating them with the values you got from Auth0.
AUTH0_AUDIENCE=''
AUTH0_DOMAIN=''
You can find an example of this code on github below.