Exploring the process of retrieving token expiration in TypeScript using the 'jsonwebtoken' library

Currently utilizing jsonwebtoken for token decoding purposes and attempting to retrieve the expiration date. Encountering TypeScript errors related to the exp property, unsure of the solution:

import jwt from 'jsonwebtoken'

const tokenBase64 = 'ey...' /* some valid token */

const token = jwt.decode(tokenBase64)
const tokenExpirationDate = token.exp
//                                ^^^
// Property 'exp' does not exist on type 'string | object'. Property 'exp' does not exist on type 'string'.

Installed @types/jsonwebtoken, but unable to find a proper token type for casting token. Any suggestions?

Utilizing

  • @types/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9df7eef2f3eaf8ffe9f2f6f8f3ddaab3afb3ae">[email protected]</a>
  • <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="771d04181900121503181c1219374f59465947">[email protected]</a>

.tsconfig:

{
  "compilerOptions": {
    "allowJs": true,
    "baseUrl": ".",
    "jsx": "Preserve",
    "moduleResolution": "Node",
    "module": "ESNext",
    "sourceMap": true,
    "removeComments": true,
    "allowSyntheticDefaultImports": true,
    "target": "ESNext"
  }
}

Answer №1

Here is an example of how I am using decode with TypeScript

import jwt from 'jsonwebtoken';

export const isTokenExpired = (token: string): boolean => {
    try {
        const { exp } = jwt.decode(token) as {
            exp: number;
        };
        const expirationDatetimeInSeconds = exp * 1000;

        return Date.now() >= expirationDatetimeInSeconds;
    } catch {
        return true;
    }
};

Although not necessary, here is another piece of code for your reference

import 'jest';
import jwt from 'jsonwebtoken';

import { isTokenExpired } from 'path-to-isTokenExpired/isTokenExpired';

describe('isTokenExpired', () => {
    it('should return true if jwt token expired', () => {
        const currentTimeInSecondsMinusThirtySeconds = Math.floor(Date.now() / 1000) - 30;
        const expiredToken = jwt.sign({ foo: 'bar', exp: currentTimeInSecondsMinusThirtySeconds }, 'shhhhh');

        expect(isTokenExpired(expiredToken)).toEqual(true);
    });

    it('should return false if jwt token not expired', () => {
        const currentTimeInSecondsPlusThirtySeconds = Math.floor(Date.now() / 1000) + 30;
        const notExpiredToken = jwt.sign({ foo: 'bar', exp: currentTimeInSecondsPlusThirtySeconds }, 'shhhhh');

        expect(isTokenExpired(notExpiredToken)).toEqual(false);
    });

    it('should return true if jwt token invalid', () => {
        expect(isTokenExpired('invalidtoken')).toEqual(true);
    });
});

Answer №2

I discovered a method for importing users:

import { sign, verify } from 'jsonwebtoken';
sign('Hello', 'secret');

Personally, I believe using the require method is more efficient as it eliminates the need to import each individual function separately.

Answer №3

Encountered a similar error message while using the line import jwt from 'jsonwebtoken'. However, switching to

var jwt = require('jsonwebtoken');
[2] resolved the issue:

var jwt = require('jsonwebtoken');
var tokenBase64 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoiMTUxMTk1MDcwMyIsImFkbWluIjp0cnVlfQ.wFC-9ZsqA9QuvLkRSkQmVYpUmgH9R-j8M4D0GECuPHY';

const token = jwt.decode(tokenBase64);
const tokenExpirationDate = token.exp
console.log(tokenExpirationDate);

[2] reference: https://github.com/auth0/node-jsonwebtoken

Answer №4

When using jsonwebtoken version 8.3, the function jsonwebtoken.decode() now has specific type definitions:

export function decode(
    token: string,
    options?: DecodeOptions,
): null | { [key: string]: any } | string;

Given that Typescript may not always determine the correct type and the value of exp is unknown, a simple solution is to cast the result as any.

import jwt from 'jsonwebtoken'

const tokenBase64 = 'ey...' /* some valid token */

const token: any = jwt.decode(tokenBase64)
const tokenExpirationDate = token.exp

Answer №5

In my opinion, using

import * as jwt from 'jsonwebtoken';
should function properly.

Answer №6

import * as jwt from 'jsonwebtoken'

const { token } = request.headers
const secretCode = token.replace('Bearer ', '')
const decodedToken = jwt.verify(secretCode, 'APP_SECRET')
const userID = (decodedToken as any).userID

Feel free to specify the type of decodedToken based on how you are using the token instead of using any

Answer №7

When using jwt.verify and jwt.decode, the return type is typically 'string | object'.

If you have additional information regarding the return type that Typescript does not account for, you can specify it like this:

const token = jwt.decode(tokenBase64) as {exp: number}
const tokenExpirationDate = token.exp

You are free to include any other values in the object as needed.

While it can be assumed that 'exp' will be present, keep in mind that other keys may not be included in the decoded token. Verify that the token being decoded actually contains them or make them optional in your type definition: ({exp: number; random?: string})

Answer №8

After encountering the need for it, I created a helper function (implemented using a class-based approach - but can also function as a standalone method):

import { JwtPayload, verify } from "jsonwebtoken";

export class BaseController {
  // ...
  static decodeJWT = <T extends { [key: string]: any }>(token: string) => {
    return verify(token, process.env.JWT_ACCESS_TOKEN!) as JwtPayload & T; 
    // By applying this typing, we maintain both our encoded data and the original properties of the JWT
  };
}

This is how it's utilized in controllers:

import { BaseController } from "./BaseController";

export class UserController extends BaseController {
  static getUser = async (
    // ...
  ) => {
    // obtain token
    // It's best to check if username exists before usage
    const payload = this.decodeJWT<{ username?: string }>(token); 
    // No errors will arise here, allowing us to extract all specified properties along with the original JWT properties
    const { username, exp } = payload;
    // perform actions...
  };
}

Answer №9

If you want to achieve this, follow these steps:

import jwt, { JwtPayload } from 'jsonwebtoken'

const tokenBase64 = 'ey...' /* valid token here */

const decodedToken = jwt.decode(tokenBase64) as JwtPayload
const expirationDate = decodedToken.exp
//                                ^^^
// decodedToken is now recognized as a JwtPayload object, allowing access to its attributes like 'exp'.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize apexcharts to apply custom colors for negative data points

I am currently utilizing apex charts within a react application, and I have a requirement to display markers with different colors if the y value is a negative number. Below is the logic that I am using to extract the values: const colorMarkers = ...

Combining Angular with X3D to create a seamless integration, showcasing a minimalist representation of a box

I am brand new to web development, and I am feeling completely overwhelmed. Recently, I decided to follow the Angular tutorial by downloading the Angular Quickstart from this link: https://github.com/angular/quickstart. My goal was to add a simple x3d ele ...

Trouble with selectionChange event in mat-select component in Angular 13

I'm having trouble getting the selectionChange event to fire in my mat-select when the value is changed. html file <mat-select (selectionChange)="changeCategory()"> <mat-option *ngFor="let category of categ ...

Steps to duplicate the package.json to the dist or build directory while executing the TypeScript compiler (tsc)

I am facing an issue with my TypeScript React component and the package.json file when transpiling it to es5 using tsc. The package.json file does not get copied automatically to the dist folder, as shown in the provided screenshot. I had to manually copy ...

Object data is not being received by the defaultValue in React Hook Form

I am currently utilizing React Hook Form to facilitate the process of editing/updating data. I retrieve my data from zustand with a value type of any, and then proceed to save it as the defaultValue in React Hook Form. However, when attempting to acquire v ...

Solving the issue where the argument type is not assignable to the parameter type

I am attempting to filter an array of objects in React using TypeScript and encountered this error. Below is my interface, state, and function: TS2345: Argument of type '(prev: IBudget, current: IBudget) => IBudget | undefined' is not assigna ...

Angular causes HTML Dropdown to vanish once a null value is assigned

In my scenario, I have two variables named power and mainPower. Both of these variables essentially represent the same concept, with mainPower storing an ID of type Long in the backend, while power contains all attributes of this data transfer object. The ...

Ways to obtain the Map object from HTTPClient in Angular

When calling a REST endpoint, the return type is as follows: ResponseEntity<Map<String, List<Object>>> How can I handle this response on the Angular side? I attempted the following approach: let requiredData = new Map<String, Array&l ...

Obtain the default/initial argument type of typescript for extension purposes

Currently, I am in the process of developing code that automatically generates type hints based on function calls related to GraphQL Nexus tasks. In one of its functions, it requires an anonymous type constructed from the attributes generated automaticall ...

Establishing authentication with passport-jwt

I am facing some challenges when trying to configure passport-jwt with my express API server. In my front end, I am utilizing ember.js to send credentials to the /auth route in order to authenticate the session. The library within ember.js is then respons ...

What are some alternatives for integrating React production build files apart from utilizing Express?

Is there a way to integrate React into my library using the HTTP module? I'm trying to figure out how to recursively send static files. Specifically, I want to include the build folder from the React production build, but I'm not sure how to go a ...

Navigating the intricacies of debugging sub-domains in Angular projects using Visual Studio Code (VS

Currently working on a massive project utilizing micro-services. The unique design for clients/tenants requires visiting their specific subdomain to select a particular tenant. For example, https://ClientA.localhost:4200 and https://ClientB.localhost:4200. ...

The ngModel directive seems to be failing to bind the select element in Angular 4

One of the challenges I am facing in my application involves a form that includes various data fields such as title, price, category (select), and imageUrl. I have successfully implemented ngModel for all fields except the select element. Strangely, when I ...

Creating a dynamic selection in Angular without duplicate values

How can I prevent repetition of values when creating a dynamic select based on an object fetched from a database? Below is the HTML code: <router-outlet></router-outlet> <hr> <div class="row"> <div class="col-xs-12"> & ...

Error: This property is not available on either 'false' or 'HTMLAudioElement' types

When working with React (Next.js) using hooks and typescript, I encountered an issue while trying to create a reference to an Audio element. The error message I received was: Property 'duration' does not exist on type 'false | HTMLAudioEleme ...

Executing callback in the incorrect context

I'm facing an issue and can't seem to navigate through it. I am setting up a callback from a third party directive, but the callback is not returning with the correct scope. This means that when it reaches my controller, this refers to some other ...

declare wrong TypeScript type in external library

I am currently using winston 3.0 in combination with the @types/winston types. Unfortunately, it seems that these types are not completely compatible, leading to an error in the types that I am unsure how to rectify. Below is the code snippet in question: ...

What is the recommended data type to assign to the `CardElement` when using the `@stripe/react-stripe-js` package in TypeScript?

I'm struggling to determine the correct type to use for this import: import { CardElement } from '@stripe/react-stripe-js'; I have successfully used the types Stripe, StripeElements, and CreateTokenCardData for the stripe and elements props ...

Investigating the issue: Why is my React Typescript canvas image resizing component producing small, fuzzy images from high-quality, large images

I have developed a small image resizer but am facing an issue with the output images being blurry, especially when working with large images. import React, { useState } from 'react'; interface PropsInterface { placeholder: string; resizeTo: ...

Is there intellisense support for Angular 2 templates in Visual Studio?

Is it possible for Visual Studio to provide autocomplete suggestions for properties of a Typescript component within a separate HTML view template? ...