Skip to content

Commit fc259ce

Browse files
authored
feat(jsonwebtoken): expose decode header utility (#795)
* feat: expose decode header utility * style: apply linting rules * fix: minor adjustments & add test suite * style: apply linting rules in test suite * fix: algorithm transformation & decode header fn * style: apply linting rules * fix: apply clippy suggestions * fix: simplified decode_header fn & generated index.{js,d.ts}
1 parent 5993557 commit fc259ce

File tree

7 files changed

+66
-1
lines changed

7 files changed

+66
-1
lines changed

packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { join } from 'node:path'
44
import test from 'ava'
55
import { decode as nodeJwtDecode } from 'jsonwebtoken'
66

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

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

33+
test('should decode header', async (t) => {
34+
const data = {
35+
id: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
36+
}
37+
const claims = { data, exp: getUtcTimestamp() + oneDayInSeconds }
38+
const secretKey = 'secret'
39+
const headers = { algorithm: Algorithm.HS384 }
40+
41+
const token = await sign(claims, secretKey, headers)
42+
43+
const header = decodeHeader(token)
44+
t.is(header.algorithm, Algorithm.HS384)
45+
})
46+
3347
test('verify should return the decoded claims', async (t) => {
3448
const data = {
3549
id: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6',

packages/jsonwebtoken/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export const enum Algorithm {
2828
EdDSA = 11
2929
}
3030

31+
export function decodeHeader(token: string): Header
32+
3133
export interface Header {
3234
/**
3335
* The algorithm used

packages/jsonwebtoken/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ if (!nativeBinding) {
347347
}
348348

349349
module.exports.Algorithm = nativeBinding.Algorithm
350+
module.exports.decodeHeader = nativeBinding.decodeHeader
350351
module.exports.sign = nativeBinding.sign
351352
module.exports.signSync = nativeBinding.signSync
352353
module.exports.verify = nativeBinding.verify

packages/jsonwebtoken/src/algorithm.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,26 @@ impl From<Algorithm> for jsonwebtoken::Algorithm {
4848
}
4949
}
5050

51+
impl From<jsonwebtoken::Algorithm> for Algorithm {
52+
#[inline]
53+
fn from(value: jsonwebtoken::Algorithm) -> Self {
54+
match value {
55+
jsonwebtoken::Algorithm::ES256 => Algorithm::ES256,
56+
jsonwebtoken::Algorithm::ES384 => Algorithm::ES384,
57+
jsonwebtoken::Algorithm::EdDSA => Algorithm::EdDSA,
58+
jsonwebtoken::Algorithm::HS256 => Algorithm::HS256,
59+
jsonwebtoken::Algorithm::HS384 => Algorithm::HS384,
60+
jsonwebtoken::Algorithm::HS512 => Algorithm::HS512,
61+
jsonwebtoken::Algorithm::PS256 => Algorithm::PS256,
62+
jsonwebtoken::Algorithm::PS384 => Algorithm::PS384,
63+
jsonwebtoken::Algorithm::PS512 => Algorithm::PS512,
64+
jsonwebtoken::Algorithm::RS256 => Algorithm::RS256,
65+
jsonwebtoken::Algorithm::RS384 => Algorithm::RS384,
66+
jsonwebtoken::Algorithm::RS512 => Algorithm::RS512,
67+
}
68+
}
69+
}
70+
5171
impl Default for Algorithm {
5272
fn default() -> Self {
5373
Self::HS256

packages/jsonwebtoken/src/decode.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use napi_derive::napi;
2+
3+
use crate::header::Header;
4+
5+
#[napi]
6+
pub fn decode_header(token: String) -> Header {
7+
let result = jsonwebtoken::decode_header(&token);
8+
9+
result.unwrap().into()
10+
}

packages/jsonwebtoken/src/header.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,22 @@ impl From<&Header> for jsonwebtoken::Header {
7373
}
7474
}
7575

76+
impl From<jsonwebtoken::Header> for Header {
77+
#[inline]
78+
fn from(value: jsonwebtoken::Header) -> Header {
79+
Header {
80+
algorithm: Algorithm::from(value.alg).into(),
81+
content_type: value.cty.clone(),
82+
json_key_url: value.jku.clone(),
83+
key_id: value.kid.clone(),
84+
x5_url: value.x5u.clone(),
85+
x5_cert_chain: value.x5c.clone(),
86+
x5_cert_thumbprint: value.x5t.clone(),
87+
x5t_s256_cert_thumbprint: value.x5t_s256.clone(),
88+
}
89+
}
90+
}
91+
7692
impl Header {
7793
#[inline]
7894
pub fn merge(self, other: Self) -> Self {

packages/jsonwebtoken/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ extern crate global_alloc;
66

77
mod algorithm;
88
mod claims;
9+
mod decode;
910
mod header;
1011
mod sign;
1112
mod validation;
1213
mod verify;
1314

1415
pub use algorithm::Algorithm;
1516
pub use claims::Claims;
17+
pub use decode::decode_header;
1618
pub use header::Header;
1719
pub use sign::{sign, sign_sync};
1820
pub use validation::Validation;

0 commit comments

Comments
 (0)