diff options
Diffstat (limited to 'src/session.js')
-rw-r--r-- | src/session.js | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/session.js b/src/session.js new file mode 100644 index 0000000..ae6d593 --- /dev/null +++ b/src/session.js @@ -0,0 +1,124 @@ +import { + AGGIETIME_URI, + LOGIN_PATH, + DUO_IFRAME_SELECTOR, + DUO_FACTOR, + DUO_INPUT_FIELD_SELECTORS, + EXECUTION_SELECTOR, +} from "./constants.js"; + +import { parse } from "node-html-parser"; +import axios from "axios"; + +const make_auth_params = (username, password, execution) => + new URLSearchParams({ + username, + password, + execution, + _eventId: "submit", + geolocation: "", + }); + +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 transaction_id = duo_sig.split(":")[0]; + + const duo = axios.create({ + withCredentials: true, + baseURL: `https://${duo_host}`, + }); + + const duo_frame = await duo + .post( + `/frame/web/v1/auth?tx=${transaction_id}&parent=${response_url}&v=2.6` + ) + .then(({ data }) => parse(data)); + + const [sid, out_of_date, days_out_of_date, days_to_block, device] = + DUO_INPUT_FIELD_SELECTORS.map((selector) => + duo_frame.querySelector(selector).getAttribute("value") + ); + + const push_params = new URLSearchParams({ + sid, + out_of_date, + days_out_of_date, + days_to_block, + device, + factor: DUO_FACTOR, + }); + + const { + response: { txid }, + } = await duo.post("/frame/prompt", push_params).then(({ data }) => data); + + return await wait_approve_duo(duo, sid, txid); +}; + +const wait_approve_duo = async (duo, sid, txid) => { + // First status to confirm device was pushed to + // Second to long-poll for approval :3 + const status_params = new URLSearchParams({ + sid, + txid, + }); + + const data = 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: { result_url }, + } = data; + + console.log(data); + + return await duo.post(result_url, new URLSearchParams({ sid })); +}; + +export const login = async (username, password) => { + const login_page_promise = axios.get(`${AGGIETIME_URI}/${LOGIN_PATH}`); + + const { + request: { + res: { responseUrl: response_url }, + }, + } = await login_page_promise; + const cas_root = await login_page_promise.then(({ data }) => parse(data)); + const execution = cas_root + .querySelector(EXECUTION_SELECTOR) + .getAttribute("value"); + + const duo_iframe_obj = await axios + .post(response_url, make_auth_params(username, password, execution)) + .then(({ data }) => parse(data).querySelector(DUO_IFRAME_SELECTOR)); + + const cookie = await push_duo_get_cookie( + duo_iframe_obj, + response_url, + username, + password, + execution + ); + + console.log(cookie); + console.log(cookie.data); + + return cookie; +}; |