Welcome to yet another Deno article. As I’ve mentioned before due to lack of enough documentation in Deno, for the time being, I focus mostly on Deno related content. For this article, I cover another interesting topic related to REST APIs and that’s JWT. We are going to generate and validate JWT in Deno.
Unfortunately, the library situation in the JWT department is not much better than the MySQL driver. There are not many projects that exist and most of them are still work-in-progress. For JWT as of now (3rd June 2020), only two JWT libraries are available which are:
- jwt [GitHub repository deleted]
- djwt
jwt
library is very immature and it’s more of a POC, so we can’t do much with it. On the other hand, djwt
is pretty much ready to use.
JWT implementation in Deno
Keep in mind that djwt
does not handle authentication and authorization. It is just a JWT library that generates and validates a token. Hence, don’t expect to simply provide a username and password to this library. And expect it to handle everything else including generating and validating a JWT.
Because of that making, a practical example out of it is very difficult. Unless we implement the other parts of the flow by ourselves. Well, that’s not the goal of this article. In this article, we exclusively focus on just generating and validating JWT and nothing else.
The fully working example will be covered in upcoming articles.
So to get started, let’s create an index.js
file and import djwt
library.
import { validateJwt } from "https://deno.land/x/djwt/validate.ts";
import { makeJwt, setExpiration } from "https://deno.land/x/djwt/create.ts";
Then we need to configure three things which are:
key
– A secret that’s used as a salt to generate JWTpayload
– The payload that’s sent to a userheader
– HTTP header of the response
The best is to externalize these configurations and read them from environment variables. If you don’t know have a look at the How to read environment variables in Deno article.
Then all we left to do is to add two functions to generate
and validate
the token.
import { validateJwt } from "https://deno.land/x/djwt/validate.ts";
import { makeJwt, setExpiration } from "https://deno.land/x/djwt/create.ts";
const expirationMinute = 10;
const key = "dummy_key"
const getTokenExpirationAsMilliseconds = () => {
return new Date().getTime() + expirationMinute * 60 * 1000;
}
const payload = {
iss: "dummy_issuer",
exp: setExpiration(getTokenExpirationAsMilliseconds()),
}
const header = {
alg: "HS256",
typ: "JWT",
}
const generateToken = () => {
return makeJwt({ key, header, payload })
}
const validateToken = (token) => {
return validateJwt(token, key, { isThrowing: false });
}
To actually test it, let’s create two (relatively dummy) endpoints for it. We use Oak to create endpoints as follow,
import { validateJwt } from "https://deno.land/x/djwt/validate.ts";
import { makeJwt, setExpiration } from "https://deno.land/x/djwt/create.ts";
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const expirationMinute = 10;
const key = "dummy_key"
const getTokenExpirationAsMilliseconds = () => {
return new Date().getTime() + expirationMinute * 60 * 1000;
}
const payload = {
iss: "dummy_issuer",
exp: setExpiration(getTokenExpirationAsMilliseconds()),
}
const header = {
alg: "HS256",
typ: "JWT",
}
const generateToken = () => {
return makeJwt({ key, header, payload })
}
const validateToken = (token) => {
return validateJwt(token, key, { isThrowing: false });
}
const router = new Router();
const app = new Application();
router
.get("/generate", (context) => {
context.response.body = { token: generateToken() };
})
.post("/validate", async (context) => {
const { token } = (await context.request.body(true)).value;
context.response.body = await validateToken(token) ? { isValid: true } : { isValid: false };
});
app.use(router.routes());
app.use(router.allowedMethods());
await app.listen({ port: 8080 });
Now it’s time to run the code,
$ deno run --allow-read --allow-net index.js
Open the browser and hit the localhost:8080/generate
. Or run the below curl command:
$ curl http://localhost:8080/generate
It should return a payload like this:
{ "token": "xyz" }
And to validate the token send a POST
request to localhost:8080/validate
like this,
$ curl -d '{"token": "xyz"}' -H 'Content-Type: application/json' http://localhost:8080/validate
The endpoint returns something similar to this,
{ "isValid": true }
Inline/featured images credits
- Lock and keys (background) by MasterTux on Pixabay
- Deno logo by Kevin (Kun) “Kassimo” Qian on Deno GitHub