Example: JSON Web Tokens with Vanilla JavaScript

In this post we’re going to learn how to use JSON web tokens on the frontend with vanilla JavaScript and no libraries necessary. What you learn will be easily applicable to frameworks such as Angular, Angular2, Vue.js or similar.

In the last post we had a look at how to create an express app with jwt authentication.

Why No Framework?

I wanted to write a post simply illustrating how everything works and how easily this can be achieved without any frameworks in place. It’s just another layer of abstraction you have to learn if you’re just trying to build some sort of login for your web app.

Changes to the Backend

In order to serve an HTML page in the browser, I have changed the backend code slightly:


app.get("/", function(req, res) {
  res.sendFile(process.cwd() + '/public/index.html');

Also I of course have created the directory public and the files inside: index.html and jwt-vanilla.js.

The HTML part

We’re just going to serve a very basic and unstyled page for our educational purposes:

<!DOCTYPE html>
<html lang="en">
  <meta charset="UTF-8">
  <title>JSON web token with vanilla js</title>
  <div class="input">
    <label for="username">user name:</label>
    <input id="username">
    <label for="password">password:</label>
    <input id="password">
    <button onclick="getToken()">login</button>
  <div id="token"></div>
  <button onclick="getSecret()">get secret message</button>
  <div id="result"></div>
  <script src="jwt-vanilla.js"></script>

Notice that we have two buttons that will each run a different function of the included JavaScript file, getToken and getSecret.

The vanilla JavaScript JWT part

In order to get our token, we create a POST request with the username and password that is accessible to our backend. Remember we set it to a static array in the last post and we have a user that’s called test with the password test.

// make the request to the login endpoint
function getToken() {
  var loginUrl = "http://localhost:3000/login"
  var xhr = new XMLHttpRequest();
  var userElement = document.getElementById('username');
  var passwordElement = document.getElementById('password');
  var tokenElement = document.getElementById('token');
  var user = userElement.value;
  var password = passwordElement.value;

  xhr.open('POST', loginUrl, true);
  xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
  xhr.addEventListener('load', function() {
    var responseObject = JSON.parse(this.response);
    if (responseObject.token) {
      tokenElement.innerHTML = responseObject.token;
    } else {
      tokenElement.innerHTML = "No token received";

  var sendObject = JSON.stringify({name: user, password: password});

  console.log('going to send', sendObject);


The function will be called when the user clicks the respective button, get user name and password from the input fields and if they are valid credentials, we’ll display the token on the HTML page. Notice that we’re setting the content type to application/json and that we’re using JSON.parse to read the response and log it to the console. Typically you would now save the token in localStorage or another convenient place for future requests.

The next function we write is the one to get access to the data that should be kept private by the API and only communicated to logged in users, those who have a token:

// make the request to the secret API endpoint
function getSecret() {

  var url = "http://localhost:3000/secret"
  var xhr = new XMLHttpRequest();
  var tokenElement = document.getElementById('token');
  var resultElement = document.getElementById('result');
  xhr.open('GET', url, true);
  xhr.setRequestHeader("Authorization", "JWT " + tokenElement.innerHTML);
  xhr.addEventListener('load', function() {
    var responseObject = JSON.parse(this.response);
    resultElement.innerHTML = this.responseText;


This request is a GET request, like in our previous Postman example, in order to set the Authorization header for the xhr request, we use .setRequestHeader and set the value to JWT and append the token value we’ve stored in the #token element on the page.

Notice that for this request, we’re sending null, because GET requests don’t have a body of data to be transmitted, but simply go to a URL.

If everything went well, you should see something like the following in your browser:


To save the token in your browser you can simply use:

localStorage.setItem('token', token);

and later access it with:


If you liked this post, feel free to subscribe on feedly, follow on twitter or check out some of my other posts. If you think I could have explained or done something better or more beginner friendly, please let me know in the comments!

Thank you for reading! If you have any comments, additions or questions, please leave them in the form below! You can also tweet them at me

If you want to read more like this, follow me on feedly or other rss readers

14 thoughts on “Example: JSON Web Tokens with Vanilla JavaScript”

  1. Hello Jonathan, I tried to save the token in the local storage by doing the following in the POST request:
    if (responseObject.token) {
    //tokenElement.innerHTML = responseObject.token;
    window.localStorage.setItem(‘token’, token);
    } else {
    tokenElement.innerHTML = “No token received”;
    And then in the GET request, I put:
    xhr.open(‘GET’, url, true);
    xhr.setRequestHeader(“Authorization”, “JWT ” + window.localStorage.getItem(‘token’));

    But this does not work for some reason.. Could you please tell me what could be going wrong with this?
    The console log shows the following error:

    VM49:1 Uncaught SyntaxError: Unexpected token U in JSON at position 0
    at JSON.parse ()
    at XMLHttpRequest. (jwt-vanilla.js:41)

    Thank you in advance,

    1. Make sure to JSON.stringify the response, since you can’t save complex structures to localStorage

  2. This post and the one before are by far the best ones I have found to explain JWT and authentication. Thank you!

      1. An “anti tutorial list”… that’s crazy. In the week since I’ve read this, I’ve come up with a question that I cannot find the answer to and hope you can help. If I understand JWTs correctly, the token allows access to a protected endpoint when it is sent in an HTTP request header. When I access the page at “/some-protected-page” but then refresh it, I get “unauthorized” because the token is not sent in such a case. What options do we have to get around this?

        1. That’s kind of about the architecture of your app, you should not expose API endpoints via URL, but when a path is hit, you bootstrap your frontend app and that one gets the token from localstorage or a cookie and makes the request, does that make sense?

  3. Hi,
    this is a nice course.
    Can you give another course about how to decode jwt that have been saved in local storage and dsiplaying into our page.
    Thanks before

  4. hello there! i was looking around the internet for hours but all i faced was react, react …. 🙂
    thanks for going simple and clean with no framework. i really appreciate it.
    thanks again.

  5. thanks man!
    after learning about code and syntax tutorials, now im looking for patterns and how to substitute Vue.js with vanilla js…. this has been eye opening… I have coded my own login using your example and it works… localstorage etc… looking to move forward learning more, thanks!

  6. This must be the single most helpful writeup on JWT on the planet. After plowing through dozens of cryptic tutorials finally some good content. Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *