Skip to content

Commit 89f2ce3

Browse files
authored
feat(jsonwebtoken): flatten claims to align with rfc (#780)
1 parent 7f436e8 commit 89f2ce3

File tree

9 files changed

+32
-90
lines changed

9 files changed

+32
-90
lines changed

packages/crc32/__tests__/__snapshots__/index.spec.ts.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,3 @@ Generated by [AVA](https://avajs.dev).
1515
> Snapshot 1
1616
1717
614479218
18-
19-
## crc32c result should be equal with sse4_crc32 when caclulate with initial crc
20-
21-
> Snapshot 1
22-
23-
614479218
Binary file not shown.
Binary file not shown.

packages/jsonwebtoken/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ crate-type = ["cdylib"]
99

1010
[dependencies]
1111
global_alloc = { path = "../../crates/alloc" }
12+
indexmap = { version = "2", features = ["serde"] }
1213
jsonwebtoken = { version = "9" }
1314
napi = { version = "2", default-features = false, features = [
1415
"napi3",
15-
"serde-json",
16+
"serde-json-ordered",
17+
"object_indexmap",
1618
] }
1719
napi-derive = { version = "2" }
1820
rand_core = { version = "0.6", features = ["std"] }

packages/jsonwebtoken/__tests__/jsonwebtoken.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const getUtcTimestamp = () => Math.floor(new Date().getTime() / 1000)
1010
const oneDayInSeconds = 86400
1111

1212
test('signSync and sign (async) should produce the same result', async (t) => {
13+
const iat = getUtcTimestamp()
1314
const claims = {
1415
data: {
1516
id: 'f81d4fae-7dec-11d0-a765-00a0c91e6bf6',
@@ -18,7 +19,8 @@ test('signSync and sign (async) should produce the same result', async (t) => {
1819
set: ['KL', 'TV', 'JI'],
1920
nest: { id: 'poly' },
2021
},
21-
exp: getUtcTimestamp() + oneDayInSeconds,
22+
exp: iat + oneDayInSeconds,
23+
iat,
2224
}
2325
const secretKey = 'secret'
2426
const resSync = signSync(claims, secretKey)

packages/jsonwebtoken/index.d.ts

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

31-
export interface Claims {
32-
data?: Record<string, any>
33-
aud?: string
34-
exp?: number
35-
iat?: number
36-
iss?: string
37-
jti?: string
38-
nbf?: number
39-
sub?: string
40-
}
41-
4231
export interface Header {
4332
/**
4433
* The algorithm used
@@ -96,9 +85,9 @@ export interface Header {
9685
x5TS256CertThumbprint?: string
9786
}
9887

99-
export function sign(claims: Claims, key: string | Buffer, header?: Header | undefined | null, abortSignal?: AbortSignal | undefined | null): Promise<string>
88+
export function sign(claims: { [key: string]: any }, key: string | Buffer, header?: Header | undefined | null, abortSignal?: AbortSignal | undefined | null): Promise<string>
10089

101-
export function signSync(claims: Claims, key: string | Buffer, header?: Header | undefined | null): string
90+
export function signSync(claims: { [key: string]: any }, key: string | Buffer, header?: Header | undefined | null): string
10291

10392
export interface Validation {
10493
/**

packages/jsonwebtoken/index.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,14 +323,18 @@ switch (platform) {
323323
if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
324324
try {
325325
nativeBinding = require('./jsonwebtoken.wasi.cjs')
326-
} catch {
327-
// ignore
326+
} catch (err) {
327+
if (process.env.NAPI_RS_FORCE_WASI) {
328+
console.error(err)
329+
}
328330
}
329331
if (!nativeBinding) {
330332
try {
331333
nativeBinding = require('@node-rs/jsonwebtoken-wasm32-wasi')
332334
} catch (err) {
333-
console.error(err)
335+
if (process.env.NAPI_RS_FORCE_WASI) {
336+
console.error(err)
337+
}
334338
}
335339
}
336340
}

packages/jsonwebtoken/src/claims.rs

Lines changed: 3 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,4 @@
1-
use napi_derive::napi;
2-
use serde::{Deserialize, Serialize};
3-
use serde_json::{Map, Number, Value};
1+
use indexmap::IndexMap;
2+
use serde_json::Value;
43

5-
#[napi(object)]
6-
#[derive(Debug, Serialize, Deserialize)]
7-
pub struct Claims {
8-
#[serde(skip_serializing_if = "Option::is_none")]
9-
pub data: Option<Map<String, Value>>,
10-
// Recipient for which the JWT is intended
11-
#[serde(skip_serializing_if = "Option::is_none")]
12-
pub aud: Option<String>,
13-
// Time after which the JWT expires (as UTC timestamp, seconds from epoch time)
14-
#[serde(skip_serializing_if = "Option::is_none")]
15-
pub exp: Option<Number>,
16-
// Time at which the JWT was issued (as UTC timestamp, seconds from epoch time)
17-
#[serde(skip_serializing_if = "Option::is_none")]
18-
pub iat: Option<Number>,
19-
// Issuer of JWT
20-
#[serde(skip_serializing_if = "Option::is_none")]
21-
pub iss: Option<String>,
22-
// [JWT id] Unique identifier
23-
#[serde(skip_serializing_if = "Option::is_none")]
24-
pub jti: Option<String>,
25-
// [not-before-time] Time before which the JWT must not be accepted for processing (as UTC timestamp, seconds from epoch time)
26-
#[serde(skip_serializing_if = "Option::is_none")]
27-
pub nbf: Option<Number>,
28-
// Subject of JWT (the user)
29-
#[serde(skip_serializing_if = "Option::is_none")]
30-
pub sub: Option<String>,
31-
}
32-
33-
impl Claims {
34-
#[inline]
35-
pub fn merge(self, other: Self) -> Self {
36-
Self {
37-
data: self.data,
38-
aud: self.aud.or(other.aud),
39-
exp: self.exp.or(other.exp),
40-
iat: self.iat.or(other.iat),
41-
iss: self.iss.or(other.iss),
42-
jti: self.jti.or(other.jti),
43-
nbf: self.nbf.or(other.nbf),
44-
sub: self.sub.or(other.sub),
45-
}
46-
}
47-
}
48-
49-
impl Default for Claims {
50-
#[inline]
51-
fn default() -> Self {
52-
Self {
53-
data: Some(Map::new()),
54-
aud: None,
55-
exp: None,
56-
iat: Some(jsonwebtoken::get_current_timestamp().into()),
57-
iss: None,
58-
jti: None,
59-
nbf: None,
60-
sub: None,
61-
}
62-
}
63-
}
4+
pub type Claims = IndexMap<String, Value>;

packages/jsonwebtoken/src/sign.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,22 @@ impl Task for SignTask {
9898

9999
#[napi]
100100
pub fn sign(
101-
claims: Claims,
101+
#[napi(ts_arg_type = "{ [key: string]: any }")] mut claims: Claims,
102102
key: Either<String, JsBuffer>,
103103
header: Option<Header>,
104104
abort_signal: Option<AbortSignal>,
105105
) -> Result<AsyncTask<SignTask>> {
106+
if !claims.contains_key("iat") {
107+
claims.insert("iat".parse()?, jsonwebtoken::get_current_timestamp().into());
108+
}
109+
106110
Ok(AsyncTask::with_optional_signal(
107111
SignTask {
108112
header: match header {
109113
Some(h) => h.merge(Header::default()),
110114
_ => Header::default(),
111115
},
112-
claims: claims.merge(Claims::default()),
116+
claims,
113117
key: AsyncKeyInput::from_either(key)?,
114118
},
115119
abort_signal,
@@ -118,15 +122,21 @@ pub fn sign(
118122

119123
#[napi]
120124
pub fn sign_sync(
121-
claims: Claims,
125+
#[napi(ts_arg_type = "{ [key: string]: any }")] mut claims: Claims,
122126
key: Either<String, Buffer>,
123127
header: Option<Header>,
124128
) -> Result<String> {
129+
if !claims.contains_key("iat") {
130+
claims.insert(
131+
"iat".to_owned(),
132+
jsonwebtoken::get_current_timestamp().into(),
133+
);
134+
}
135+
125136
let header = match header {
126137
Some(h) => h.merge(Header::default()),
127138
_ => Header::default(),
128139
};
129-
let claims = claims.merge(Claims::default());
130140

131141
SignTask::sign(&claims, &header, key.as_ref())
132142
}

0 commit comments

Comments
 (0)