npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

easy-token-auth

v1.2.2

Published

Easy Token Authentication Implementation with access and refresh tokens

Readme

Easy Token Auth

Implement Token Authentication into your project easily

This is developed as a wrapper for jsonwebtoken

Install

npm:

$ npm i easy-token-auth

Usage Example

utils/auth.ts

import { createAuthHandler } from "easy-token-auth";

const authHandler = createAuthHandler()
const credentials = generateCredentials('ES384')
authHandler.setCredentials(credentials)

cron.schedule('0 0 */7 * *', () => { // optional
    const credentials = generateCredentials('ES384')
    authHandler.setCredentials(credentials) // generate and set new key pair every 7 days
});

export authHandler

/api/login.ts

import { authHandler } from 'utils/auth'

router.post("/", async (req: Request, res: Response) => {
    const userId = USER_ID
    try{
        const accessJWT = authHandler.generateAccessToken(userId);
        const { hashedToken, jwt: refreshJWT } = authHandler.generateRefreshToken();
        // STORE hashedToken WITH userId IN DATABASE
        // STORE refreshJWT IN USER DEVICE SAFELY -> Example: httpOnly Cookie
        // STORE accessJWT IN USER DEVICE
    }catch(err){
        ...
    }
})

/api/refresh.ts

import { authHandler } from 'utils/auth';
import { hashRefreshToken } from 'easy-token-auth';

router.post("/", async (req: Request, res: Response) => {
    const refreshJWT = USER_REFRESH_JWT
    try{
        const token = authHandler.verifyAndDecodeToken(refreshJWT);
        const hashedToken = hashRefreshToken(token)
        // FIND hashedToken IN DATABASE
        const accessJWT = authHandler.generateAccessToken(userId);
        const { hashedToken, jwt: refreshJWT } = authHandler.generateRefreshToken();
        // UPDATE hashedToken IN DATABASE
        // STORE refreshJWT IN USER DEVICE SAFELY -> Example: httpOnly Cookies
        // STORE accessJWT IN USER DEVICE
    }catch(err){
        ...
    }
})

Usage

Package usage with examples

Creating Auth Handler

createAuthHandler(config?: Partial<Config>)

Returns functions for generating and verifying tokens

  • config is ojbect of Config type and can be partial.

Config

type TokenConfig = {
    expiry: number
}
type Config = {
    access_token: TokenConfig,
    refresh_token: TokenConfig,
    credentials_limit: number
}

Because config can be partially set we have default values:

|Property | Value | |----------------------|----------------| | access_token.expiry | 3600s | | refresh_token.expiry | 7776000s | | credentials_limit | 10 |

credentials_limit is number of old Credentials which can be saved in memory.

Explanation: Auth Handler can store more than one credentials at a time and can provide easy key rotation logic. Because of that developer can set how many credentials can be set before deleting oldest ones. For example user can login at day 1 and after x + 1 days (where x is days after keys reroll) user wont be able to login even if his jwt isn't expired so because of that developers are able to store n credentials for each Auth Handler.

Example

In this example, we’ll set the refresh token expiration to 10 days and limit the credentials to 2. It’s recommended to rotate credentials every 6+ days. This way, if a user logs in on the first day and doesn’t refresh their tokens for 9 days, they will still be able to refresh them on the 10th day. If we don't store the first token, the user won’t be able to refresh it after that period.

const config: Partial<Config> = {
    refresh_token: {
        expiry: 3600 * 24 * 12 // 10 days
    },
    credentials_limit: 2
}
const authHandler = createAuthHandler(config)

Setting Credentials of Auth Handler

authHandler.setCredentials(credentials: Credentials) After initialization of Auth Handler setting credentials is needed. Every time you reroll you can call same method

Credentials

type Credentials = {
    id: string;
    algorithm: algorithm;
    privateKey: string;
    publicKey: string;
};

id is a unique string so every stored credential can be distinguished algorithm is a string representing algorithm used by jwt to sign tokens. Allowed values: RSA

  • RSA RS256, RS384, RS512
  • ECDSA ES256, ES384, ES512
  • PSS PS256, PS384, PS512

Examples

Example 1

Generating credentials with generateCredentials function.

const credentials = generateCredentials();
authHandler.setCredentials(credentials);
Example 2

Here we are going to create credentials manually and read already generated keys from files.

const credentials: Credentials = {
    id: RANDOM_STRING,
    algorithm: 'RS256',
    privateKey: fs.readFileSync(PATH_TO_KEY, 'utf-8'),
    publicKey: fs.readFileSync(PATH_TO_KEY, 'utf-8'),
}
authHandler.setCredentials(credentials);

Generating Access Token

authHandler.generateAccessToken(data: any)

Returns generated jwt

  • data is required and can be any type. userID or other unique user data

Examples

try{
    const userID = UNIQUE_USER_ID
    const token = authHandler.generateAccessToken(userID)
}catch(err){
    ...
}

Errors

soon...

Generating Refresh Token

authHandler.generateRefreshToken()

Returns object of jwt, token and hashedToken

  • jwt is generated jwt
  • token is random generated 64 string that is included in jwt
  • hashedToken is sha256 hashed token and it is not included in jwt

Example

try{
    const { jwt, token, hashedToken } = authHandler.generateRefreshToken()
}catch(err){
    ...
}

Errors

soon...

Idea behind refresh token

When user log in, he should store JWT somewhere safe in his device and also server should store hashedToken in database along userId or other unique identifier. When access token expires we should validate refresh token and extract token from it. After that we can use hashRefreshToken function to hash token and try to find that hashed value in database. Storing hashed value in database instead of plain one is a bit safer.

Validating Token

authHandler.verifyAndDecodeToken(jwt: string)

Returns decoded data

  • jwt is string of jsonwebtoken

Example

try{
    const jwt = YOUR_JSONWEBTOKEN
    const data = authHandler.verifyAndDecodeToken(jwt);
}catch(err){
    ...
}

Errors

soon...

Generating Credentials

generateCredentials(algorithm: Algorithm, keySize?: KeySize)

Returns generated credentials

  • algorithm is string representing algorithm which will be used with jwt.

    • RSA RS256, RS384, RS512
    • ECDSA ES256, ES384, ES512
  • keySize can be low, medium or high for

    • low: For general use with moderate security. RSA modulus is 2048 bits, ECDSA curve is prime256v1.
    • medium: For more secure key generation with a balance of performance. RSA modulus is 3072 bits, ECDSA curve is secp384r1.
    • high: For highly secure key generation, at the cost of performance. RSA modulus is 4096 bits, ECDSA curve is secp521r1.

Important: Key size must match algorithm for ECDSA, otherwise an error will be thrown. for e.g. 'ES256' algorithm must have 'low' key size.

Examples

Example 1

Here we are creating Credentials with RS384 algorithm and 2048 modulus length.

const credentials = generateCredentials('RS384', 'low');
/* credentials = {
    id: GENERATED_ID,
    privateKey: GENERATED_PRIVATE_KEY,
    publicKEY: GENERATED_PUBLIC_KEY,
    algorithm: 'RS384'
} */
Example 2

For RSA if keySize is not provided default value is medium.

const credentials = generateCredentials('RS256');
Example 3

For ECDSA if keySize is not provided it will be picked automatically. In this case high.

const credentials = generateCredentials('ES512');

Errors

soon...

Hashing Refresh Token

hashRefreshToken(token)

Returns hashed token

  • token is string of plain hexadecimal token

Example

const token = DECODED_REFRESH_JWT
const hashedToken = hashRefreshToken(token);

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

This project uses jsonwebtoken which is licensed under the MIT License. See the jsonwebtoken repository for more details.