Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jsonwebtoken): expose decode header utility #795

Merged
merged 9 commits into from
Feb 26, 2024
Merged
16 changes: 15 additions & 1 deletion packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { join } from 'node:path'
import test from 'ava'
import { decode as nodeJwtDecode } from 'jsonwebtoken'

import { Algorithm, sign, signSync, verifySync, verify } from '../index.js'
import { Algorithm, sign, signSync, verifySync, verify, decodeHeader } from '../index.js'

const getUtcTimestamp = () => Math.floor(new Date().getTime() / 1000)
const oneDayInSeconds = 86400
Expand All @@ -30,6 +30,20 @@ test('signSync and sign (async) should produce the same result', async (t) => {
t.truthy(nodeJwtDecode(resAsync))
})

test('should decode header', async (t) => {
const data = {
id: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
}
const claims = { data, exp: getUtcTimestamp() + oneDayInSeconds }
const secretKey = 'secret'
const headers = { algorithm: Algorithm.HS384 }

const token = await sign(claims, secretKey, headers)

const header = decodeHeader(token)
t.is(header.algorithm, Algorithm.HS384)
})

test('verify should return the decoded claims', async (t) => {
const data = {
id: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
Expand Down
2 changes: 2 additions & 0 deletions packages/jsonwebtoken/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const enum Algorithm {
EdDSA = 11
}

export function decodeHeader(token: string): Header

export interface Header {
/**
* The algorithm used
Expand Down
1 change: 1 addition & 0 deletions packages/jsonwebtoken/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ if (!nativeBinding) {
}

module.exports.Algorithm = nativeBinding.Algorithm
module.exports.decodeHeader = nativeBinding.decodeHeader
module.exports.sign = nativeBinding.sign
module.exports.signSync = nativeBinding.signSync
module.exports.verify = nativeBinding.verify
Expand Down
20 changes: 20 additions & 0 deletions packages/jsonwebtoken/src/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ impl From<Algorithm> for jsonwebtoken::Algorithm {
}
}

impl From<jsonwebtoken::Algorithm> for Algorithm {
#[inline]
fn from(value: jsonwebtoken::Algorithm) -> Self {
match value {
jsonwebtoken::Algorithm::ES256 => Algorithm::ES256,
jsonwebtoken::Algorithm::ES384 => Algorithm::ES384,
jsonwebtoken::Algorithm::EdDSA => Algorithm::EdDSA,
jsonwebtoken::Algorithm::HS256 => Algorithm::HS256,
jsonwebtoken::Algorithm::HS384 => Algorithm::HS384,
jsonwebtoken::Algorithm::HS512 => Algorithm::HS512,
jsonwebtoken::Algorithm::PS256 => Algorithm::PS256,
jsonwebtoken::Algorithm::PS384 => Algorithm::PS384,
jsonwebtoken::Algorithm::PS512 => Algorithm::PS512,
jsonwebtoken::Algorithm::RS256 => Algorithm::RS256,
jsonwebtoken::Algorithm::RS384 => Algorithm::RS384,
jsonwebtoken::Algorithm::RS512 => Algorithm::RS512,
}
}
}

impl Default for Algorithm {
fn default() -> Self {
Self::HS256
Expand Down
10 changes: 10 additions & 0 deletions packages/jsonwebtoken/src/decode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use napi_derive::napi;

use crate::header::Header;

#[napi]
pub fn decode_header(token: String) -> Header {
let result = jsonwebtoken::decode_header(&token);

result.unwrap().into()
}
16 changes: 16 additions & 0 deletions packages/jsonwebtoken/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ impl From<&Header> for jsonwebtoken::Header {
}
}

impl From<jsonwebtoken::Header> for Header {
#[inline]
fn from(value: jsonwebtoken::Header) -> Header {
Header {
algorithm: Algorithm::from(value.alg).into(),
content_type: value.cty.clone(),
json_key_url: value.jku.clone(),
key_id: value.kid.clone(),
x5_url: value.x5u.clone(),
x5_cert_chain: value.x5c.clone(),
x5_cert_thumbprint: value.x5t.clone(),
x5t_s256_cert_thumbprint: value.x5t_s256.clone(),
}
}
}

impl Header {
#[inline]
pub fn merge(self, other: Self) -> Self {
Expand Down
2 changes: 2 additions & 0 deletions packages/jsonwebtoken/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ extern crate global_alloc;

mod algorithm;
mod claims;
mod decode;
mod header;
mod sign;
mod validation;
mod verify;

pub use algorithm::Algorithm;
pub use claims::Claims;
pub use decode::decode_header;
pub use header::Header;
pub use sign::{sign, sign_sync};
pub use validation::Validation;
Expand Down