|
1 | 1 | /*
|
2 | 2 | * JavaScript functions for providing SAML SP with NGINX Plus
|
3 | 3 | *
|
4 |
| - * Copyright (C) 2023 Nginx, Inc. |
| 4 | + * Copyright (C) 2025 Nginx, Inc. |
5 | 5 | */
|
6 | 6 |
|
7 |
| -export default { |
8 |
| - handleSingleSignOn, // Process SAML Response form IdP |
9 |
| - handleSingleLogout, // Process SAML LogoutRequest and LogoutResponse from IdP |
10 |
| - handleAllMessages, // Process all SAML messages from IdP |
11 |
| - initiateSingleSignOn, // Initiate SAML SSO by redirecting to IdP |
12 |
| - initiateSingleLogout // Initiate SAML SLO by redirecting to IdP |
13 |
| -}; |
14 |
| - |
15 |
| -const xml = require("xml"); |
16 |
| -const zlib = require("zlib"); |
17 |
| -const querystring = require("querystring"); |
18 |
| -const fs = require("fs"); |
| 7 | +import xml from 'xml'; |
| 8 | +import zlib from 'zlib'; |
| 9 | +import querystring from 'querystring'; |
| 10 | +import fs from 'fs'; |
19 | 11 |
|
20 | 12 | const initiateSingleSignOn = produceSAMLMessage.bind(null, "AuthnRequest");
|
21 | 13 | const initiateSingleLogout = produceSAMLMessage.bind(null, "LogoutRequest");
|
@@ -124,7 +116,14 @@ async function handleSAMLMessage(messageType, r) {
|
124 | 116 | }
|
125 | 117 |
|
126 | 118 | function samlError(r, http_code, id, e) {
|
127 |
| - let msg = r.variables.saml_debug ? e.stack : "ReferenceError: " + e.message; |
| 119 | + let msg; |
| 120 | + |
| 121 | + if (r.variables.saml_debug) { |
| 122 | + msg = `ReferenceError: ${e.message}\nStack: ${e.stack}`; |
| 123 | + } else { |
| 124 | + msg = `ReferenceError: ${e.message}`; |
| 125 | + } |
| 126 | + |
128 | 127 | r.error(`SAML SSO Error: ReferenceID: ${id} ${msg}`);
|
129 | 128 |
|
130 | 129 | r.variables.internal_error_message += `ReferenceID: ${id}`;
|
@@ -1321,22 +1320,20 @@ function parseConfigurationOptions(r, messageType) {
|
1321 | 1320 | }
|
1322 | 1321 |
|
1323 | 1322 | function getEscapeXML() {
|
1324 |
| - const fpc = Function.prototype.call; |
1325 |
| - const _replace = fpc.bind(fpc, String.prototype.replace); |
1326 |
| - |
1327 |
| - const tbl = { |
1328 |
| - '<': '<', |
1329 |
| - '>': '>', |
1330 |
| - "'": ''', |
1331 |
| - '"': '"', |
1332 |
| - '&': '&', |
| 1323 | + const escapeMap = { |
| 1324 | + '<': '<', |
| 1325 | + '>': '>', |
| 1326 | + "'": ''', |
| 1327 | + '"': '"', |
| 1328 | + '&': '&' |
1333 | 1329 | };
|
1334 |
| - tbl.__proto__ = null; |
1335 | 1330 |
|
1336 |
| - return function (str) { |
1337 |
| - return _replace(str, /[<>'"&]/g, c => tbl[c]); |
1338 |
| - } |
1339 |
| -}; |
| 1331 | + return function escapeXML(str) { |
| 1332 | + if (str == null) return ''; |
| 1333 | + |
| 1334 | + return String(str).replace(/[<>'"&]/g, character => escapeMap[character]); |
| 1335 | + }; |
| 1336 | +} |
1340 | 1337 |
|
1341 | 1338 | function isUrlOrUrn(str) {
|
1342 | 1339 | const urlRegEx = /^((?:(?:https?):)\/\/)?((?:(?:[^:@]+(?::[^:@]+)?|[^:@]+@[^:@]+)(?::\d+)?)|(?:\[[a-fA-F0-9:]+]))(\/(?:[^?#]*))?(\\?(?:[^#]*))?(#(?:.*))?$/;
|
@@ -1373,3 +1370,11 @@ function readKeysFromFile(keyFile) {
|
1373 | 1370 | throw Error(`Failed to read private or public key from file "${keyFile}": ${e.message}`);
|
1374 | 1371 | }
|
1375 | 1372 | }
|
| 1373 | + |
| 1374 | +export default { |
| 1375 | + handleSingleSignOn, // Process SAML Response form IdP |
| 1376 | + handleSingleLogout, // Process SAML LogoutRequest and LogoutResponse from IdP |
| 1377 | + handleAllMessages, // Process all SAML messages from IdP |
| 1378 | + initiateSingleSignOn, // Initiate SAML SSO by redirecting to IdP |
| 1379 | + initiateSingleLogout // Initiate SAML SLO by redirecting to IdP |
| 1380 | +}; |
0 commit comments