lawnet-singapore-student
Version:
Library to login and download cases from LawNet for students in Singapore law schools.
459 lines (458 loc) • 37.9 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.login = exports.LOGOUT_REDIRECT_URL_2 = exports.LOGOUT_REDIRECT_URL = exports.LOGOUT_REDIRECT_SCRIPT_2 = exports.LOGOUT_REDIRECT_SCRIPT = exports.FIRST_URL = void 0;
const axios_1 = __importDefault(require("axios"));
exports.FIRST_URL = {
SMU: 'https://www-lawnet-sg.libproxy.smu.edu.sg',
NUS: 'https://www-lawnet-sg.libproxy1.nus.edu.sg'
};
const SMU_LIBPROXY_URL = 'http://libproxy.smu.edu.sg/login?url=https://www.lawnet.sg/lawnet/web/lawnet/ip-access';
const SMU_ADFS_LOGIN_PAGE = 'https://login2.smu.edu.sg/adfs/ls/';
const SMU_ADFS_LOGIN_PAGE_ROOT = 'https://login2.smu.edu.sg';
const SMU_SHIBBOLETH_SSO_URL = 'https://login.libproxy.smu.edu.sg:443/Shibboleth.sso/SAML2/POST';
const SMU_INCORRECT_USER_ID_OR_PASSWORD = 'Incorrect user ID or password. Type the correct user ID and password, and try again.';
const SMU_RESET_PASSWORD_URL = 'https://smu.sg/password';
const NUS_LOGIN_URL = 'https://libproxy1.nus.edu.sg/login';
const NUS_LAWNET_URL = 'https://www.lawnet.sg/lawnet/ip-access';
const NUS_VAFS_LOGIN_PAGE = 'https://vafs.nus.edu.sg/adfs/ls/';
const NUS_VAFS_ALTERNATE_LOGIN_PAGE = 'https://vafs.u.nus.edu/adfs/ls/';
const NUS_VAFS_PREFIX = 'https://vafs.nus.edu.sg';
const NUS_VAFS_ALTERNATE_PREFIX = 'https://vafs.u.nus.edu';
const NUS_LAWPROXY_URL = 'https://www-lawnet-sg.libproxy1.nus.edu.sg/lawnet/group/lawnet/legal-research/basic-search';
const NUS_IP_ACCESS_URL = 'http://www.lawnet.sg/lawnet/ip-access';
const NUS_LOGIN_FORM_URL = 'https://proxylogin.nus.edu.sg/libproxy1/public/login_form.asp';
const NUS_INCORRECT_USER_ID_OR_PASSWORD = 'We are unable to authenticate the Userid and password that was entered. The Domain, NUSNET ID or the password entered could be invalid / mistyped.';
const NUS_OTHER_INCORRECT_USER_ID_OR_PASSWORD = 'Incorrect user ID or password. Type the correct user ID and password, and try again.';
const NUS_HELPDESK_URL = 'http://www.nus.edu.sg/comcen/gethelp';
const DUPLICATE_LOGIN = '<div>Multiple logins with the same User ID are not allowed.</div> <div>To terminate the earlier session, please click on the Remove Button.</div> <div><br><br></div> <div>Sharing of User ID is prohibited. Legal action will be taken if access is unauthorised.</div>';
const DUPLICATE_LOGIN_REMOVE_URL = '/lawnet/group/lawnet/duplicate-login?p_p_id=lawnetuniquelogin_WAR_lawnet3portalportlet&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-2&p_p_col_count=1&_lawnetuniquelogin_WAR_lawnet3portalportlet_loginType=old&_lawnetuniquelogin_WAR_lawnet3portalportlet_javax.portlet.action=removeOldLogin';
exports.LOGOUT_REDIRECT_SCRIPT = '<script type="text/javascript">location.href="\\x2flawnet\\x2fweb\\x2flawnet\\x2fhome";</script>';
exports.LOGOUT_REDIRECT_SCRIPT_2 = '<script type="text/javascript">location.href="\\x2flawnet\\x2fc";</script>';
exports.LOGOUT_REDIRECT_URL = '/lawnet/web/lawnet/home';
exports.LOGOUT_REDIRECT_URL_2 = '/lawnet/c';
function followRedirects(response, localAxios, corsPrefix) {
return __awaiter(this, void 0, void 0, function* () {
while (response.status >= 300 && response.status < 400) {
let locationCaseSensitive = '';
for (let i in response.headers) {
if (i.toLowerCase() === 'location')
locationCaseSensitive = i;
}
if (!locationCaseSensitive)
throw new Error('Redirect without location header');
let location = response.headers[locationCaseSensitive];
if (corsPrefix && !location.startsWith(corsPrefix))
location = corsPrefix + location;
response = yield localAxios.get(location, { responseType: 'document' });
}
return response;
});
}
function loginSMU(username, password, corsPrefix, domain, localAxios) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29;
return __awaiter(this, void 0, void 0, function* () {
let libproxyPage = yield followRedirects(yield localAxios.get(corsPrefix + SMU_LIBPROXY_URL, { responseType: 'document' }), localAxios, corsPrefix);
// EDIT: added this short circuit to prevent relogin attempt
if ((_b = (_a = libproxyPage === null || libproxyPage === void 0 ? void 0 : libproxyPage.data) === null || _a === void 0 ? void 0 : _a.querySelector('li.userInfo')) === null || _b === void 0 ? void 0 : _b.innerHTML.includes('Welcome User IP Access')) {
// console.log(libproxyPage?.data?.documentElement?.outerHTML);
console.log('User already logged in');
return localAxios;
}
let libproxyAction = (_d = (_c = libproxyPage === null || libproxyPage === void 0 ? void 0 : libproxyPage.data) === null || _c === void 0 ? void 0 : _c.querySelector('form[name="EZproxyForm"]')) === null || _d === void 0 ? void 0 : _d.getAttribute('action');
if (!libproxyAction) {
// console.log(libproxyPage?.data?.documentElement?.outerHTML);
throw new Error('No EZproxyForm on SMU login page');
}
let samlRequest = (_f = (_e = libproxyPage === null || libproxyPage === void 0 ? void 0 : libproxyPage.data) === null || _e === void 0 ? void 0 : _e.querySelector('input[name="SAMLRequest"]')) === null || _f === void 0 ? void 0 : _f.getAttribute('value');
if (!samlRequest)
throw new Error('No SAMLRequest on SMU login page');
let relayState = (_h = (_g = libproxyPage === null || libproxyPage === void 0 ? void 0 : libproxyPage.data) === null || _g === void 0 ? void 0 : _g.querySelector('input[name="RelayState"]')) === null || _h === void 0 ? void 0 : _h.getAttribute('value');
if (!relayState)
throw new Error('No RelayState on SMU login page');
// if(!samlRequest||!relayState)return localAxios; //already authenticated
let params = new URLSearchParams();
params.append('SAMLRequest', samlRequest);
params.append('RelayState', relayState);
//params.append('back','2');
let microsoftLoginPage = yield followRedirects(yield localAxios.post(corsPrefix + libproxyAction, params, { responseType: 'document' }), localAxios, corsPrefix);
let hiddenformRedirectSMU;
if (!((_j = microsoftLoginPage === null || microsoftLoginPage === void 0 ? void 0 : microsoftLoginPage.data) === null || _j === void 0 ? void 0 : _j.querySelector('form[name="hiddenform"][action]'))) {
//wrong username clause to be added
let originalRequest = '';
let flowToken = '';
let urlGetCredentialType = '';
let isOtherIdpSupported;
let checkPhones;
let isRemoteNGCSupported;
let isCookieBannerShown;
let isFidoSupported;
let country = '';
let forceotclogin;
let isExternalFederationDisallowed;
let isRemoteConnectSupported;
let federationFlags = 0;
let isSignup;
let isAccessPassSupported;
let isQrCodePinSupported;
do {
const microsoftDocument = microsoftLoginPage === null || microsoftLoginPage === void 0 ? void 0 : microsoftLoginPage.data;
const scriptTags = microsoftDocument.querySelectorAll('script');
if (!scriptTags || scriptTags.length <= 0)
throw new Error('No Script tag found in Microsoft HTML');
let configObject;
for (let scriptTag of scriptTags) {
if (!scriptTag.textContent)
continue;
//Declaring variables for extracting out of Script and Config
if (scriptTag && scriptTag.textContent) {
const scriptContent = scriptTag.textContent;
const configMatch = scriptContent.match(/\$Config\s*=\s*(\{[\s\S]*?\});/);
if (configMatch && configMatch[1]) {
configObject = JSON.parse(configMatch[1]);
originalRequest = configObject.sCtx;
flowToken = configObject.sFT;
urlGetCredentialType = configObject.urlGetCredentialType;
isOtherIdpSupported = true;
checkPhones = true;
isRemoteNGCSupported = configObject.fIsRemoteNGCSupported;
isCookieBannerShown = false;
isFidoSupported = true; //sometimes dissapears
country = configObject.country;
forceotclogin = false;
isExternalFederationDisallowed = false;
isRemoteConnectSupported = false;
isSignup = false;
isAccessPassSupported = configObject.fAccessPassSupported;
isQrCodePinSupported = configObject.fIsQrCodePinSupported;
if (originalRequest && flowToken && urlGetCredentialType && isRemoteNGCSupported && country && isAccessPassSupported && isQrCodePinSupported)
break;
}
}
}
if (!configObject)
throw new Error('Failed to extract $Config object from the script content.');
if (!originalRequest) {
let libproxyActionHost = libproxyAction.substring(0, libproxyAction.indexOf('/', libproxyAction.indexOf('://') + 3));
params = new URLSearchParams();
if (!configObject.oPostParams)
throw new Error('No oPostParams in $Config');
for (let i in configObject.oPostParams) {
params.append(i, configObject.oPostParams[i]);
}
if (!configObject.urlPost)
throw new Error('No urlPost in $Config');
microsoftLoginPage = yield followRedirects(yield localAxios.post(corsPrefix + libproxyActionHost + configObject.urlPost, params, { responseType: 'document' }), localAxios, corsPrefix);
}
} while (!originalRequest);
if (!flowToken)
throw new Error('No flowToken found in Microsoft HTML');
if (!urlGetCredentialType)
throw new Error('No urlGetCredentialType found in Microsoft HTML');
if (!isRemoteNGCSupported)
throw new Error('No isRemoteNGCSupported found in Microsoft HTML');
if (!country)
throw new Error('No country found in Microsoft HTML');
if (!isAccessPassSupported)
throw new Error('No isAccessPassSupported found in Microsoft HTML');
if (!isQrCodePinSupported)
throw new Error('No isQrCodePinSupported found in Microsoft HTML');
let jsonParams = {
username,
isOtherIdpSupported,
checkPhones,
isRemoteNGCSupported,
isCookieBannerShown,
isFidoSupported,
originalRequest,
country,
forceotclogin,
isExternalFederationDisallowed,
isRemoteConnectSupported,
federationFlags,
isSignup,
flowToken,
isAccessPassSupported,
isQrCodePinSupported
};
let getCredentialRedirect = yield followRedirects(yield localAxios.post(corsPrefix + urlGetCredentialType, jsonParams, {
responseType: 'json'
}), localAxios, corsPrefix);
let redirectSMULoginForm = (_l = (_k = getCredentialRedirect === null || getCredentialRedirect === void 0 ? void 0 : getCredentialRedirect.data) === null || _k === void 0 ? void 0 : _k.Credentials) === null || _l === void 0 ? void 0 : _l.FederationRedirectUrl;
//FederationRedirectUrl will be inside GetCredentialType if microsoft email is correct
if (!redirectSMULoginForm)
throw new Error('Invalid email, please try again.');
//On to SMU login
params = new URLSearchParams();
params.append('UserName', username);
params.append('Password', password);
params.append('AuthMethod', 'FormsAuthentication');
hiddenformRedirectSMU = yield followRedirects(yield localAxios.post(corsPrefix + redirectSMULoginForm, params, { responseType: 'document' }), localAxios, corsPrefix);
}
else {
hiddenformRedirectSMU = microsoftLoginPage;
}
//proxy fix starts here
params = new URLSearchParams();
if ((_p = (_o = (_m = hiddenformRedirectSMU === null || hiddenformRedirectSMU === void 0 ? void 0 : hiddenformRedirectSMU.data) === null || _m === void 0 ? void 0 : _m.documentElement) === null || _o === void 0 ? void 0 : _o.outerHTML) === null || _p === void 0 ? void 0 : _p.includes(SMU_INCORRECT_USER_ID_OR_PASSWORD))
throw new Error('Invalid email or password. Too many wrong attempts will result in your account being locked. If in doubt, <a href="javascript:window.open(\'' + SMU_RESET_PASSWORD_URL + '\',\'_system\');">reset password here</a>.');
let hiddenform = (_r = (_q = hiddenformRedirectSMU === null || hiddenformRedirectSMU === void 0 ? void 0 : hiddenformRedirectSMU.data) === null || _q === void 0 ? void 0 : _q.querySelector('form[name="hiddenform"]')) === null || _r === void 0 ? void 0 : _r.getAttribute('action');
if (!hiddenform)
throw new Error('No intermediate hiddenform for SMU');
let wa = (_t = (_s = hiddenformRedirectSMU === null || hiddenformRedirectSMU === void 0 ? void 0 : hiddenformRedirectSMU.data) === null || _s === void 0 ? void 0 : _s.querySelector('input[name="wa"]')) === null || _t === void 0 ? void 0 : _t.getAttribute('value');
if (!wa)
throw new Error('No intermediate wa for SMU');
let wresult = (_v = (_u = hiddenformRedirectSMU === null || hiddenformRedirectSMU === void 0 ? void 0 : hiddenformRedirectSMU.data) === null || _u === void 0 ? void 0 : _u.querySelector('input[name="wresult"]')) === null || _v === void 0 ? void 0 : _v.getAttribute('value');
if (!wresult)
throw new Error('No intermediate wresult for SMU');
let wctx = (_x = (_w = hiddenformRedirectSMU === null || hiddenformRedirectSMU === void 0 ? void 0 : hiddenformRedirectSMU.data) === null || _w === void 0 ? void 0 : _w.querySelector('input[name="wctx"]')) === null || _x === void 0 ? void 0 : _x.getAttribute('value');
if (!wctx)
throw new Error('No intermediate wctx for SMU');
params.append('wa', wa);
params.append('wresult', wresult);
params.append('wctx', wctx);
let shibbolethRedirectSMU = yield followRedirects(yield localAxios.post(corsPrefix + hiddenform, params, { responseType: 'document' }), localAxios, corsPrefix);
let shibbolethFormActionSMU = (_z = (_y = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _y === void 0 ? void 0 : _y.querySelector('form[name="hiddenform"][action]')) === null || _z === void 0 ? void 0 : _z.getAttribute('action');
let shibbolethSAMLResponseSMU = (_1 = (_0 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _0 === void 0 ? void 0 : _0.querySelector('input[name="SAMLResponse"]')) === null || _1 === void 0 ? void 0 : _1.getAttribute('value');
let shibbolethRelayStateSMU = (_3 = (_2 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _2 === void 0 ? void 0 : _2.querySelector('input[name="RelayState"]')) === null || _3 === void 0 ? void 0 : _3.getAttribute('value');
if (!shibbolethFormActionSMU) {
do {
const microsoftDocument = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data;
const scriptTags = microsoftDocument.querySelectorAll('script');
if (!scriptTags || scriptTags.length <= 0)
throw new Error('No Script tag found in Microsoft HTML');
let configObject;
for (let scriptTag of scriptTags) {
if (!scriptTag.textContent)
continue;
//Declaring variables for extracting out of Script and Config
if (scriptTag && scriptTag.textContent) {
const scriptContent = scriptTag.textContent;
const configMatch = scriptContent.match(/\$Config\s*=\s*(\{[\s\S]*?\});/);
if (configMatch && configMatch[1]) {
configObject = JSON.parse(configMatch[1]);
}
}
}
if (!configObject) {
shibbolethSAMLResponseSMU = (_5 = (_4 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _4 === void 0 ? void 0 : _4.querySelector('input[name="SAMLRequest"]')) === null || _5 === void 0 ? void 0 : _5.getAttribute('value');
shibbolethRelayStateSMU = (_7 = (_6 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _6 === void 0 ? void 0 : _6.querySelector('input[name="RelayState"]')) === null || _7 === void 0 ? void 0 : _7.getAttribute('value');
if (!shibbolethSAMLResponseSMU || !shibbolethRelayStateSMU)
throw new Error('Failed to extract $Config object from the script content.');
}
if (!shibbolethFormActionSMU) {
let hiddenformHost = 'https://login.libproxy.smu.edu.sg/'; //hiddenform.substring(0,hiddenform.indexOf('/',hiddenform.indexOf('://')+3));
params = new URLSearchParams();
if (!configObject.oPostParams && !configObject.urlResume)
throw new Error('No oPostParams or urlResume in $Config');
if (configObject.oPostParams) {
for (let i in configObject.oPostParams) {
params.append(i, configObject.oPostParams[i]);
}
if (!configObject.urlPost)
throw new Error('No urlPost in $Config');
shibbolethRedirectSMU = yield followRedirects(yield localAxios.post(corsPrefix + hiddenformHost + configObject.urlPost, params, { responseType: 'document' }), localAxios, corsPrefix);
}
if (configObject.urlResume) {
let urlResume = configObject.urlResume;
shibbolethRedirectSMU = yield followRedirects(yield localAxios.get(corsPrefix + urlResume, { responseType: 'document' }), localAxios, corsPrefix);
}
}
shibbolethFormActionSMU = (_9 = (_8 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _8 === void 0 ? void 0 : _8.querySelector('form[name="hiddenform"][action]')) === null || _9 === void 0 ? void 0 : _9.getAttribute('action');
shibbolethSAMLResponseSMU = (_11 = (_10 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _10 === void 0 ? void 0 : _10.querySelector('input[name="SAMLResponse"]')) === null || _11 === void 0 ? void 0 : _11.getAttribute('value');
shibbolethRelayStateSMU = (_13 = (_12 = shibbolethRedirectSMU === null || shibbolethRedirectSMU === void 0 ? void 0 : shibbolethRedirectSMU.data) === null || _12 === void 0 ? void 0 : _12.querySelector('input[name="RelayState"]')) === null || _13 === void 0 ? void 0 : _13.getAttribute('value');
if (!shibbolethFormActionSMU && shibbolethSAMLResponseSMU && shibbolethRelayStateSMU) {
console.log('Force rouing shibbolethFormAction to https://login.libproxy.smu.edu.sg/Shibboleth.sso/SAML2/POST');
shibbolethFormActionSMU = 'https://login.libproxy.smu.edu.sg/Shibboleth.sso/SAML2/POST';
}
} while (!shibbolethFormActionSMU);
}
if (!shibbolethSAMLResponseSMU)
throw new Error('No Shibboleth SAMLResponse for SMU');
if (!shibbolethRelayStateSMU)
throw new Error('No Shibboleth RelayState for SMU');
params = new URLSearchParams();
params.append('SAMLResponse', shibbolethSAMLResponseSMU);
params.append('RelayState', shibbolethRelayStateSMU);
let basicSearchRedirect = yield followRedirects(yield localAxios.post(corsPrefix + shibbolethFormActionSMU, params, { responseType: 'document' }), localAxios, corsPrefix);
if ((_16 = (_15 = (_14 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _14 === void 0 ? void 0 : _14.documentElement) === null || _15 === void 0 ? void 0 : _15.outerHTML) === null || _16 === void 0 ? void 0 : _16.includes(DUPLICATE_LOGIN)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.SMU + DUPLICATE_LOGIN_REMOVE_URL), localAxios, corsPrefix);
for (;;) {
if ((_19 = (_18 = (_17 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _17 === void 0 ? void 0 : _17.documentElement) === null || _18 === void 0 ? void 0 : _18.outerHTML) === null || _19 === void 0 ? void 0 : _19.includes(exports.LOGOUT_REDIRECT_SCRIPT)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.SMU + exports.LOGOUT_REDIRECT_URL), localAxios, corsPrefix);
continue;
}
if ((_22 = (_21 = (_20 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _20 === void 0 ? void 0 : _20.documentElement) === null || _21 === void 0 ? void 0 : _21.outerHTML) === null || _22 === void 0 ? void 0 : _22.includes(exports.LOGOUT_REDIRECT_SCRIPT_2)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.SMU + exports.LOGOUT_REDIRECT_URL_2), localAxios, corsPrefix);
continue;
}
break;
}
}
if ((_23 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _23 === void 0 ? void 0 : _23.querySelector('div.alert.alert-error'))
throw new Error(basicSearchRedirect.data.querySelector('div.alert.alert-error').innerHTML);
if (!((_26 = (_25 = (_24 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _24 === void 0 ? void 0 : _24.querySelector('li.userInfo')) === null || _25 === void 0 ? void 0 : _25.innerHTML) === null || _26 === void 0 ? void 0 : _26.includes('<i>Welcome')))
throw new Error((_29 = (_28 = (_27 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _27 === void 0 ? void 0 : _27.body) === null || _28 === void 0 ? void 0 : _28.innerHTML) !== null && _29 !== void 0 ? _29 : 'Unable to reach welcome page');
return localAxios;
});
}
// Old SMU manual redirects
/**let adfsLoginPage1=await followRedirects(
await localAxios.post<Document>(
corsPrefix+SMU_ADFS_LOGIN_PAGE,
params,
{responseType:'document'}
),
localAxios
);
let adfsLoginPage2:AxiosResponse<Document,any>;
while(adfsLoginPage1?.data?.querySelector('form[name="hiddenform"]')?.getAttribute('action')!==SMU_SHIBBOLETH_SSO_URL){
let action=adfsLoginPage1?.data?.querySelector('form#loginForm')?.getAttribute('action');
if(!action)throw new Error(adfsLoginPage1?.data?.body?.innerHTML);
let adfsLoginPageUrl2=SMU_ADFS_LOGIN_PAGE_ROOT+action;
params=new URLSearchParams();
params.append('UserName',username);
params.append('Password',password);
params.append('AuthMethod','FormsAuthentication');
adfsLoginPage1=await followRedirects(
await localAxios.post<Document>(
corsPrefix+adfsLoginPageUrl2,
params,
{responseType:'document'}
),
localAxios
);
if(adfsLoginPage1?.data?.documentElement?.outerHTML?.includes(SMU_INCORRECT_USER_ID_OR_PASSWORD))throw new Error('Incorrect username or password. Too many wrong attempts will result in your account being locked. If in doubt, <a href="javascript:window.open(\''+SMU_RESET_PASSWORD_URL+'\',\'_system\');">reset your password</a>.');;
}
adfsLoginPage2=adfsLoginPage1;
let samlResponse=adfsLoginPage2?.data?.querySelector('input[name="SAMLResponse"]')?.getAttribute('value');
relayState=adfsLoginPage2?.data?.querySelector('input[name="RelayState"]')?.getAttribute('value');
if(!samlResponse||!relayState)throw new Error(adfsLoginPage2?.data?.body?.innerHTML??'No SAML Response or Relay State');
params=new URLSearchParams();
params.append('SAMLResponse',samlResponse);
params.append('RelayState',relayState);
let basicSearchRedirect=await followRedirects(
await localAxios.post<Document>(
corsPrefix+SMU_SHIBBOLETH_SSO_URL,
params,
{responseType:'document'}
),
localAxios
);
**/
function loginNUS(username, password, corsPrefix, domain, localAxios) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19;
return __awaiter(this, void 0, void 0, function* () {
let params = new URLSearchParams();
params.append('url', NUS_LAWNET_URL);
params.append('auth', 'adfs');
let nusLoginPage = yield followRedirects(yield localAxios.post(corsPrefix + NUS_LOGIN_URL, params, { responseType: 'document' }), localAxios, corsPrefix);
if ((_a = nusLoginPage === null || nusLoginPage === void 0 ? void 0 : nusLoginPage.data) === null || _a === void 0 ? void 0 : _a.querySelector('div[class="resourcesAccordion"]'))
return localAxios; //already authenticated
let samlRequest = (_c = (_b = nusLoginPage === null || nusLoginPage === void 0 ? void 0 : nusLoginPage.data) === null || _b === void 0 ? void 0 : _b.querySelector('input[name="SAMLRequest"]')) === null || _c === void 0 ? void 0 : _c.getAttribute('value');
let useAlternate = false;
if (!samlRequest) {
if ((_d = nusLoginPage === null || nusLoginPage === void 0 ? void 0 : nusLoginPage.data) === null || _d === void 0 ? void 0 : _d.querySelector('input[type="hidden"][name="auth"]')) {
params = new URLSearchParams();
params.append('url', NUS_LAWNET_URL);
params.append('auth', { nusstu: 'student', nusstf: 'staff', nusext: 'alumni' }[domain] || 'student');
nusLoginPage = yield followRedirects(yield localAxios.post(corsPrefix + NUS_LOGIN_URL, params, { responseType: 'document' }), localAxios, corsPrefix);
samlRequest = (_f = (_e = nusLoginPage === null || nusLoginPage === void 0 ? void 0 : nusLoginPage.data) === null || _e === void 0 ? void 0 : _e.querySelector('input[name="SAMLRequest"]')) === null || _f === void 0 ? void 0 : _f.getAttribute('value');
if (samlRequest)
useAlternate = true;
}
}
if (!samlRequest)
throw new Error('No SAMLRequest on NUS login page');
let relayState = (_h = (_g = nusLoginPage === null || nusLoginPage === void 0 ? void 0 : nusLoginPage.data) === null || _g === void 0 ? void 0 : _g.querySelector('input[name="RelayState"]')) === null || _h === void 0 ? void 0 : _h.getAttribute('value');
if (!relayState)
throw new Error('No RelayState on NUS login page');
params = new URLSearchParams();
params.append('SAMLRequest', samlRequest);
params.append('RelayState', relayState);
let nusVafsLoginPage = yield followRedirects(yield localAxios.post(useAlternate ? corsPrefix + NUS_VAFS_ALTERNATE_LOGIN_PAGE : corsPrefix + NUS_VAFS_LOGIN_PAGE, params, { responseType: 'document' }), localAxios, corsPrefix);
if ((_l = (_k = (_j = nusVafsLoginPage === null || nusVafsLoginPage === void 0 ? void 0 : nusVafsLoginPage.data) === null || _j === void 0 ? void 0 : _j.documentElement) === null || _k === void 0 ? void 0 : _k.outerHTML) === null || _l === void 0 ? void 0 : _l.includes(NUS_INCORRECT_USER_ID_OR_PASSWORD))
throw new Error('Incorrect username or password. Too many wrong attempts will result in your account being locked. If in doubt, <a href="javascript:window.open(\'' + NUS_HELPDESK_URL + '\',\'_system\');">contact the NUS Helpdesk</a>.');
if ((_p = (_o = (_m = nusVafsLoginPage === null || nusVafsLoginPage === void 0 ? void 0 : nusVafsLoginPage.data) === null || _m === void 0 ? void 0 : _m.documentElement) === null || _o === void 0 ? void 0 : _o.outerHTML) === null || _p === void 0 ? void 0 : _p.includes(NUS_OTHER_INCORRECT_USER_ID_OR_PASSWORD))
throw new Error('Incorrect username or password. Too many wrong attempts will result in your account being locked. If in doubt, <a href="javascript:window.open(\'' + NUS_HELPDESK_URL + '\',\'_system\');">contact the NUS Helpdesk</a>.');
let loginFormAction = (_r = (_q = nusVafsLoginPage === null || nusVafsLoginPage === void 0 ? void 0 : nusVafsLoginPage.data) === null || _q === void 0 ? void 0 : _q.querySelector('form#loginForm[action]')) === null || _r === void 0 ? void 0 : _r.getAttribute('action');
if (!loginFormAction)
throw new Error((_u = (_t = (_s = nusVafsLoginPage === null || nusVafsLoginPage === void 0 ? void 0 : nusVafsLoginPage.data) === null || _s === void 0 ? void 0 : _s.body) === null || _t === void 0 ? void 0 : _t.innerHTML) !== null && _u !== void 0 ? _u : 'Error retrieving NUS login form');
params = new URLSearchParams();
params.append('UserName', useAlternate ? username + '@u.nus.edu' : domain + '\\' + username);
params.append('Password', password);
params.append('AuthMethod', 'FormsAuthentication');
let shibbolethRedirect = yield followRedirects(yield localAxios.post(corsPrefix + (useAlternate ? NUS_VAFS_ALTERNATE_PREFIX : NUS_VAFS_PREFIX) + loginFormAction, params, { responseType: 'document' }), localAxios, corsPrefix);
if ((_x = (_w = (_v = shibbolethRedirect === null || shibbolethRedirect === void 0 ? void 0 : shibbolethRedirect.data) === null || _v === void 0 ? void 0 : _v.documentElement) === null || _w === void 0 ? void 0 : _w.outerHTML) === null || _x === void 0 ? void 0 : _x.includes(NUS_OTHER_INCORRECT_USER_ID_OR_PASSWORD))
throw new Error('Incorrect username or password. Too many wrong attempts will result in your account being locked. If in doubt, <a href="javascript:window.open(\'' + NUS_HELPDESK_URL + '\',\'_system\');">contact the NUS Helpdesk</a>.');
let shibbolethFormAction = (_z = (_y = shibbolethRedirect === null || shibbolethRedirect === void 0 ? void 0 : shibbolethRedirect.data) === null || _y === void 0 ? void 0 : _y.querySelector('form[name="hiddenform"][action]')) === null || _z === void 0 ? void 0 : _z.getAttribute('action');
if (!shibbolethFormAction)
throw new Error('No Shibboleth form action for NUS');
let shibbolethSAMLResponse = (_1 = (_0 = shibbolethRedirect === null || shibbolethRedirect === void 0 ? void 0 : shibbolethRedirect.data) === null || _0 === void 0 ? void 0 : _0.querySelector('input[name="SAMLResponse"]')) === null || _1 === void 0 ? void 0 : _1.getAttribute('value');
if (!shibbolethSAMLResponse)
throw new Error('No Shibboleth SAMLResponse for NUS');
let shibbolethRelayState = (_3 = (_2 = shibbolethRedirect === null || shibbolethRedirect === void 0 ? void 0 : shibbolethRedirect.data) === null || _2 === void 0 ? void 0 : _2.querySelector('input[name="RelayState"]')) === null || _3 === void 0 ? void 0 : _3.getAttribute('value');
if (!shibbolethRelayState)
throw new Error('No Shibboleth RelayState for NUS');
params = new URLSearchParams();
params.append('SAMLResponse', shibbolethSAMLResponse);
params.append('RelayState', shibbolethRelayState);
let basicSearchRedirect = yield followRedirects(yield localAxios.post(corsPrefix + shibbolethFormAction, params, { responseType: 'document' }), localAxios, corsPrefix);
if ((_6 = (_5 = (_4 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _4 === void 0 ? void 0 : _4.documentElement) === null || _5 === void 0 ? void 0 : _5.innerHTML) === null || _6 === void 0 ? void 0 : _6.includes(DUPLICATE_LOGIN)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.NUS + DUPLICATE_LOGIN_REMOVE_URL), localAxios, corsPrefix);
for (;;) {
if ((_9 = (_8 = (_7 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _7 === void 0 ? void 0 : _7.documentElement) === null || _8 === void 0 ? void 0 : _8.outerHTML) === null || _9 === void 0 ? void 0 : _9.includes(exports.LOGOUT_REDIRECT_SCRIPT)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.NUS + exports.LOGOUT_REDIRECT_URL), localAxios, corsPrefix);
continue;
}
if ((_12 = (_11 = (_10 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _10 === void 0 ? void 0 : _10.documentElement) === null || _11 === void 0 ? void 0 : _11.outerHTML) === null || _12 === void 0 ? void 0 : _12.includes(exports.LOGOUT_REDIRECT_SCRIPT_2)) {
basicSearchRedirect = yield followRedirects(yield localAxios.get(corsPrefix + exports.FIRST_URL.NUS + exports.LOGOUT_REDIRECT_URL_2), localAxios, corsPrefix);
continue;
}
break;
}
}
if ((_13 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _13 === void 0 ? void 0 : _13.querySelector('div.alert.alert-error'))
throw new Error(basicSearchRedirect.data.querySelector('div.alert.alert-error').innerHTML);
if (!((_16 = (_15 = (_14 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _14 === void 0 ? void 0 : _14.querySelector('li.userInfo')) === null || _15 === void 0 ? void 0 : _15.innerHTML) === null || _16 === void 0 ? void 0 : _16.includes('<i>Welcome')))
throw new Error((_19 = (_18 = (_17 = basicSearchRedirect === null || basicSearchRedirect === void 0 ? void 0 : basicSearchRedirect.data) === null || _17 === void 0 ? void 0 : _17.body) === null || _18 === void 0 ? void 0 : _18.innerHTML) !== null && _19 !== void 0 ? _19 : 'Unable to reach welcome page');
return localAxios;
});
}
function loginSUSS(username, password, corsPrefix, domain, localAxios) {
return __awaiter(this, void 0, void 0, function* () {
throw new Error('Work in progress');
});
}
let loginFunctions = {
SMU: loginSMU,
NUS: loginNUS,
SUSS: loginSUSS
};
function login(params) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
let corsPrefix = params.corsPrefix;
if (corsPrefix.trim() && !corsPrefix.endsWith('/'))
corsPrefix += '/';
return yield loginFunctions[params.school](params.username, params.password, corsPrefix, params.domain, (_a = params.localAxios) !== null && _a !== void 0 ? _a : axios_1.default.create({
baseURL: corsPrefix + exports.FIRST_URL[params.school],
withCredentials: true,
responseType: 'text'
}));
});
}
exports.login = login;
;
exports.default = login;