Skip to content

jwt-none-algorithm-usage

Ensure JWT algorithm defined

The usage of the none algorithm with JSON Web Token (JWT) is highly risky. And shall be avoided at all costs, because there is simply no way to verify the authenticity or assert the integrity of such tokens. The none algorithm simply means that the payload of the token is NOT cryptographically signed in any way (the signature part of the JWT is simply omitted). Using such method, would trivially allow a malicious actor to forge a token that will be implicitely considered valid. Instead of using the none algorithm, you should use an algorithm such as HS256 (HMAC with SHA256), RS256 (RSA with SHA256) or ECS56 (ECDSA using P-256 with SHA256).

Examples

Insecure Example

package main

import (
    "time"
    "github.com/dgrijalva/jwt-go"
)

func GenerateJWT(userId string) string {
    claims := jwt.StandardClaims{
        Issuer: "server",
        Subject: userId,
        ExpiresAt: time.Now().Unix() + 3600,
    }

    token := jwt.NewWithClaims(jwt.SigningMethodNone, claims)
    tokenString, _ := token.SignedString(jwt.UnsafeAllowNoneSignatureType)

    return tokenString
}
package com.bigcorp.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;

public class App
{
    private static String generateJWT(String userId) throws Exception {
        // Algorithm.none() is not safe
        String token = JWT.create()
            .withIssuer("server")
            .withSubject(userId)
            .sign(Algorithm.none());

        return token;
    }
}
const jwt = require('jsonwebtoken')
const SECRET = process.env.JWT_SECRET_KEY

function generateJWT(userId) {
    const payload = {
        Issuer: "server",
        Subject: userId,
    }
    // { algorithm: 'none' } is not safe
    const token = jwt.sign(payload, SECRET, {algorithm: 'none'}));
    return token
}
import datetime
import jwt

JWT_SECRET = os.getenv('JWT_SECRET')

def generateJWT(userId):
    #Generate token
    timeLimit= datetime.datetime.utcnow() + datetime.timedelta(minutes=30) #set limit for user
    payload = {"user_id": userId ,"exp":timeLimit}

    # algorithm='none' is not safe
    return jwt.encode(payload, JWT_SECRET, algorithm='none')
require 'json/jwt'

jwtsecret = ENV['JWT_SECRET']

def generate_jwt(userid)
    # setting the algorithm parameter to 'none' is not safe
    return JSON::JWT.new(payload).sign(jwtsecret, 'none')
end

Secure Example

package main

import (
    "time"
    "os"
    "github.com/dgrijalva/jwt-go"
)

func getSigningKey() []byte {
    secret := os.Getenv("JWT_SECRET")
    if (secret == "") {
        panic("JWT_SECRET environment variable not found - aborting")
    }
    return []byte(secret)
}

func GenerateJWT(userId string) string {
    claims := jwt.StandardClaims{
        Issuer: "server",
        Subject: userId,
        ExpiresAt: time.Now().Unix() + 3600,
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, _ := token.SignedString(getSigningKey())

    return tokenString
}
package com.bigcorp.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;

public class App
{
    private static String generateJWT(String userId) throws Exception {
        String secret = System.getenv("JWT_SECRET");

        // HMAC256 is a safe algorithm choice
        String token = JWT.create()
            .withIssuer("server")
            .withSubject(userId)
            .sign(Algorithm.HMAC256(secret));

        return token;
    }
}
const jwt = require('jsonwebtoken')
const SECRET = process.env.JWT_SECRET_KEY

function generateJWT(userId) {
    const payload = {
        Issuer: "server",
        Subject: userId,
    }
    // { algorithm: 'HS256' } is a safe algorithm choice
    const token = jwt.sign(payload, SECRET, {algorithm: 'HS256'}));
    return token
}
import datetime
import jwt

JWT_SECRET = os.getenv('JWT_SECRET')

def generateJWT(userId):
    #Generate token
    timeLimit= datetime.datetime.utcnow() + datetime.timedelta(minutes=30) #set limit for user
    payload = {"user_id": userId ,"exp":timeLimit}

    # jwt.encode sets the optional parameter `algorithm` to 'HS256' by default
    # so the line below is safe. The same thing can be done more explicitly with
    # `return jwt.encode(payload, JWT_SECRET, algorithm='HS256')
    return jwt.encode(payload, JWT_SECRET)
require 'json/jwt'

jwtsecret = ENV['JWT_SECRET']

def generate_jwt(userid)
    # HS256 is a safe algorithm choice
    return JSON::JWT.new(payload).sign(jwtsecret, 'HS256')
end