Custom Authentication (JWT)
Customizing your JWT settings to integrate an existing user base.
Introduction
JSON Web Tokens (JWTs) are a compact and self-contained way for securely transmitting information between parties as a JSON object. Within Particle Network, JWT custom authentication allows you to integrate Particle Auth with your existing user base and authentication methods. By leveraging JWTs, you can seamlessly enable users to log in using their current accounts while maintaining the security and efficiency of the authentication process.
Particle Network’s Dashboard allows developers to configure custom JWT settings to seamlessly integrate their existing user base or authentication methods, such as a custom OAuth provider.
In this tutorial, you will learn how to:
- Build a basic server to handle JWT operations, including:
- Serving public keys in JWK format
- Generate a sample JWT with a static payload.
- Verifying a username against a predetermined value and generate a JWT if the username is valid.
- Decode and verify a JWT.
- Integrate JWT authentication in your dApp using Particle Auth.
What are JSON Web Tokens?
JWTs are compact, URL-safe means of representing claims between two parties. Think of them as digital passports for your users, containing encrypted information about their identity and permissions. These tokens are self-contained, making them ideal for stateless authentication in web applications.
Structure of a JWT
A JSON Web Token (JWT) comprises three main parts: a header, a payload, and a signature. These segments are Base64Url-encoded and concatenated with periods (.) to form the complete JWT.
Header
The header is a JSON object that usually contains two fields: a token type (commonly JWT) and a signing algorithm (e.g., RS256 for RSA SHA-256). As such, it provides details about how the JWT is encoded and secured.
Example of a header:
Payload
The payload is a JSON object containing claims and information about the user and other relevant data. Claims are key-value pairs and can be registered, public, or private. Registered claims are predefined by the JWT specification (e.g., iss for issuer and **exp **for expiration time), while the developer can define public and private claims.
Common keys within JWT claims include:
- iss (Issuer) — identifies the entity that issued the JWT. For instance, particle-network.
- sub (Subject) — identifies the user the token is for by storing the user’s unique identifier.
- aud (Audience) — specifies the recipients allowed to process the token.
- exp (Expiration Time) — defines when the token expires, in seconds since the Unix epoch.
- nbf (Not Before) — defines the earliest time the token can be considered valid, in seconds since the Unix epoch.
- iat (Issued At) — indicates when the token was issued in seconds since the Unix epoch.
Example of a payload:
Signature
The signature is a cryptographic hash created using the encoded header, payload, and a secret key. It ensures the token’s integrity and authenticity.
The encoded header and payload are concatenated with a period (.) and then hashed with the secret key, using a specified algorithm to generate the signature.
Example of signature creation with RSA SHA-256:
This approach ensures that the JWT has not been tampered with and can be trusted as authentic.
The final JWT token is a combination of the encoded header, payload, and signature, separated by periods (.), as shown below:
Example of a real JWT:
Custom Authentication via JWT
This guide will demonstrate how to integrate JWT authentication with Particle Auth, allowing you to seamlessly incorporate your existing user base or custom authentication system into your dApp.
In the following repository, you will find two directories: one containing code for a JWT server, and the other containing a frontend project built with Next.js.
General JWT Authentication Flow
To understand how JWTs are typically used for authentication, let’s consider the following flow:
- User Information Storage: You have a database that holds a user’s information, including a unique user ID, username, password for authentication, and other data relevant to your application.
- User Login: When the user logs in from the front end using their username and password, the front end sends these credentials to the server for verification.
- JWT Generation: If the user’s credentials are correct, the server generates a JWT that includes their unique ID and possibly other claims.
- JWT Storage: The JWT is sent back to the front end, where it is stored (typically in local storage or cookies) and used for subsequent authenticated requests.
- JWT Validation: For each request from the front end, the server validates the JWT to ensure it is still valid and has not been tampered with. Particle Auth can validate the JWT by accessing the server’s endpoint serving the public key.
- Public Key Endpoint: If using asymmetric keys (RSA), the server provides an endpoint for retrieving the public key to verify the JWT’s signature.
Demo Project’s Flow
To keep things simpler here, our demo project follows a basic flow:
- User Information Storage: In this example, a single user is created within the JWT server to simulate a database entry. Only a username is needed for authentication.
- User Login: When a user logs in from the front end using their username, the front end sends a request to the server to verify the user’s identity.
- JWT Generation: If the username matches the “database,” the server takes their unique ID and uses it to generate and issue a new valid JWT.
- JWT Validation: The front end receives the JWT from the server, and Particle Auth validates it by accessing the server’s endpoint that serves public keys.
- JWT Decoding: As a bonus, the front end calls the server again to decode the JWT and extract information to display to the user.
The following section will review how the server handles JWTs operations and how to set it up.
The JWT Server
The JWT server implementation in the jwt-server
directory is built using Node.js and the Express framework. It manages key generation, JWT issuance, and verification, serving as an example of a server that handles user authentication in a dApp.
Code Breakdown
Dependencies and Setup
- Dependencies: The server uses Express for handling HTTP requests,
cors
for enabling Cross-Origin Resource Sharing, andjose
for JWT handling and key management. - App Setup: Sets up the Express app, defines constants for key paths and a predetermined user, and enables CORS.
Key Initialization
- Key Initialization: When the server starts, it checks for existing keys on the filesystem. If keys are found, they are loaded and converted to the necessary formats. If not, new keys are generated, saved, and loaded.
Starting the Server and Setting Up Routes
- startServer: Initializes the keys, sets up the necessary middleware, and starts the Express server.
- /token: Generates and returns a JWT with a static payload; this can be used to test the process.
- /.well-known/jwks.json: Provides the public key in JWKS format for verification.
- /login: Validates the username and issues a JWT if the username is correct.
- /decode: Decodes and verifies a JWT provided by the client.
Run the server
Now that you have a good understanding of how the server works, let’s get it up and running.
- Clone the repository:
- Move into the
jwt-server
directory:
- Install server’s dependencies
- Run the server
The server is now running on http://localhost:4000
. It needs to be accessible from the Internet since Particle Auth will need to call the /.well-known/jwks.json
endpoint to validate the JWT. Make sure to deploy this server on a platform like Digital Ocean or use Ngrok to expose the server when running locally.
Integrating JWT Auth with Particle Auth
With the server set up, you can integrate it with Particle Auth. You can find the full implementation in Next.js within the particle-auth-frontend directory. Here, we’ll cover the main steps to handle the JWT flow.
Setting up a Dashboard
- The first step is configuring JWT custom authentication in the Particle Dashboard. Create a new project and application, then navigate to the Custom section on the side menu.
Click on the JSON Web Token button and add the necessary configuration.
- JWKS URI: This is the endpoint in your server serving the public keys, in this case,
/.well-known/jwks.json
. Ensure your server is exposed to the Internet. - Unique ID Key: This key identifies the user. Set it to
sub
, which represents the unique user ID. - Validation Rules: These are optional. Here, it’s configured it to include the JWT issuer to ensure the JWT comes from the correct source.
- JWT to Verify (validation test): Add a valid JWT to validate and verify that everything is working correctly.
Configure Particle Auth
Now, you can move into the particle-auth-frontend
directory to work on the front end.
Before getting started, retrieve the API keys generated during the creation of your project and app and place them in a .env
file within the particle-auth-frontend
directory file using the following keys:
To configure Particle Auth for JWT, use the AuthCoreContextProvider
component in src/components/Authkit.tsx
.This component initializes Particle Auth.
To handle the login request and extract data from the JWT, create two support functions in src/app/utils/jwtUtils.ts
.
Integrating JWT Handling within your dApp’s UI
After the above, you can integrate integrate the login and JWT handling functionality with your dApp’s UI. These are contained in page.tsx
, which includes an input field for the username and a login button to trigger login logic.
The login workflow is as follows:
- A user enters their username and clicks the login button.
- The
handleLogin
function sends a login request to the server. - If their username is valid, the server returns a JWT.
- The JWT is used to connect with Particle Auth.
- The JWT is decoded to extract user information, which is then displayed in the UI.
Running the full application
Now, you can run and test your application. Make sure your server is running and configured in the Particle Dashboard, then follow the instructions below to run the front end :
After cloning the repository, move into the front end directory:
Install dependencies:
Run the front end:
Using Production-Ready Services for JWT Authentication
While this tutorial provides a foundational understanding of JWT authentication with a custom server, it’s recommended that robust authentication services be used for production environments. Services like Auth0, Firebase Authentication, and AWS Cognito are good options to consider.
Auth0
Auth0 is a flexible, drop-in solution to add authentication and authorization services to your applications. With Auth0, you can quickly set up a secure JWT authentication system.
Firebase Authentication
Firebase Authentication provides backend services to help authenticate users in your app. It supports various authentication methods, including email/password and social logins.
AWS Cognito
AWS Cognito provides user sign-up, sign-in, and access control, allowing you to add user authentication to your web and mobile apps easily.
Conclusion
By following this tutorial, you’ve learned how to integrate JSON Web Tokens (JWTs) effectively into your dApp using Particle Auth. JWTs provide a secure, stateless way to handle authentication, making them ideal for modern web applications.
You now also have a robust server that can generate, verify, and decode JWTs and a front end that can authenticate users with these tokens. This setup ensures that your authentication process is secure and scalable, allowing for seamless integration with your existing user base.
With Particle Auth, you can now leverage JWTs to enhance your dApp’s security and user experience, providing a flexible and efficient authentication solution.
Was this page helpful?