Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Implementing JWT Authentication

This tutorial will guide you through implementing a complete JWT (JSON Web Token) authentication system using Kinesis API. You'll create login functionality that generates tokens and a verification endpoint that validates those tokens, establishing a secure authentication flow for your APIs.

Prefer video tutorials? You can follow along with our YouTube walkthrough of this same project.

Prerequisites

Before you begin, you need:

  1. Access to a Kinesis API instance:

  2. A user account with ADMIN or ROOT privileges

  3. Basic understanding of:

    • REST APIs and HTTP methods
    • Authentication concepts
    • JSON Web Tokens (JWT)

What is JWT Authentication?

JWT (JSON Web Token) is an open standard for securely transmitting information between parties. In the context of authentication:

  1. A user logs in with their credentials
  2. The server validates the credentials and generates a signed JWT
  3. The client stores this JWT and sends it with subsequent requests
  4. The server verifies the JWT's signature to authenticate the user

This stateless approach eliminates the need for server-side session storage, making it ideal for APIs.

1. Creating the Authentication Project

First, let's create a project to organize our authentication API:

  1. Log in to your Kinesis API instance
  2. Navigate to the Projects page from the main menu
  3. Click "Create New" to open the project creation modal
  4. Fill in the following details:
    • Name: "Authentication"
    • ID: "auth"
    • Description: "Simple project to test JWT authentication." (or anything else you want)
    • API Path: "/auth" (this will be the base URL path for all routes in this project) Create Project
  5. Click "Create" to save your project

2. Creating the Accounts Collection

Next, let's create a collection to store user accounts:

  1. From your newly created project page, click "Create New" on the "Collections" section
  2. Fill in the following details:
    • Name: "Accounts"
    • ID: "accounts"
    • Description: "To store user accounts." (or anything else you want) Create Collection
  3. Click "Create" to save your collection

Project Page

3. Creating Structures

Now we'll create structures (fields) to store user information:

UID Structure

  1. From the Accounts collection page, locate the "Structures" section
  2. Click "Create New" to add a structure
  3. Fill in the following details:
    • Name: "uid"
    • ID: "uid"
    • Description: "" (leave blank or insert anything else)
    • Type: "INTEGER"
    • Min: "0"
    • Max: "1000"
    • Default Value: "0"
    • Required: Check this box
    • Unique: Check this box Create UID Structure
  4. Click "Create" to save the structure

Username Structure

  1. Click "Create New" again to add another structure
  2. Fill in the following details:
    • Name: "username"
    • ID: "username"
    • Description: "" (leave blank or insert anything else)
    • Type: "TEXT"
    • Min: "4"
    • Max: "100"
    • Required: Check this box
    • Unique: Check this box Create Username Structure
  3. Click "Create" to save the structure

Password Structure

  1. Click "Create New" again to add the final structure
  2. Fill in the following details:
    • Name: "password"
    • ID: "password"
    • Description: "" (leave blank or insert anything else)
    • Type: "PASSWORD"
    • Min: "8"
    • Max: "100"
    • Required: Check this box Create Password Structure
  3. Click "Create" to save the structure

Collection Page

4. Creating a Test User Account

Let's create a test user to demonstrate our authentication system:

  1. Navigate to the "Data" section in the top navigation bar
  2. Select your "Authentication" project and then the "Accounts" collection
  3. Click "Create New" to create a data object
  4. Add a nickname (optional)
  5. Fill in the fields:
    • uid: "0" (this will be our unique identifier)
    • username: "john_doe"
    • password: "password123" (in a real system, you'd use a strong password) Create Data
  6. Click "Create" to save your data object

Data Page

5. Creating the Login Route

Now we'll create a route that validates credentials and generates a JWT token:

  1. Navigate to "Routes" in the top navigation bar
  2. Select your "Authentication" project
  3. Click "Create New" to create a route
  4. Fill in the route details:
    • Route ID: "LOGIN"
    • Route Path: "/login"
    • HTTP Method: "POST"
  5. Add 2 parameters to the "Body" section:
    • username: "STRING"
    • password: "STRING"
  6. The "JWT Authentication" and "URL Parameters" sections don't need to be modified

Create Route

Building the Login Route Logic

In the Flow Editor, we'll create a flow that:

  1. Accepts username and password from the request body
  2. Validates these against our stored accounts
  3. Generates a JWT token if credentials are valid
  4. Returns an error if credentials are invalid

Follow these steps:

  1. Add a FETCH block:

    • Drag a FETCH block onto the canvas and connect the START node to it
    • Fill in the following details:
      • Local Name: "_accounts"
      • Reference Collection: "accounts"

    Fetch Block

  2. Add a FILTER block:

    • Drag a FILTER block onto the canvas and connect the FETCH block to it
    • Fill in the following details:
      • Local Name: "_matchingAccounts"
      • Reference Variable: "_accounts"
      • Reference Property: "username"
    • Add a "filter" submodule and fill in the following details:
      • Operation Type: "Equal To"
      • Operand:
        • Reference: Check this box
        • Type: "String"
        • Data: "username"

    Filter Block

  3. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the FILTER block to it
    • Fill in the following details:
      • Local Name: "_matchingAccountsLength"
      • Property Apply: "LENGTH"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Array"
      • Data: "_matchingAccounts"

    Property Block

  4. Add a CONDITION block:

    • Drag a CONDITION block onto the canvas and connect the PROPERTY block to it
    • Fill in the following details:
      • Action: "Fail"
      • Fail Object Status: "404"
      • Fail Object Message: "User not found"
    • Add a "condition" submodule with 2 operands, and fill in the following details:
      • First Operand:
        • Reference: Check this box
        • Type: "Integer"
        • Data: "_matchingAccountsLength"
      • Second Operand:
        • Reference: Leave unchecked
        • Type: "Integer"
        • Data: "1"
      • Condition Type: "Less than"

    Condition Block

  5. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the CONDITION block to it
    • Fill in the following details:
      • Local Name: "_foundAccount"
      • Property Apply: "GET_FIRST"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Array"
      • Data: "_matchingAccounts"

    Property Block

  6. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the previous PROPERTY block to it
    • Fill in the following details:
      • Local Name: "_savedPassword"
      • Property Apply: "GET_PROPERTY"
      • Additional: "password"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Other"
      • Data: "_foundAccount"

    Property Block

  7. Add a CONDITION block:

    • Drag a CONDITION block onto the canvas and connect the PROPERTY block to it
    • Fill in the following details:
      • Action: "Fail"
      • Fail Object Status: "401"
      • Fail Object Message: "Invalid Password"
    • Add a "condition" submodule with 2 operands, and fill in the following details:
      • First Operand:
        • Reference: Check this box
        • Type: "String"
        • Data: "password"
      • Second Operand:
        • Reference: Check this box
        • Type: "String"
        • Data: "_savedPassword"
      • Condition Type: "Not equal to"

    Condition Block

  8. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the CONDITION block to it
    • Fill in the following details:
      • Local Name: "_uid"
      • Property Apply: "GET_PROPERTY"
      • Additional: "uid"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Other"
      • Data: "_foundAccount"

    Property Block

  9. Add a FUNCTION block:

    • Drag a FUNCTION block onto the canvas and connect the PROPERTY block to it
    • Fill in the following details:
      • Local Name: "_jwt"
      • Function: "GENERATE_JWT_TOKEN"
    • Add a "parameter" submodule and fill in the following details:
      • Reference: Check this box
      • Type: "Integer"
      • Data: "_uid"

    Function Block

  10. Add a RETURN block:

    • Drag a RETURN block onto the canvas and connect the FUNCTION block to it
    • Add an "object pair" submodule
    • Fill in the following details:
      • id: "uid"
      • data:
        • Reference: Check this box
        • Type: "Integer"
        • Data: "_uid"
    • Add another "object pair" submodule
    • Fill in the following details:
      • id: "jwt"
      • data:
        • Reference: Check this box
        • Type: "String"
        • Data: "_jwt"

    Return Block

  11. Ensure that your Flow Editor looks like the following: Flow Editor

  12. Click "Create" to save your route

Route Page

6. Creating the Verify Route

Now let's create a route that verifies JWT tokens:

  1. Navigate back to "Routes" in the top navigation bar
  2. Select your "Authentication" project
  3. Click "Create New" to create a route
  4. Fill in the route details:
    • Route ID: "VERIFY"
    • Route Path: "/verify"
    • HTTP Method: "GET"
  5. Fill in the details for the "JWT Authentication" section:
    • Active: Check this box
    • Field: "uid"
    • Reference Collection: "accounts"
  6. Set the "delimiter" to be "&" for the "URL Parameters" section
  7. Add 1 parameter to the "URL Parameters" section:
    • uid: "INTEGER"
  8. The "Body" section doesn't need to be modified

Create Route

Building the Verification Route Logic

In the Flow Editor, we'll create a flow that:

  1. Extracts the JWT token from the Authorization header
  2. Verifies the token's signature and expiration
  3. Returns the decoded payload if valid
  4. Returns an error if invalid

Follow these steps:

  1. Add a FETCH block:

    • Drag a FETCH block onto the canvas and connect the START node to it
    • Fill in the following details:
      • Local Name: "_accounts"
      • Reference Collection: "accounts"

    Fetch Block

  2. Add a FILTER block:

    • Drag a FILTER block onto the canvas and connect the FETCH block to it
    • Fill in the following details:
      • Local Name: "_matchingAccounts"
      • Reference Variable: "_accounts"
      • Reference Property: "uid"
    • Add a "filter" submodule and fill in the following details:
      • Operation Type: "Equal To"
      • Operand:
        • Reference: Check this box
        • Type: "Integer"
        • Data: "uid"

    Filter Block

  3. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the FILTER block to it
    • Fill in the following details:
      • Local Name: "_foundAccount"
      • Property Apply: "GET_FIRST"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Array"
      • Data: "_matchingAccounts"

    Property Block

  4. Add a PROPERTY block:

    • Drag a PROPERTY block onto the canvas and connect the previous PROPERTY block to it
    • Fill in the following details:
      • Local Name: "_username"
      • Property Apply: "GET_PROPERTY"
      • Additional: "username"
    • As for the data section, fill in the following details:
      • Reference: Check this box
      • Type: "Other"
      • Data: "_foundAccount"

    Property Block

  5. Add a RETURN block:

    • Drag a RETURN block onto the canvas and connect the PROPERTY block to it
    • Add an "object pair" submodule
    • Fill in the following details:
      • id: "message"
      • data:
        • Reference: Leave unchecked
        • Type: "String"
        • Data: "Authentication Succeeded!"
    • Add another "object pair" submodule
    • Fill in the following details:
      • id: "username"
      • data:
        • Reference: Check this box
        • Type: "String"
        • Data: "_username"

    Return Block

  6. Ensure that your Flow Editor looks like the following: Flow Editor

  7. Click "Create" to save your route

Route Page

7. Testing the Authentication System

Now let's test our JWT authentication system using the Playground:

Testing the Login Route

  1. Navigate to "Playground" in the top navigation bar
  2. Select your "Authentication" project Playground Page
  3. Click on the "LOGIN" route Playground Project Page
  4. Set the request body to:
    {
      "username": "john_doe",
      "password": "password123"
    }
    
  5. Click "Send" to make a request to your API
  6. You should see a response like:
    {
      "uid": 0,
      "jwt": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9..."
    }
    
  7. Copy the generated JWT token and memorize the value of the uid

Playground Request Page

Testing Edge Cases

Let's test some edge cases to ensure our authentication system is robust:

  1. Invalid Username

    • Try the login route with an invalid username:
      {
        "username": "wronguser",
        "password": "password123"
      }
      
    • You should receive a 404 error response:
      {
        "message": "User not found",
        "status": 404
      }
      
  2. Invalid Password

    • Try the login route with an incorrect password:
      {
        "username": "john_doe",
        "password": "wrongpassword"
      }
      
    • You should receive a 401 error response:
      {
        "message": "Invalid Password",
        "status": 401
      }
      

Testing the Verify Route

  1. Navigate to "Playground" in the top navigation bar
  2. Select your "Authentication" project Playground Page
  3. Click on the "VERIFY" route Playground Project Page
  4. Paste the JWT token that you copied from the previous section in the "Authorization" field
  5. Enter the value "0" for the "uid" field in the "URL Parameters" section
  6. Click "Send" to make a request to your API
  7. You should see a response like:
    {
      "message": "Authentication Succeeded!",
      "username": "john_doe"
    }
    

Playground Request Page

Testing Edge Cases

Let's test some edge cases to ensure our authentication system is robust:

  1. No Authorization Header / Invalid Token

    • Try the verify route without an Authorization header or by setting it to a random value
    • You should receive a 500 error response:
      {
        "message": "Error: Failed decoding JWT (InvalidToken)",
        "status": 500
      }
      
  2. Wrong UID

    • Try the verify route with a different value for the "uid" field
    • You should receive a 403 error response:
      {
        "message": "Error: Incorrect uid",
        "status": 403
      }
      

Congratulations!

You've successfully implemented a complete JWT authentication system using Kinesis API! Here's what you've accomplished:

  • Created a project and collection to store user accounts
  • Set up the necessary data structures for authentication
  • Built a login route that validates credentials and generates JWT tokens
  • Created a verification route that validates tokens
  • Tested both successful authentication flows and edge cases

Next Steps

To build on this authentication system, you could:

  1. Add User Registration: Create a route that allows new users to register
  2. Add Role-Based Access Control: Extend the JWT payload to include user roles for authorization
  3. Create Protected Routes: Build additional routes that require valid authentication
  4. Add Refresh Tokens: Implement a token refresh mechanism for longer sessions

Continuous Improvement

Note: Kinesis API is continuously evolving based on user feedback. As users test and provide suggestions, the platform will become simpler, more intuitive, and easier to use. This tutorial will be updated regularly to reflect improvements in the user experience and new features. A dedicated "AUTH" block is planned for the future to dramatically simplify the process of adding authentication to your APIs.

We value your feedback! If you have suggestions for improving this tutorial or the Kinesis API platform, please reach out through our contact page.