Skip to content

Commit

Permalink
Merge pull request #3 from carbonteq/add-jwt-client
Browse files Browse the repository at this point in the history
Add jwt client
  • Loading branch information
volf52 committed Jun 11, 2023
2 parents 909645e + 8153d71 commit c5e045b
Show file tree
Hide file tree
Showing 13 changed files with 470 additions and 200 deletions.
5 changes: 5 additions & 0 deletions .changeset/good-seas-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@carbonteq/jwt": minor
---

Add JwtClient and ClaimOpts
8 changes: 7 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ version = "0.0.0"
crate-type = ["cdylib"]

[dependencies]
jsonwebtoken = { version = "8.3.0", default-features = false }
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
napi = { version = "2.12.2", default-features = false, features = ["napi4"] }
napi = { version = "2.12.2", default-features = false, features = [
"napi4",
"serde-json",
] }
napi-derive = "2.12.2"
serde = { version = "1.0.164" }
serde_json = "1.0.96"

[build-dependencies]
napi-build = "2.0.1"
Expand Down
68 changes: 68 additions & 0 deletions __test__/jwt-client.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Claims, JwtClient } from '../index';
import test from 'ava';
import * as jose from 'jose';

const secret = 'testsecretkeycanbeexposed';
const secretEnc = new TextEncoder().encode(secret);
const client = new JwtClient(secret);

const testPayload = { user: '[email protected]' };

test('should create a valid token from payload', async (t) => {
const token = client.sign(testPayload, 10000);
const joseVerifyRes = await jose.jwtVerify(token, secretEnc);

t.deepEqual(joseVerifyRes.payload?.data, testPayload);
});

test('should create a valid token from claims', async (t) => {
const claims = new Claims(testPayload, 10000);
const token = client.signClaims(claims);
const joseVerifyRes = await jose.jwtVerify(token, secretEnc);

t.deepEqual(joseVerifyRes.payload?.data, testPayload);
});

test('created token should be valid', (t) => {
const token = client.sign(testPayload, 10000);

t.true(client.verify(token));
});

test('created (claims) token should be valid', (t) => {
const claims = new Claims(testPayload, 10000);
const token = client.signClaims(claims);

t.true(client.verify(token));
});

test('decode output should give the correct payload data', (t) => {
const token = client.sign(testPayload, 10000);
const decoded = client.verifyAndDecode(token);

t.deepEqual(decoded.data, testPayload);
});

test('decode output should give the correct payload data for claims', (t) => {
const claims = new Claims(testPayload, 10000);
const token = client.signClaims(claims);
const decoded = client.verifyAndDecode(token);

t.deepEqual(decoded.data, testPayload);
});

test('verifying after exp should return false', async (t) => {
const claims = new Claims(testPayload, 2);
claims.exp = 10; // In the past
const token = client.signClaims(claims);

t.false(client.verify(token));
});

test('decoding after exp should throw error', async (t) => {
const claims = new Claims(testPayload, 2);
claims.exp = 10; // In the past
const token = client.signClaims(claims);

t.throws(() => client.verifyAndDecode(token));
});
6 changes: 0 additions & 6 deletions __test__/mul.spec.ts

This file was deleted.

6 changes: 0 additions & 6 deletions __test__/sum.spec.ts

This file was deleted.

105 changes: 56 additions & 49 deletions bench/decode.mjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import bench from "benchmark";
import jwt from "jsonwebtoken";
import fastJwt from "fast-jwt";
import * as jose from "jose";
import { Claims, sign, decodeToken } from "../index.js";
import bench from 'benchmark';
import jwt from 'jsonwebtoken';
import fastJwt from 'fast-jwt';
import * as jose from 'jose';
import { Claims, JwtClient } from '../index.js';

const suite = new bench.Suite();

const secret = "somelongsecretasdbnakwfbjawf";
const secret = 'somelongsecretasdbnakwfbjawf';
const minSamples = 100;

const encodedKey = new TextEncoder().encode(secret);
const payload = { userId: "abc123" };
const payload = { userId: 'abc123' };

const client = new JwtClient(secret);

const joseSign = async (payload) => {
const s = new jose.SignJWT(payload);
return s.setProtectedHeader({ alg: "HS256" }).sign(encodedKey);
// const key = jose.JWK.asKey(secret);
// return await jose.JWT.sign(payload, key);
const s = new jose.SignJWT(payload);
return s.setProtectedHeader({ alg: 'HS256' }).sign(encodedKey);
// const key = jose.JWK.asKey(secret);
// return await jose.JWT.sign(payload, key);
};

const joseSigned = await joseSign(payload);
Expand All @@ -24,43 +28,46 @@ const signer = fastJwt.createSigner({ key: secret });
const fastJwtDecode = fastJwt.createDecoder();
const fastJwtSigned = signer(payload);

const currentTimeStamp = new Date().getTime();
const claims = new Claims(JSON.stringify(payload), currentTimeStamp + 60000);
const fasterJwtSigned = sign(claims, secret);
const claims = new Claims(JSON.stringify(payload), 60000);
const fasterJwtSigned = client.signClaims(claims);

suite
.add("jsonwebtoken#decode", {
defer: true,
fn: function (deferred) {
jwt.decode(jwtSigned);
deferred.resolve();
},
})
.add("jose#decode", {
defer: true,
fn: function (deferred) {
jose.decodeJwt(joseSigned);
deferred.resolve();
},
})
.add("fastjwt#decode", {
defer: true,
fn: function (deferred) {
fastJwtDecode(fastJwtSigned);
deferred.resolve();
},
})
.add("faster-jwt#decode", {
defer: true,
fn: function (deferred) {
decodeToken(fasterJwtSigned, secret);
deferred.resolve();
},
})
.on("cycle", (e) => {
console.log(String(e.target));
})
.on("complete", function () {
console.log("\nFastest is " + this.filter("fastest").map("name"));
})
.run({ async: true });
.add('jsonwebtoken#decode', {
defer: true,
minSamples,
fn: function (deferred) {
jwt.decode(jwtSigned);
deferred.resolve();
},
})
.add('jose#decode', {
defer: true,
minSamples,
fn: function (deferred) {
jose.decodeJwt(joseSigned);
deferred.resolve();
},
})
.add('fastjwt#decode', {
defer: true,
minSamples,
fn: function (deferred) {
fastJwtDecode(fastJwtSigned);
deferred.resolve();
},
})
.add('@carbonteq/jwt#decode', {
defer: true,
minSamples,
fn: function (deferred) {
client.decode(fasterJwtSigned);
deferred.resolve();
},
})
.on('cycle', (e) => {
console.log(String(e.target));
})
.on('complete', function () {
console.log('\nFastest is ' + this.filter('fastest').map('name'));
})
.run({ async: true });
131 changes: 64 additions & 67 deletions bench/sign.mjs
Original file line number Diff line number Diff line change
@@ -1,77 +1,74 @@
import bench from "benchmark";
import jwt from "jsonwebtoken";
import fastJwt from "fast-jwt";
import * as jose from "jose";
import { Claims, sign, Signer } from "../index.js";
import bench from 'benchmark';
import jwt from 'jsonwebtoken';
import fastJwt from 'fast-jwt';
import * as jose from 'jose';
import { Claims, JwtClient } from '../index.js';

const suite = new bench.Suite();

const secret = "somelongsecretasdbnakwfbjawf";
const secret = 'somelongsecretasdbnakwfbjawf';
const minSamples = 100;

const encodedKey = new TextEncoder().encode(secret);
const payload = { userId: "abc123" };
const payload = { userId: 'abc123' };

let myEncoder = new Signer(secret);
let myEncoder2 = Signer.fromBufferKey(Buffer.from(secret));
const client = new JwtClient(secret);

const joseSign = async (payload) => {
const s = new jose.SignJWT(payload);
return s.setProtectedHeader({ alg: "HS256" }).sign(encodedKey);
// const key = jose.JWK.asKey(secret);
// return await jose.JWT.sign(payload, key);
const s = new jose.SignJWT(payload);
return s.setProtectedHeader({ alg: 'HS256' }).sign(encodedKey);
// const key = jose.JWK.asKey(secret);
// return await jose.JWT.sign(payload, key);
};

suite
.add("jsonwebtoken#sign", {
defer: true,
fn: function (deferred) {
jwt.sign(payload, secret);
deferred.resolve();
},
})
.add("jose#sign", {
defer: true,
fn: function (deferred) {
joseSign(payload).then(() => deferred.resolve());
// const s = new jose.SignJWT(payload);
// s.setProtectedHeader({ alg: "HS256" }).sign(encodedKey).then(defer);
},
})
.add("fastjwt#sign", {
defer: true,
fn: function (deferred) {
const signer = fastJwt.createSigner({ key: secret });
signer(payload);
deferred.resolve();
},
})
.add("faster-jwt#sign", {
defer: true,
fn: function (deferred) {
const claims = new Claims(JSON.stringify(payload), 1000);
sign(claims, secret);
deferred.resolve();
},
})
.add("faster-jwt#signWithEncoder", {
defer: true,
fn: function (deferred) {
const claims = new Claims(JSON.stringify(payload), 1000);
myEncoder.sign(claims);
deferred.resolve();
},
})
.add("faster-jwt#signWithEncoder2", {
defer: true,
fn: function (deferred) {
const claims = new Claims(JSON.stringify(payload), 1000);
myEncoder2.sign(claims);
deferred.resolve();
},
})
.on("cycle", (e) => {
console.log(String(e.target));
})
.on("complete", function () {
console.log("Fastest is " + this.filter("fastest").map("name"));
})
.run({ async: true });
.add('jsonwebtoken#sign', {
defer: true,
minSamples,
fn: function (deferred) {
jwt.sign(payload, secret);
deferred.resolve();
},
})
.add('jose#sign', {
defer: true,
minSamples,
fn: function (deferred) {
joseSign(payload).then(() => deferred.resolve());
// const s = new jose.SignJWT(payload);
// s.setProtectedHeader({ alg: "HS256" }).sign(encodedKey).then(defer);
},
})
.add('fastjwt#sign', {
defer: true,
minSamples,
fn: function (deferred) {
const signer = fastJwt.createSigner({ key: secret });
signer(payload);
deferred.resolve();
},
})
.add('@carbonteq/jwt#sign', {
defer: true,
minSamples,
fn: function (deferred) {
client.sign(payload, 1000);
deferred.resolve();
},
})
.add('@carbonteq/jwt#signClaims', {
defer: true,
minSamples,
fn: function (deferred) {
const claims = new Claims(payload, 1000);
client.signClaims(claims);
deferred.resolve();
},
})
.on('cycle', (e) => {
console.log(String(e.target));
})
.on('complete', function () {
console.log('\nFastest is ' + this.filter('fastest').map('name'));
})
.run({ async: true });
Loading

0 comments on commit c5e045b

Please sign in to comment.