Improve the mock-idp to include in respnse : InResponseTo
References #4
This commit is contained in:
parent
f17ae330d3
commit
f548a0b31e
1 changed files with 43 additions and 4 deletions
|
@ -7,6 +7,7 @@ const path = require('path');
|
||||||
const bodyParser = require('body-parser');
|
const bodyParser = require('body-parser');
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
const xml2js = require('xml2js');
|
const xml2js = require('xml2js');
|
||||||
|
const xpath = require('xpath');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 3000;
|
const port = 3000;
|
||||||
|
@ -34,12 +35,15 @@ app.get('/saml/sso', async (req, res) => {
|
||||||
storedSamlRequest = samlRequest;
|
storedSamlRequest = samlRequest;
|
||||||
storedRelayState = relayState;
|
storedRelayState = relayState;
|
||||||
|
|
||||||
|
const authnRequestId = await extractAuthnRequestId(storedSamlRequest);
|
||||||
|
console.log('SAML2 AuthnRequestId:', authnRequestId);
|
||||||
|
|
||||||
// Show simple login form
|
// Show simple login form
|
||||||
res.send(createLoginForm());
|
res.send(createLoginForm());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Step 2: Handle login form and send SAMLResponse
|
// Step 2: Handle login form and send SAMLResponse
|
||||||
app.post('/saml/login', (req, res) => {
|
app.post('/saml/login', async (req, res) => {
|
||||||
const { username, email, orgCode, securityGroup, roles } = req.body;
|
const { username, email, orgCode, securityGroup, roles } = req.body;
|
||||||
if (!storedSamlRequest) {
|
if (!storedSamlRequest) {
|
||||||
return res.status(400).send('No SAMLRequest stored');
|
return res.status(400).send('No SAMLRequest stored');
|
||||||
|
@ -60,7 +64,8 @@ app.post('/saml/login', (req, res) => {
|
||||||
console.log('ServiceProvider URL :', serviceProviderUrl);
|
console.log('ServiceProvider URL :', serviceProviderUrl);
|
||||||
console.log('ServiceProvider ACS :', acsUrl);
|
console.log('ServiceProvider ACS :', acsUrl);
|
||||||
|
|
||||||
const samlResponse = createFakeSamlResponse(username, email, orgCode, securityGroup, roles, serviceProviderUrl, issuerUrl);
|
const inResponseTo = await extractAuthnRequestId(storedSamlRequest);
|
||||||
|
const samlResponse = createFakeSamlResponse(username, email, orgCode, securityGroup, roles, serviceProviderUrl, issuerUrl, inResponseTo);
|
||||||
const relayState = storedRelayState;
|
const relayState = storedRelayState;
|
||||||
|
|
||||||
res.send(`
|
res.send(`
|
||||||
|
@ -75,7 +80,41 @@ app.post('/saml/login', (req, res) => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
function createFakeSamlResponse(nameId, email, orgCode, securityGroupCode, roles, serviceProviderUrl, issuerUrl) {
|
/**
|
||||||
|
* Extracts the AuthnRequest ID from a base64-encoded SAMLRequest.
|
||||||
|
* @param {string} samlRequest - Base64-encoded SAMLRequest parameter from the URL.
|
||||||
|
* @returns {Promise<string|null>} - Promise resolving to the AuthnRequest ID, or null if not found.
|
||||||
|
*/
|
||||||
|
function extractAuthnRequestId(samlRequest) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const decoded = Buffer.from(samlRequest, 'base64');
|
||||||
|
|
||||||
|
zlib.inflateRaw(decoded, (err, inflated) => {
|
||||||
|
if (err) return reject(new Error('Failed to inflate SAMLRequest: ' + err.message));
|
||||||
|
|
||||||
|
const xml = inflated.toString('utf8');
|
||||||
|
const doc = new DOMParser().parseFromString(xml, 'text/xml');
|
||||||
|
|
||||||
|
// Define namespace mappings for XPath
|
||||||
|
const select = xpath.useNamespaces({
|
||||||
|
saml2p: 'urn:oasis:names:tc:SAML:2.0:protocol',
|
||||||
|
});
|
||||||
|
|
||||||
|
const node = select('//saml2p:AuthnRequest', doc)[0];
|
||||||
|
if (node) {
|
||||||
|
resolve(node.getAttribute('ID'));
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFakeSamlResponse(nameId, email, orgCode, securityGroupCode, roles, serviceProviderUrl, issuerUrl, inResponseTo) {
|
||||||
const issuer = issuerUrl;
|
const issuer = issuerUrl;
|
||||||
// const audience = "https://localhost:8443/saml2/service-provider-metadata/mock-idp";
|
// const audience = "https://localhost:8443/saml2/service-provider-metadata/mock-idp";
|
||||||
const audience = serviceProviderUrl + "/saml2/service-provider-metadata/mock-idp";
|
const audience = serviceProviderUrl + "/saml2/service-provider-metadata/mock-idp";
|
||||||
|
@ -152,7 +191,7 @@ function createFakeSamlResponse(nameId, email, orgCode, securityGroupCode, roles
|
||||||
});
|
});
|
||||||
|
|
||||||
const signedAssertion = sig.getSignedXml();
|
const signedAssertion = sig.getSignedXml();
|
||||||
const samlResponse = `<?xml version="1.0" encoding="UTF-8"?><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="${responseId}" Version="2.0" IssueInstant="${now}" Destination="${destination}"><saml:Issuer>${issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>${signedAssertion}</samlp:Response>`;
|
const samlResponse = `<?xml version="1.0" encoding="UTF-8"?><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="${responseId}" Version="2.0" IssueInstant="${now}" Destination="${destination}" InResponseTo="${inResponseTo}"><saml:Issuer>${issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>${signedAssertion}</samlp:Response>`;
|
||||||
|
|
||||||
const samlResponseToUse = samlResponse.trim().replace(/^\uFEFF/, '');
|
const samlResponseToUse = samlResponse.trim().replace(/^\uFEFF/, '');
|
||||||
return Buffer.from(samlResponseToUse, 'utf-8').toString('base64');
|
return Buffer.from(samlResponseToUse, 'utf-8').toString('base64');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue