Last active
February 13, 2020 09:02
-
-
Save oddlyfunctional/e9448ead07cb7bd72be7d91925851da8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* | |
* Usage: | |
$ node decode.js https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO?SAMLRequest=nVPBjtowEP2VyPckNgvqyiKsKKgq0rYbkWwPe6mMMyxuEzv1THbp39cJUNFqlwOnWDPPzzPvvUzv9k0dvYBH42zGRMLZ3WyKqqlbOe9oZ9fwqwOkKMAsyqGRsc5b6RQalFY1gJK0LOZf7uUo4bL1jpx2NYvmiOAp8C6cxa4BX4B%2FMRoe1%2FcZ2xG1KNOUAnmMrUie1c%2FOGptYYxKlkx9tWuzMZuNqoF2C6NL%2BhVGaPxQli5bhlrGKhqH%2FoTLVm1yhnIbJtqaGI9EaKuNBU1oUDyxaLTP2XUy4vp2Mt2IrPqgbzicCbkMLsYOVRVKWMjbiIx5zEd%2FwUnApxnLEk8l48sSi%2FLj4R2MrY58vq7Q5gFB%2BLss8Piz17eRCALCDCXJ43J%2Bpf5lWnSRns%2F8EjkWiXecRNgohHKfpGf%2FJ8a%2BBcLXMXW3072sc%2F%2BR8o%2Bgyuq%2BYKt4OUNn2OyOBpZCXunavCw%2BKIGPkO2DpabBjCqEaMhnyRLC%2FKpML17TKG%2Bxlhr3SdBL6nHhRBx3XsL1G9oswLXVPHcp5%2BLw6X%2FWhCSGEqvTKYus8HY15a57ZofeOHH%2B75%2F%2Ft7A8%3D | |
<?xml version="1.0"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://test-sp1.gakunin.nii.ac.jp/Shibboleth.sso/SAML2/POST" Destination="https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO" ID="_150c854f1f17a30051e8" IssueInstant="2020-01-30T10:14:20.545Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://test-sp-1.coursebase.co</saml:Issuer><samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" AllowCreate="true"/><samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"><saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest> | |
*/ | |
const zlib = require('zlib'); | |
const decode = url => | |
zlib.inflateRawSync( | |
Buffer.from( | |
new URL(url).searchParams.get('SAMLRequest'), | |
"base64" | |
) | |
).toString(); | |
console.log(decode(process.argv[2])); |
This file contains hidden or 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
/* | |
* Usage: | |
* node decodeResponse.js pathToBase64EncodedSamlResponse pathToCoursebaseDecryptionPrivateKey | |
*/ | |
const xmlenc = require('xml-encryption'); | |
const xmldom = require('xmldom'); | |
const xpath = require('xml-crypto').xpath; | |
const fs = require('fs'); | |
const encoded = fs.readFileSync(process.argv[2]).toString(); | |
const xml = Buffer.from(encoded, 'base64').toString('utf8'); | |
const doc = new xmldom.DOMParser({}).parseFromString(xml); | |
const encryptedAssertions = xpath(doc, | |
"/*[local-name()='Response']/*[local-name()='EncryptedAssertion']"); | |
const options = { | |
key: fs.readFileSync(process.argv[3]), | |
}; | |
xmlenc.decrypt(encryptedAssertions[0].toString(), options, function(err, decryptedXml) { | |
if (err) { throw err; } | |
const decryptedDoc = new xmldom.DOMParser().parseFromString(decryptedXml); | |
doc.replaceChild(decryptedDoc, encryptedAssertions[0]); | |
console.log(doc.toString()); | |
}); |
This file contains hidden or 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
/* | |
Our original request: | |
<?xml version="1.0"?> | |
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_f6c1d5e36096162b95f7" Version="2.0" IssueInstant="2020-01-30T11:07:01.783Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO" AssertionConsumerServiceURL="https://test.coursebase.co/sso/saml"> | |
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://test.coursebase.co</saml:Issuer> | |
<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" AllowCreate="true" /> | |
<samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"> | |
<saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> | |
</samlp:RequestedAuthnContext> | |
</samlp:AuthnRequest> | |
Their original request: | |
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://test-sp1.gakunin.nii.ac.jp/Shibboleth.sso/SAML2/POST" Destination="https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO" ID="_db7c7f8e5fde425700f947b7837d743b" IssueInstant="2020-01-30T09:38:49Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"> | |
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://test-sp1.gakunin.nii.ac.jp/shibboleth-sp</saml:Issuer> | |
<samlp:NameIDPolicy AllowCreate="1" /> | |
</samlp:AuthnRequest> | |
*/ | |
// Below, their original request was edited the closest possible to our's. | |
// Everything matches, except the `AssertionConsumerServiceURL` and the | |
// `saml:Issuer`. Note that the `ID` and `IssueInstant` attributes must be | |
// dynamically generated, therefore they are instead defined here as templates | |
// to be replaced at the moment of usage. | |
const makeXml = ({ AssertionConsumerServiceURL, Issuer }) => ` | |
<?xml version="1.0"?> | |
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="%ID%" Version="2.0" IssueInstant="%NOW%" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Destination="https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO" AssertionConsumerServiceURL="${AssertionConsumerServiceURL}"> | |
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${Issuer}</saml:Issuer> | |
<samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" AllowCreate="true" /> | |
<samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact"> | |
<saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> | |
</samlp:RequestedAuthnContext> | |
</samlp:AuthnRequest> | |
`; | |
const coursebaseSetup = { | |
AssertionConsumerServiceURL: 'https://test.coursebase.co/sso/saml', | |
Issuer: 'https://test.coursebase.co', | |
}; | |
const gakuninSetup = { | |
AssertionConsumerServiceURL: 'https://test-sp1.gakunin.nii.ac.jp/Shibboleth.sso/SAML2/POST', | |
Issuer: 'https://test-sp1.gakunin.nii.ac.jp/shibboleth-sp', | |
}; | |
let xml = makeXml(gakuninSetup); | |
// To test how the idP respond when we replace our `Issuer` and `AssertionConsumerServiceURL`, uncomment the line below | |
// xml = makeXml(coursebaseSetup); | |
const minify = xml => xml.replace(/\n\s*/g, ""); | |
const zlib = require('zlib'); | |
const nanoid = require('nanoid/generate'); | |
const makeId = () => '_' + nanoid('1234567890abcdef', 20); | |
const encode = xml => | |
zlib.deflateRawSync( | |
Buffer.from( | |
minify(xml) | |
.replace(/%NOW%/g, new Date().toISOString()) | |
.replace(/%ID%/, makeId()), | |
"utf-8" | |
) | |
).toString("base64"); | |
const makeUrl = saml => { | |
const url = new URL('https://test-idp1.gakunin.nii.ac.jp/idp/profile/SAML2/Redirect/SSO'); | |
url.searchParams.set("SAMLRequest", saml); | |
return url.toString(); | |
}; | |
const { exec } = require('child_process'); | |
console.log("SAMLRequest:"); | |
console.log(xml); | |
const url = makeUrl(encode(xml)); | |
console.log("URL:", url); | |
exec(`open "${url}"`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment