Skip to content

Commit c0eaafd

Browse files
committed
v4.0.7 - opt verify-jwt
1 parent b888b6f commit c0eaafd

File tree

6 files changed

+34
-19
lines changed

6 files changed

+34
-19
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ See [CODE_OF_CONDUCT](CODE_OF_CONDUCT.md)
6969

7070
| Version | Description
7171
|-- |--
72+
| 4.0.7 | optimized `verifyJWT()` w/ more detail error.
7273
| 4.0.6 | optimized `loadProfile()` as sync call.
7374
| 4.0.5 | improve `$protocol` w/ `lambda` invoke.
7475
| 4.0.0 | optimized with `nodejs22`.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "lemon-core",
3-
"version": "4.0.6",
3+
"version": "4.0.7",
44
"description": "Lemon Serverless Micro-Service Platform",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/cores/aws/aws-kms-service.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { GetPublicKeyCommand, EncryptCommand, DecryptCommand, VerifyCommand } fr
2323
import { EncryptCommandInput, DecryptCommandInput, GetPublicKeyCommandInput, SignCommandInput, VerifyCommandInput } from '@aws-sdk/client-kms';
2424
import { CoreKmsService } from '../core-services';
2525
import { awsConfig } from '../../tools';
26+
import { GETERR } from '../../common/test-helper';
2627
const NS = $U.NS('KMSS', 'blue'); // NAMESPACE TO BE PRINTED.
2728

2829
type MySigningAlgorithm = SigningAlgorithmSpec;
@@ -169,9 +170,11 @@ export class AWSKMSService implements CoreKmsService {
169170
* @param {*} message any string
170171
* @param {*} signature signature of Buffer or string(in base64)
171172
*/
172-
public verify = async (message: string, signature: Buffer | string): Promise<boolean> => {
173-
if (!message || typeof message !== 'string') throw new Error(`@message[${message}] is invalid - kms.verify()`);
174-
if (!signature) throw new Error(`@signature (string|Buffer) is required - kms.verify()`);
173+
public verify = async (message: string, signature: string, options?: { throwable?: boolean }): Promise<boolean> => {
174+
const errScope = `kms.verify()`;
175+
const throwable = options?.throwable ?? false;
176+
if (!message || typeof message !== 'string') throw new Error(`@message[${message}] is invalid - ${errScope}`);
177+
if (!signature) throw new Error(`@signature (string|Buffer) is required - ${errScope}`);
175178
const KeyId = this.keyId();
176179
_inf(NS, `verify(${KeyId}, ${message.substring(0, 10)}...)..`);
177180
const params: VerifyCommandInput = {
@@ -184,7 +187,8 @@ export class AWSKMSService implements CoreKmsService {
184187
const result = await this.instance()
185188
.send(new VerifyCommand(params))
186189
.catch(e => {
187-
_err(NS, `! err=`, e);
190+
if (throwable) throw e;
191+
_err(NS, `! err =`, GETERR(e), e);
188192
return null as any;
189193
});
190194
return result?.SignatureValid;

src/cores/lambda/lambda-web-handler.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,11 @@ describe('LambdaWEBHandler', () => {
161161
iat: 1652149353,
162162
...identity,
163163
});
164-
expect2(await $t.parseIdentityJWT(null).catch(GETERR)).toEqual('@token (string) is required - but object');
164+
expect2(await $t.parseIdentityJWT(null).catch(GETERR)).toEqual(
165+
'@token (string) is required (but object) - verifyJWT(http)',
166+
);
165167
expect2(await $t.parseIdentityJWT(`${expectedHead}.`).catch(GETERR)).toEqual(
166-
'@iss[null] is invalid - unsupportable issuer!',
168+
'@iss[null] is invalid (unsupportable issuer) - verifyJWT(http)',
167169
);
168170
}
169171

src/cores/lambda/lambda-web-handler.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -670,23 +670,25 @@ export class MyHttpHeaderTool implements HttpHeaderTool<APIGatewayEventRequestCo
670670
},
671671
): Promise<T> {
672672
const isVerify = params?.verify ?? true;
673+
const errScope = `verifyJWT(http)`;
673674

674675
//* it must be JWT Token. verify signature, and load.
675-
if (typeof token !== 'string' || !token) throw new Error(`@token (string) is required - but ${typeof token}`);
676+
if (typeof token !== 'string' || !token)
677+
throw new Error(`@token (string) is required (but ${typeof token}) - ${errScope}`);
676678
// STEP.1 decode jwt, and extract { iss, iat, exp }
677679
const current = params?.current ?? $U.current_time_ms();
678680
const sections = token.split('.');
679-
if (sections.length !== 3) throw new Error(`@token[${token}] is invalid format!`);
681+
if (sections.length !== 3) throw new Error(`@token[${token}] is invalid (format) - ${errScope}`);
680682
const [header, payload, signature] = sections;
681683
const $jwt = $U.jwt();
682684
const data = $jwt.decode(token, { complete: false, json: true });
683-
if (!data) throw new Error(`@token[${token}] is invalid - failed to decode!`);
685+
if (!data) throw new Error(`@token[${token}] is invalid (failed to decode) - ${errScope}`);
684686
const { iss, iat, exp } = data;
685687

686688
// STEP.1-1 validate parameters.
687-
if (typeof iss !== 'string' && iss !== null) throw new Error(`.iss (string) is required!`);
688-
if (typeof iat !== 'number' && iat !== null) throw new Error(`.iat (number) is required!`);
689-
if (typeof exp !== 'number' && exp !== null) throw new Error(`.exp (number) is required!`);
689+
if (typeof iss !== 'string' && iss !== null) throw new Error(`.iss (string) is required - ${errScope}`);
690+
if (typeof iat !== 'number' && iat !== null) throw new Error(`.iat (number) is required - ${errScope}`);
691+
if (typeof exp !== 'number' && exp !== null) throw new Error(`.exp (number) is required - ${errScope}`);
690692

691693
// STEP.2 validate signature by KMS(iss).verify()
692694
//TODO - iss 에 인증제공자의 api 넣기 (ex: api/lemon-backend-dev?)
@@ -697,13 +699,19 @@ export class MyHttpHeaderTool implements HttpHeaderTool<APIGatewayEventRequestCo
697699
} else if (typeof iss === 'string' && iss.startsWith('kms/')) {
698700
const alias = _alias(iss);
699701
const $kms = alias ? this.findKMSService(`alias/${alias}`) : null;
700-
const verified = $kms ? await $kms.verify([header, payload].join('.'), signature) : false;
701-
if (!verified) throw new Error(`@signature[] is invalid - not be verified by iss:${iss}!`);
702-
if (!exp || exp * 1000 < current) throw new Error(`.exp[${$U.ts(exp * 1000)}] is invalid - expired!`);
702+
const message = [header, payload].join('.');
703+
const verified = $kms
704+
? await $kms.verify(message, signature, { throwable: true }).catch(e => {
705+
throw new Error(`@signature[] is invalid (kms: ${GETERR(e)}) - ${errScope}`);
706+
})
707+
: false;
708+
if (!verified) throw new Error(`@signature[] is invalid (failed to verify by iss:${iss}) - ${errScope}`);
709+
if (!exp) throw new Error(`.exp[${exp}] is invalid (empty) - ${errScope}`);
710+
if (exp * 1000 < current) throw new Error(`.exp[${$U.ts(exp * 1000)}] is invalid (expired) - ${errScope}`);
703711
return data as T;
704712
}
705713
//* or throw
706-
throw new Error(`@iss[${iss}] is invalid - unsupportable issuer!`);
714+
throw new Error(`@iss[${iss}] is invalid (unsupportable issuer) - ${errScope}`);
707715
}
708716

709717
/**

0 commit comments

Comments
 (0)