diff --git a/packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts b/packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts index 613fed5a..44f4c0e6 100644 --- a/packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts +++ b/packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts @@ -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 @@ -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', diff --git a/packages/jsonwebtoken/index.d.ts b/packages/jsonwebtoken/index.d.ts index bdb42102..a96c1f24 100644 --- a/packages/jsonwebtoken/index.d.ts +++ b/packages/jsonwebtoken/index.d.ts @@ -28,6 +28,8 @@ export const enum Algorithm { EdDSA = 11 } +export function decodeHeader(token: string): Header + export interface Header { /** * The algorithm used diff --git a/packages/jsonwebtoken/index.js b/packages/jsonwebtoken/index.js index 735c47cd..1759598f 100644 --- a/packages/jsonwebtoken/index.js +++ b/packages/jsonwebtoken/index.js @@ -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 diff --git a/packages/jsonwebtoken/src/algorithm.rs b/packages/jsonwebtoken/src/algorithm.rs index d749d793..4ca8aa3c 100644 --- a/packages/jsonwebtoken/src/algorithm.rs +++ b/packages/jsonwebtoken/src/algorithm.rs @@ -48,6 +48,26 @@ impl From for jsonwebtoken::Algorithm { } } +impl From 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 diff --git a/packages/jsonwebtoken/src/decode.rs b/packages/jsonwebtoken/src/decode.rs new file mode 100644 index 00000000..f802f443 --- /dev/null +++ b/packages/jsonwebtoken/src/decode.rs @@ -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() +} diff --git a/packages/jsonwebtoken/src/header.rs b/packages/jsonwebtoken/src/header.rs index 34da8da3..cf402294 100644 --- a/packages/jsonwebtoken/src/header.rs +++ b/packages/jsonwebtoken/src/header.rs @@ -73,6 +73,22 @@ impl From<&Header> for jsonwebtoken::Header { } } +impl From 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 { diff --git a/packages/jsonwebtoken/src/lib.rs b/packages/jsonwebtoken/src/lib.rs index 01f2c49a..9dc180e2 100644 --- a/packages/jsonwebtoken/src/lib.rs +++ b/packages/jsonwebtoken/src/lib.rs @@ -6,6 +6,7 @@ extern crate global_alloc; mod algorithm; mod claims; +mod decode; mod header; mod sign; mod validation; @@ -13,6 +14,7 @@ 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;