-
-
Notifications
You must be signed in to change notification settings - Fork 313
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
109 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { decode as base64url } from './base64url.js' | ||
import { decoder } from '../lib/buffer_utils.js' | ||
import isObject from '../lib/is_object.js' | ||
import type { JWTPayload } from '../types.d' | ||
import { JWTInvalid } from './errors.js' | ||
|
||
/** | ||
* Decodes a signed JSON Web Token payload. This does not validate the JWT Claims Set | ||
* types or values. This does not validate the JWS Signature. For a proper | ||
* Signed JWT Claims Set validation and JWS signature verification use `jose.jwtVerify()`. | ||
* For an encrypted JWT Claims Set validation and JWE decryption use `jose.jwtDecrypt()`. | ||
* | ||
* @param jwt JWT token in compact JWS serialization. | ||
* | ||
* @example Usage | ||
* ```js | ||
* const claims = jose.decodeJwt(token) | ||
* console.log(claims) | ||
* ``` | ||
*/ | ||
export function decodeJwt(jwt: string) { | ||
if (typeof jwt !== 'string') | ||
throw new JWTInvalid('JWTs must use Compact JWS serialization, JWT must be a string') | ||
|
||
const { 1: payload, length } = jwt.split('.') | ||
|
||
if (length === 5) throw new JWTInvalid('Only JWTs using Compact JWS serialization can be decoded') | ||
if (length !== 3) throw new JWTInvalid('Invalid JWT') | ||
if (!payload) throw new JWTInvalid('JWTs must contain a payload') | ||
|
||
let decoded: Uint8Array | ||
try { | ||
decoded = base64url(payload) | ||
} catch { | ||
throw new JWTInvalid('Failed to parse the base64url encoded payload') | ||
} | ||
|
||
let result: unknown | ||
try { | ||
result = JSON.parse(decoder.decode(decoded)) | ||
} catch { | ||
throw new JWTInvalid('Failed to parse the decoded payload as JSON') | ||
} | ||
|
||
if (!isObject<JWTPayload>(result)) throw new JWTInvalid('Invalid JWT Claims Set') | ||
|
||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import test from 'ava' | ||
|
||
const root = !('WEBCRYPTO' in process.env) ? '#dist' : '#dist/webcrypto' | ||
const { decodeJwt, errors, base64url } = await import(root) | ||
|
||
test('invalid inputs', (t) => { | ||
const jwt = | ||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c' | ||
|
||
const parts = jwt.split('.') | ||
|
||
t.throws(() => decodeJwt(null), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'JWTs must use Compact JWS serialization, JWT must be a string', | ||
}) | ||
|
||
t.throws(() => decodeJwt('....'), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'Only JWTs using Compact JWS serialization can be decoded', | ||
}) | ||
|
||
t.throws(() => decodeJwt('.'), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'Invalid JWT', | ||
}) | ||
|
||
t.throws(() => decodeJwt([parts[0], '', parts[2]].join('.')), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'JWTs must contain a payload', | ||
}) | ||
|
||
t.throws(() => decodeJwt([parts[0], base64url.encode('null'), parts[2]].join('.')), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'Invalid JWT Claims Set', | ||
}) | ||
|
||
t.throws(() => decodeJwt([parts[0], base64url.encode('[]'), parts[2]].join('.')), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'Invalid JWT Claims Set', | ||
}) | ||
|
||
t.throws(() => decodeJwt([parts[0], base64url.encode('{"notajson'), parts[2]].join('.')), { | ||
instanceOf: errors.JWTInvalid, | ||
message: 'Failed to parse the decoded payload as JSON', | ||
}) | ||
|
||
t.deepEqual(decodeJwt([parts[0], base64url.encode('{}'), parts[2]].join('.')), {}) | ||
|
||
t.deepEqual(decodeJwt(jwt), { | ||
sub: '1234567890', | ||
name: 'John Doe', | ||
iat: 1516239022, | ||
}) | ||
}) |