Skip to content

Commit 239eefb

Browse files
committed
feat: wrap inflation errors
`pako` has a tendency to throw obscure error strings e.g. "too many length or distance symbols", which can make gracefully handling bad input difficult when an error is thrown from `parseLoginRequest`. This wraps the inflation step to allow throwing a dedicated error with a static message for inflation issues, while still making the original error available.
1 parent 2d124fe commit 239eefb

3 files changed

Lines changed: 23 additions & 11 deletions

File tree

src/flow.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { inflateString, base64Decode, isNonEmptyArray } from './utility';
1+
import { inflateString, base64Decode, WrappedError } from './utility';
22
import { verifyTime } from './validator';
33
import libsaml from './libsaml';
44
import {
@@ -68,7 +68,13 @@ async function redirectFlow(options): Promise<FlowResult> {
6868
return Promise.reject('ERR_REDIRECT_FLOW_BAD_ARGS');
6969
}
7070

71-
const xmlString = inflateString(decodeURIComponent(content));
71+
let xmlString: string
72+
73+
try {
74+
xmlString = inflateString(decodeURIComponent(content));
75+
} catch (e) {
76+
throw new WrappedError('ERR_FAILED_INFLATION', e)
77+
}
7278

7379
// validate the xml
7480
try {

src/libsaml.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ const libSaml = () => {
175175
context: '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" InResponseTo="{InResponseTo}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="{StatusCode}"/></samlp:Status><saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{AssertionID}" Version="2.0" IssueInstant="{IssueInstant}"><saml:Issuer>{Issuer}</saml:Issuer><saml:Subject><saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="{SubjectConfirmationDataNotOnOrAfter}" Recipient="{SubjectRecipient}" InResponseTo="{InResponseTo}"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="{ConditionsNotBefore}" NotOnOrAfter="{ConditionsNotOnOrAfter}"><saml:AudienceRestriction><saml:Audience>{Audience}</saml:Audience></saml:AudienceRestriction></saml:Conditions>{AuthnStatement}{AttributeStatement}</saml:Assertion></samlp:Response>',
176176
attributes: [],
177177
additionalTemplates: {
178-
"attributeStatementTemplate": defaultAttributeStatementTemplate,
179-
"attributeTemplate": defaultAttributeTemplate
178+
'attributeStatementTemplate': defaultAttributeStatementTemplate,
179+
'attributeTemplate': defaultAttributeTemplate
180180
}
181181
};
182182
/**

src/utility.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,20 @@ import { inflate, deflate } from 'pako';
88

99
const BASE64_STR = 'base64';
1010

11+
export class WrappedError extends Error {
12+
constructor(message: string, public readonly originalErr: unknown) {
13+
super(message);
14+
}
15+
}
16+
1117
/**
1218
* @desc Mimic lodash.zipObject
1319
* @param arr1 {string[]}
1420
* @param arr2 {[]}
1521
*/
1622
export function zipObject(arr1: string[], arr2: any[], skipDuplicated = true) {
1723
return arr1.reduce((res, l, i) => {
18-
24+
1925
if (skipDuplicated) {
2026
res[l] = arr2[i];
2127
return res;
@@ -61,19 +67,19 @@ export function uniq(input: string[]) {
6167
return [... set];
6268
}
6369
/**
64-
* @desc Alternative to lodash.get
70+
* @desc Alternative to lodash.get
6571
* @reference https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_get
66-
* @param obj
67-
* @param path
68-
* @param defaultValue
72+
* @param obj
73+
* @param path
74+
* @param defaultValue
6975
*/
7076
export function get(obj, path, defaultValue) {
7177
return path.split('.')
7278
.reduce((a, c) => (a && a[c] ? a[c] : (defaultValue || null)), obj);
7379
}
7480
/**
75-
* @desc Check if the input is string
76-
* @param {any} input
81+
* @desc Check if the input is string
82+
* @param {any} input
7783
*/
7884
export function isString(input: any) {
7985
return typeof input === 'string';

0 commit comments

Comments
 (0)