Skip to content

Instantly share code, notes, and snippets.

@code-atom
Created September 9, 2020 10:48
Show Gist options
  • Save code-atom/791c9e161ccea98258e91b1f82a0a77d to your computer and use it in GitHub Desktop.
Save code-atom/791c9e161ccea98258e91b1f82a0a77d to your computer and use it in GitHub Desktop.
OIDC Authorization Proof Key in Postman Per-Request
var crypto = require("crypto-js");
var interval = setTimeout(function() {}, 10000);
var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad = "=";
var stsEndpoint = 'https://XX-XXX-XXX-XXX.XXX.net/ids';
var tokenEndpoint = stsEndpoint + '/connect/token';
var authorizationEndpoint = stsEndpoint + '/connect/authorize';
var loginEndpoint = stsEndpoint + '/login';
var redirectUrl = 'https://XXX-XX-XX-XXX.azurewebsites.net/sign-in';
var clientId = 'XXXX'
var clientSecret = 'XXXX';
var scopes = 'openid';
const authorizeRequest = {
scope: "scope",
responseType: "response_type",
clientId: "client_id",
redirectUri: "redirect_uri",
state: "state",
responseMode: "response_mode",
nonce: "nonce",
display: "display",
prompt: "prompt",
maxAge: "max_age",
uiLocales: "ui_locales",
idTokenHint: "id_token_hint",
loginHint: "login_hint",
acrValues: "acr_values",
codeChallenge: "code_challenge",
codeChallengeMethod: "code_challenge_method",
request: "request",
requestUri: "request_uri"
};
function addOptional(values, key, value) {
if (value) {
values[key] = value;
}
};
function objectToQuerystring(obj) {
return Object.keys(obj).reduce(function (str, key, i) {
var delimiter, val;
delimiter = (i === 0) ? '?' : '&';
key = encodeURIComponent(key);
val = encodeURIComponent(obj[key]);
return [str, delimiter, key, '=', val].join('');
}, '');
};
function uuid() {
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
(c ^ Math.random() * 16 >> c / 4).toString(16)
)
}
function random() {
return uuid().replace(/-/g, '');
}
function hexToBase64(h) {
var i;
var c;
var ret = "";
for (i = 0; i + 3 <= h.length; i += 3) {
c = parseInt(h.substring(i, i + 3), 16);
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
}
if (i + 1 === h.length) {
c = parseInt(h.substring(i, i + 1), 16);
ret += b64map.charAt(c << 2);
}
else if (i + 2 === h.length) {
c = parseInt(h.substring(i, i + 2), 16);
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
}
if (b64pad) while ((ret.length & 3) > 0) ret += b64pad;
return ret;
}
function base64ToBase64Url(s) {
s = s.replace(/=/g, "");
s = s.replace(/\+/g, "-");
s = s.replace(/\//g, "_");
return s;
}
function hextob64u(s) {
if (s.length % 2 === 1) {
s = '0' + s;
}
return base64ToBase64Url(hexToBase64(s));
}
function createAuthorizeUri(
requestUri,
clientId,
responseType,
scope,
redirectUri,
state,
responseMode,
codeChallenge,
codeChallengeMethod,
nonce,
loginHint,
acrValues,
prompt,
display,
maxAge,
uiLocales,
idTokenHint,
extra
) {
var promise = new Promise((resolve, reject) => {
var values = {};
values[authorizeRequest.clientId] = clientId;
values[authorizeRequest.responseType] = responseType;
addOptional(values, authorizeRequest.scope, scope);
addOptional(values, authorizeRequest.redirectUri, redirectUri);
addOptional(values, authorizeRequest.state, state);
addOptional(values, authorizeRequest.nonce, nonce);
addOptional(values, authorizeRequest.loginHint, loginHint);
addOptional(values, authorizeRequest.acrValues, acrValues);
addOptional(values, authorizeRequest.prompt, prompt);
addOptional(values, authorizeRequest.responseMode, responseMode);
addOptional(values, authorizeRequest.codeChallenge, codeChallenge);
addOptional(values, authorizeRequest.codeChallengeMethod, codeChallengeMethod);
addOptional(values, authorizeRequest.display, display);
addOptional(values, authorizeRequest.maxAge, maxAge);
addOptional(values, authorizeRequest.uiLocales, uiLocales);
addOptional(values, authorizeRequest.idTokenHint, idTokenHint);
var endpoint = requestUri + objectToQuerystring(values);
pm.sendRequest(endpoint, function (err, response, additional) {
if (err) {
reject(err);
}
const session = additional.cookies.filter(x => x.name === 'idsrv')[0];
const responseBody = cheerio.load(response.stream.toString());
resolve({ body: responseBody, sessionExist: !!session });
})
})
return promise;
};
function createLoginRequest(
endpoint,
username,
password,
xsfrToken,
) {
var promise = new Promise((resolve, reject) => {
const request = {
url: endpoint,
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: {
mode: 'urlencoded',
urlencoded: [
{ key: "username", value: username, disabled: false },
{ key: "password", value: password, disabled: false },
{ key: "button", value: "login", disabled: false },
{ key: "__RequestVerificationToken", value: xsfrToken, disabled: false }
]
}
};
pm.sendRequest(request, function (err, response) {
if (err) {
reject(err);
}
const responseBody = cheerio.load(response.stream.toString());
resolve(responseBody);
})
})
return promise;
}
function createTokenRequest(
endpoint,
clientId,
client_secret,
code,
redirect_uri,
code_verifier,
grant_type
) {
var promise = new Promise((resolve, reject) => {
const rm = {
url: endpoint,
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: {
mode: 'urlencoded',
urlencoded: [
{ key: "client_id", value: clientId, disabled: false },
{ key: "client_secret", value: client_secret, disabled: false },
{ key: "code", value: code, disabled: false },
{ key: "redirect_uri", value: redirect_uri, disabled: false },
{ key: "grant_type", value: grant_type, disabled: false },
{ key: "code_verifier", value: code_verifier, disabled: false }
]
}
};
pm.sendRequest(rm, function (err, response) {
if (err) {
reject(err);
}
resolve(response.json());
});
})
return promise;
}
const code_verifier = random() + random() + random();
const hash = crypto.SHA256(code_verifier).toString();
const code_challenge = hextob64u(hash);
createAuthorizeUri(
authorizationEndpoint,
clientId,
'code',
scopes,
redirectUrl,
'xyz',
'form_post',
code_challenge,
'S256'
).then((response) => {
if (response.sessionExist) {
return response.body;
}
var token = response.body('input[name="__RequestVerificationToken"]').val();
var returnUrl = response.body('input[name="ReturnUrl"]').val();
const loginRequest = loginEndpoint + '?ReturnUrl=' + encodeURIComponent(returnUrl);
return createLoginRequest(loginRequest, '[email protected]', 'password', token);
}).then(body => {
var code = body('input[name="code"]').val();
return createTokenRequest(tokenEndpoint,
clientId,
clientSecret,
code,
redirectUrl,
code_verifier,
'authorization_code')
})
.then(tokenResponse => {
console.log(tokenResponse);
})
.then((v) => {clearTimeout(interval);})
.catch(console.log)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment