summaryrefslogtreecommitdiff
path: root/src/session.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/session.js')
-rw-r--r--src/session.js221
1 files changed, 72 insertions, 149 deletions
diff --git a/src/session.js b/src/session.js
index a127ac2..aee49c2 100644
--- a/src/session.js
+++ b/src/session.js
@@ -1,112 +1,19 @@
+import { Builder, Browser, By, Key, until } from "selenium-webdriver";
+import { Cookie } from "tough-cookie";
+
import {
+ AGGIETIME_AUTH_COOKIE_NAME,
+ AGGIETIME_DOMAIN,
AGGIETIME_URI,
+ AGGIETIME_URL_CONTAINS_SIGNIFIES_AUTH_COMPLETE,
LOGIN_PATH,
- LOGOUT_PATH,
- USER_PATH,
- DUO_IFRAME_SELECTOR,
- DUO_FACTOR,
- DUO_INPUT_FIELD_SELECTORS,
- EXECUTION_SELECTOR,
+ SAML_SIGN_IN_TITLE,
+ SAML_SUBMIT_SELECTOR,
+ SAML_EMAIL_SELECTOR,
+ SAML_PASSWORD_SELECTOR,
} from "./constants.js";
+import { jar } from "./axios_client.js";
import * as aggietime from "./aggietime.js";
-import { client } from "./axios_client.js";
-
-import { parse } from "node-html-parser";
-
-const make_auth_params = (username, password, execution) =>
- new URLSearchParams({
- username,
- password,
- execution,
- _eventId: "submit",
- geolocation: "",
- });
-
-const make_duo_push_params = (
- sid,
- out_of_date,
- days_out_of_date,
- days_to_block,
- device
-) =>
- new URLSearchParams({
- sid,
- out_of_date,
- days_out_of_date,
- days_to_block,
- device,
- factor: DUO_FACTOR,
- });
-
-const push_duo_get_cookie = async (
- duo_iframe_obj,
- response_url,
- username,
- password,
- execution
-) => {
- const [duo_host, duo_sig, duo_src] = [
- "data-host",
- "data-sig-request",
- "src",
- ].map((attr) => duo_iframe_obj.getAttribute(attr));
-
- const duo = client.create({
- baseURL: `https://${duo_host}`,
- });
- const transaction_id = duo_sig.split(":").at(0);
- const app = duo_sig.split(":APP").at(-1);
-
- console.log("Retrieving DUO frame DOM for this transaction...");
- const duo_frame = await duo
- .post(
- `/frame/web/v1/auth?tx=${transaction_id}&parent=${response_url}&v=2.6`
- )
- .then(({ data }) => parse(data));
-
- const push_param_list = DUO_INPUT_FIELD_SELECTORS.map((selector) =>
- duo_frame.querySelector(selector).getAttribute("value")
- );
- let [sid, _] = push_param_list;
-
- const {
- response: { txid },
- } = await duo
- .post("/frame/prompt", make_duo_push_params.apply(null, push_param_list))
- .then(({ data }) => data);
-
- console.log("Waiting for approval...");
- const { cookie, parent } = await wait_approve_duo_cookie_resp(duo, sid, txid);
- return { duo_signed_resp: cookie + ":APP" + app, parent };
-};
-
-const wait_approve_duo_cookie_resp = async (duo, sid, txid) => {
- // First status to confirm device was pushed to,
- // Second to create a long-poll connection-alive socket for approval status :3
- const status_params = new URLSearchParams({
- sid,
- txid,
- });
- const {
- response: { result_url },
- } = await duo.post("/frame/status", status_params).then(async ({ data }) => {
- if (data.stat === "OK" && data.response.status_code === "pushed")
- return await duo
- .post("/frame/status", status_params)
- .then(({ data }) => data);
- return data;
- });
-
- const {
- response: { cookie, parent },
- } = await duo
- .post(result_url, new URLSearchParams({ sid }))
- .then(({ data }) => data);
-
- if (!cookie) throw "Unable to retrieve signed cookie from DUO";
-
- return { cookie, parent };
-};
export const refresh_jwt = () => {
console.log("Refreshing JWT...");
@@ -116,51 +23,67 @@ export const refresh_jwt = () => {
export const logout = () => client.get(`${AGGIETIME_URI}/${LOGOUT_PATH}`);
-export const login = async (username, password) => {
- const login_page_promise = client.get(`${AGGIETIME_URI}/${LOGIN_PATH}`);
- console.log("Retreiving login page...");
-
- const {
- request: {
- res: { responseUrl: response_url },
- },
- } = await login_page_promise;
-
- let cas_root = await login_page_promise.then(({ data }) => parse(data));
-
- console.log("Parsing DOM for spring execution token...");
- const login_execution = cas_root
- .querySelector(EXECUTION_SELECTOR)
- .getAttribute("value");
-
- console.log("Sending CAS credentials...");
- cas_root = await client
- .post(response_url, make_auth_params(username, password, login_execution))
- .then(({ data }) => parse(data));
-
- console.log("Parsing DOM for authenticated spring execution token...");
- const authed_execution = cas_root
- .querySelector(EXECUTION_SELECTOR)
- .getAttribute("value");
-
- const duo_iframe_obj = cas_root.querySelector(DUO_IFRAME_SELECTOR);
- console.log("Starting DUO authentication...");
- const { duo_signed_resp, parent: signed_response_url } =
- await push_duo_get_cookie(
- duo_iframe_obj,
- response_url,
- username,
- password,
- login_execution
+export const login = async (a_number, password) => {
+ const driver = await new Builder().forBrowser(Browser.CHROME).build();
+ let cookie;
+
+ try {
+ console.log("Navigating to login path...");
+ await driver.get(`${AGGIETIME_URI}/${LOGIN_PATH}`);
+
+ if (a_number && password) {
+ console.log("Waiting until we eventually redirect to SAML...");
+ await driver.wait(until.titleIs(SAML_SIGN_IN_TITLE));
+
+ console.log("Waiting until email field is located...");
+ await driver.wait(until.elementLocated(By.css(SAML_EMAIL_SELECTOR)));
+
+ console.log("Filling email field...");
+ await driver
+ .findElement(By.css(SAML_EMAIL_SELECTOR))
+ .sendKeys(`${a_number}@usu.edu`);
+ await driver.findElement(By.css(SAML_SUBMIT_SELECTOR)).click();
+
+ console.log("Waiting until password field is located...");
+ await Promise.all(
+ [SAML_PASSWORD_SELECTOR, SAML_SUBMIT_SELECTOR].map((selector) =>
+ driver.wait(until.elementLocated(By.css(selector)))
+ )
+ );
+
+ console.log("Filling password...");
+ await driver
+ .findElement(By.css(SAML_PASSWORD_SELECTOR))
+ .sendKeys(password);
+
+ console.log("Debouncing a bit...");
+ await new Promise((res) => setTimeout(res, 500));
+
+ console.log("Submit!");
+ await driver.findElement(By.css(SAML_SUBMIT_SELECTOR)).click();
+ }
+
+ console.log(
+ "Waiting for aggietime response (potential DUO required here)..."
+ );
+ await driver.wait(
+ until.urlContains(AGGIETIME_URL_CONTAINS_SIGNIFIES_AUTH_COMPLETE)
+ );
+
+ console.log("Retrieving cookie...");
+ cookie = await driver.manage().getCookie(AGGIETIME_AUTH_COOKIE_NAME);
+
+ await jar.setCookie(
+ new Cookie({
+ ...cookie,
+ key: cookie.name,
+ }),
+ AGGIETIME_URI
);
+ console.log("Got it!");
+ } finally {
+ await driver.quit();
+ }
- console.log("Sending DUO signed response back to CAS...");
- return await client.post(
- signed_response_url,
- new URLSearchParams({
- execution: authed_execution,
- signedDuoResponse: duo_signed_resp,
- _eventId: "submit",
- })
- );
+ return cookie;
};