Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit 750d280

Browse files
committed
fix: use real base64 converted values in the helpers
1 parent 056da53 commit 750d280

File tree

1 file changed

+48
-43
lines changed

1 file changed

+48
-43
lines changed

test/webauthn.helpers.test.ts

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ describe('WebAuthn Serialization/Deserialization', () => {
2323

2424
describe('deserializeCredentialCreationOptions', () => {
2525
const validServerOptions = {
26-
challenge: 'dGVzdC1jaGFsbGVuZ2U', // "test-challenge" in base64url
26+
challenge: 'SGVsbG8gV2ViQXV0aG4h',
2727
rp: {
2828
name: 'Test RP',
2929
id: 'example.com',
3030
},
3131
user: {
32-
id: 'dXNlci1pZA', // "user-id" in base64url
32+
id: 'dXNlci0xMjM0NTY',
3333
name: 'test@example.com',
3434
displayName: 'Test User',
3535
},
@@ -41,37 +41,40 @@ describe('WebAuthn Serialization/Deserialization', () => {
4141
attestation: 'direct' as const,
4242
excludeCredentials: [
4343
{
44-
id: 'Y3JlZC1pZA', // "cred-id" in base64url
44+
id: 'Y3JlZGVudGlhbC1hYmMteHl6',
4545
type: 'public-key' as const,
4646
transports: ['usb', 'nfc'] as AuthenticatorTransportFuture[],
4747
},
4848
],
4949
}
5050

5151
it('should convert base64url strings to ArrayBuffers using polyfill', () => {
52-
// Force polyfill path by removing PublicKeyCredential
52+
5353
delete (global as any).PublicKeyCredential
5454

5555
const result = deserializeCredentialCreationOptions(validServerOptions)
5656

57-
// Verify challenge was converted to ArrayBuffer
57+
5858
expect(result.challenge).toBeInstanceOf(ArrayBuffer)
5959
const challengeBytes = new Uint8Array(result.challenge)
60+
6061
expect(challengeBytes).toEqual(
61-
new Uint8Array([116, 101, 115, 116, 45, 99, 104, 97, 108, 108, 101, 110, 103, 101])
62+
new Uint8Array([72, 101, 108, 108, 111, 32, 87, 101, 98, 65, 117, 116, 104, 110, 33])
6263
)
6364

64-
// Verify user.id was converted to ArrayBuffer
65+
6566
expect(result.user.id).toBeInstanceOf(ArrayBuffer)
6667
const userIdBytes = new Uint8Array(result.user.id)
67-
expect(userIdBytes).toEqual(new Uint8Array([117, 115, 101, 114, 45, 105, 100]))
68+
69+
expect(userIdBytes).toEqual(new Uint8Array([117, 115, 101, 114, 45, 49, 50, 51, 52, 53, 54]))
6870

69-
// Verify excludeCredentials[0].id was converted to ArrayBuffer
71+
7072
expect(result.excludeCredentials![0].id).toBeInstanceOf(ArrayBuffer)
7173
const credIdBytes = new Uint8Array(result.excludeCredentials![0].id as ArrayBuffer)
72-
expect(credIdBytes).toEqual(new Uint8Array([99, 114, 101, 100, 45, 105, 100]))
74+
75+
expect(credIdBytes).toEqual(new Uint8Array([99, 114, 101, 100, 101, 110, 116, 105, 97, 108, 45, 97, 98, 99, 45, 120, 121, 122]))
7376

74-
// Verify other fields are preserved
77+
7578
expect(result.rp).toEqual(validServerOptions.rp)
7679
expect(result.pubKeyCredParams).toEqual(validServerOptions.pubKeyCredParams)
7780
expect(result.timeout).toBe(60000)
@@ -99,10 +102,10 @@ describe('WebAuthn Serialization/Deserialization', () => {
99102

100103
it('should handle missing optional fields correctly', () => {
101104
const minimalOptions = {
102-
challenge: 'dGVzdC1jaGFsbGVuZ2U',
105+
challenge: 'SGVsbG8gV2ViQXV0aG4h',
103106
rp: { name: 'Test RP' },
104107
user: {
105-
id: 'dXNlci1pZA',
108+
id: 'dXNlci0xMjM0NTY',
106109
name: 'test@example.com',
107110
displayName: 'Test User',
108111
},
@@ -130,13 +133,13 @@ describe('WebAuthn Serialization/Deserialization', () => {
130133

131134
describe('deserializeCredentialRequestOptions', () => {
132135
const validServerOptions = {
133-
challenge: 'dGVzdC1jaGFsbGVuZ2U',
136+
challenge: 'QXV0aGVudGljYXRlTWU',
134137
timeout: 60000,
135138
rpId: 'example.com',
136139
userVerification: 'preferred' as const,
137140
allowCredentials: [
138141
{
139-
id: 'Y3JlZC1pZA',
142+
id: 'YWxsb3dlZC1jcmVkLTEyMw',
140143
type: 'public-key' as const,
141144
transports: ['usb', 'nfc'] as AuthenticatorTransportFuture[],
142145
},
@@ -148,19 +151,21 @@ describe('WebAuthn Serialization/Deserialization', () => {
148151

149152
const result = deserializeCredentialRequestOptions(validServerOptions)
150153

151-
// Verify challenge was converted
154+
152155
expect(result.challenge).toBeInstanceOf(ArrayBuffer)
153156
const challengeBytes = new Uint8Array(result.challenge)
157+
154158
expect(challengeBytes).toEqual(
155-
new Uint8Array([116, 101, 115, 116, 45, 99, 104, 97, 108, 108, 101, 110, 103, 101])
159+
new Uint8Array([65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 77, 101])
156160
)
157161

158-
// Verify allowCredentials[0].id was converted
162+
159163
expect(result.allowCredentials![0].id).toBeInstanceOf(ArrayBuffer)
160164
const credIdBytes = new Uint8Array(result.allowCredentials![0].id as ArrayBuffer)
161-
expect(credIdBytes).toEqual(new Uint8Array([99, 114, 101, 100, 45, 105, 100]))
165+
166+
expect(credIdBytes).toEqual(new Uint8Array([97, 108, 108, 111, 119, 101, 100, 45, 99, 114, 101, 100, 45, 49, 50, 51]))
162167

163-
// Verify other fields preserved
168+
164169
expect(result.rpId).toBe('example.com')
165170
expect(result.userVerification).toBe('preferred')
166171
expect(result.timeout).toBe(60000)
@@ -192,15 +197,15 @@ describe('WebAuthn Serialization/Deserialization', () => {
192197
}
193198

194199
const result = deserializeCredentialRequestOptions(optionsWithEmptyArray)
195-
// Empty array is not added to result per implementation
200+
196201
expect(result.allowCredentials).toBeUndefined()
197202
})
198203

199204
it('should handle missing allowCredentials', () => {
200205
delete (global as any).PublicKeyCredential
201206

202207
const optionsWithoutAllow = {
203-
challenge: 'dGVzdC1jaGFsbGVuZ2U',
208+
challenge: 'QXV0aGVudGljYXRlTWU',
204209
rpId: 'example.com',
205210
}
206211

@@ -233,10 +238,10 @@ describe('WebAuthn Serialization/Deserialization', () => {
233238

234239
const result = serializeCredentialCreationResponse(mockCredential)
235240

236-
// Verify ArrayBuffers were converted to base64url
237-
expect(result.rawId).toBe(mockCredential.id) // Now correctly converts rawId ArrayBuffer to base64url
238-
expect(result.response.attestationObject).toBe('AQIDBAU')
239-
expect(result.response.clientDataJSON).toBe('BgcICQo')
241+
242+
expect(result.rawId).toBe(mockCredential.id)
243+
expect(result.response.attestationObject).toBe('AQIDBAU')
244+
expect(result.response.clientDataJSON).toBe('BgcICQo')
240245
expect(result.authenticatorAttachment).toBe('platform')
241246
expect(result.clientExtensionResults).toEqual({ credProps: { rk: true } })
242247
})
@@ -320,12 +325,12 @@ describe('WebAuthn Serialization/Deserialization', () => {
320325

321326
const result = serializeCredentialRequestResponse(mockCredential)
322327

323-
// Verify conversions
324-
expect(result.rawId).toBe(mockCredential.id) // Now correctly converts rawId ArrayBuffer to base64url
325-
expect(result.response.authenticatorData).toBe('AQIDBAU')
326-
expect(result.response.clientDataJSON).toBe('BgcICQo')
327-
expect(result.response.signature).toBe('CwwNDg8')
328-
expect(result.response.userHandle).toBe('EBESExQ')
328+
329+
expect(result.rawId).toBe(mockCredential.id)
330+
expect(result.response.authenticatorData).toBe('AQIDBAU')
331+
expect(result.response.clientDataJSON).toBe('BgcICQo')
332+
expect(result.response.signature).toBe('CwwNDg8')
333+
expect(result.response.userHandle).toBe('EBESExQ')
329334
})
330335

331336
it('should handle null userHandle correctly', () => {
@@ -386,10 +391,10 @@ describe('WebAuthn Serialization/Deserialization', () => {
386391

387392
describe('mergeCredentialCreationOptions', () => {
388393
const baseOptions: PublicKeyCredentialCreationOptionsFuture = {
389-
challenge: new Uint8Array([1, 2, 3, 4]).buffer,
394+
challenge: new Uint8Array([67, 104, 97, 108, 108, 101, 110, 103, 101, 49, 50, 51]).buffer,
390395
rp: { name: 'Test RP', id: 'example.com' },
391396
user: {
392-
id: new Uint8Array([5, 6, 7, 8]).buffer,
397+
id: new Uint8Array([85, 115, 101, 114, 49, 50, 51]).buffer,
393398
name: 'user@example.com',
394399
displayName: 'Test User',
395400
},
@@ -399,7 +404,7 @@ describe('WebAuthn Serialization/Deserialization', () => {
399404
it('should apply DEFAULT_CREATION_OPTIONS correctly', () => {
400405
const result = mergeCredentialCreationOptions(baseOptions)
401406

402-
// Verify defaults are applied
407+
403408
expect(result.authenticatorSelection).toEqual({
404409
authenticatorAttachment: 'cross-platform',
405410
requireResidentKey: false,
@@ -409,7 +414,7 @@ describe('WebAuthn Serialization/Deserialization', () => {
409414
expect(result.hints).toEqual(['security-key'])
410415
expect(result.attestation).toBe('direct')
411416

412-
// Verify base options are preserved
417+
413418
expect(result.challenge).toBe(baseOptions.challenge)
414419
expect(result.rp).toEqual(baseOptions.rp)
415420
expect(result.user).toEqual(baseOptions.user)
@@ -422,12 +427,12 @@ describe('WebAuthn Serialization/Deserialization', () => {
422427
},
423428
})
424429

425-
// Should merge, not replace
430+
426431
expect(result.authenticatorSelection).toEqual({
427432
authenticatorAttachment: 'cross-platform',
428433
requireResidentKey: false,
429434
residentKey: 'discouraged',
430-
userVerification: 'required', // Override applied
435+
userVerification: 'required',
431436
})
432437
})
433438

@@ -454,7 +459,7 @@ describe('WebAuthn Serialization/Deserialization', () => {
454459
})
455460

456461
it('should not modify ArrayBuffer fields during merge', () => {
457-
const customChallenge = new Uint8Array([9, 10, 11, 12]).buffer
462+
const customChallenge = new Uint8Array([78, 101, 119, 67, 104, 97, 108, 108]).buffer
458463
const result = mergeCredentialCreationOptions(baseOptions, {
459464
challenge: customChallenge,
460465
})
@@ -466,11 +471,11 @@ describe('WebAuthn Serialization/Deserialization', () => {
466471

467472
describe('mergeCredentialRequestOptions', () => {
468473
const baseOptions: PublicKeyCredentialRequestOptionsFuture = {
469-
challenge: new Uint8Array([1, 2, 3, 4]).buffer,
474+
challenge: new Uint8Array([82, 101, 113, 117, 101, 115, 116]).buffer,
470475
rpId: 'example.com',
471476
allowCredentials: [
472477
{
473-
id: new Uint8Array([5, 6, 7, 8]).buffer,
478+
id: new Uint8Array([67, 114, 101, 100, 49, 50, 51]).buffer,
474479
type: 'public-key',
475480
transports: ['usb'],
476481
},
@@ -483,7 +488,7 @@ describe('WebAuthn Serialization/Deserialization', () => {
483488
expect(result.userVerification).toBe('preferred')
484489
expect(result.hints).toEqual(['security-key'])
485490

486-
// Base options preserved
491+
487492
expect(result.challenge).toBe(baseOptions.challenge)
488493
expect(result.allowCredentials).toBe(baseOptions.allowCredentials)
489494
})
@@ -503,7 +508,7 @@ describe('WebAuthn Serialization/Deserialization', () => {
503508
it('should preserve allowCredentials ArrayBuffers', () => {
504509
const newCreds = [
505510
{
506-
id: new Uint8Array([9, 10, 11, 12]).buffer,
511+
id: new Uint8Array([78, 101, 119, 67, 114, 101, 100]).buffer,
507512
type: 'public-key' as const,
508513
transports: ['nfc'] as AuthenticatorTransportFuture[],
509514
},

0 commit comments

Comments
 (0)