Last active
December 5, 2024 11:25
-
-
Save RobinBoers/2fb550080bec7984bd68953b0fd0569d to your computer and use it in GitHub Desktop.
Script to authenticate with the Somtoday API via SSO, by intercepting the redirect to the app.
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
{ | |
"dependencies": { | |
"axios": "^1.4.0" | |
} | |
} |
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
// NodeJS crap | |
// This unfortunately doesn't work in the browser atm :( | |
const crypto = require("crypto"); | |
const axios = require('axios'); | |
const { spawn } = require('node:child_process'); | |
const readline = require("readline").createInterface({ | |
input: process.stdin, | |
output: process.stdout, | |
}); | |
// Configuration | |
// | |
// - Redirect URI should be a verified Somtoday callback URL. You intercept the code from this URL. | |
// - School UUID should be the UUID for your school. Can be found in the `organisations.json` file. | |
// - Third party method should be the `oidc_iss` shit from the login URL. It can also be found in the `organisations.json` file. | |
// - The client ID is a verified Somtoday client ID for OAuth. This one is from the Somtoday app. | |
const REDIRECT_URI = "somtodayouder://oauth/callback"; | |
const SCHOOL_UUID = "ec284fda-3d0f-4f54-a77e-91d94b94ff1a"; | |
const third_party_method = "https://accounts.google.com"; | |
const CLIENT_ID = "CD4EBCF7-2809-4AB3-8D71-7D9CE518AF1B"; | |
// Crypto utils | |
// | |
// Some utility functions for handling verifiers and such. | |
// Used in the OAuth code. | |
let url_encode = function (input) { | |
return input | |
.toString("base64") | |
.replace(/\+/g, "-") | |
.replace(/\//g, "_") | |
.replace(/=/g, ""); | |
}; | |
let randomBytes = function (amountOfBytes) { | |
return crypto.randomBytes(amountOfBytes); | |
}; | |
let sha256 = function (buffer) { | |
return crypto.createHash("sha256").update(buffer).digest(); | |
}; | |
let verifier = url_encode(randomBytes(32)); | |
let challenge = url_encode(sha256(verifier)); | |
// Main login flow | |
// | |
// We open a login window, in which the user authenticates using their credentials. Som will the redirect to the `REDIRECT_URI`, | |
// but since this is a fucking laptop it won't find the app, and error in the console, where you can then copy the code. | |
// The script will prompt for it, paste it there. It will then send a request to the Somtoday API to generate an access token. | |
function login() { | |
openLoginWindow(); | |
askForInput(); | |
} | |
function openLoginWindow() { | |
let url = `https://inloggen.somtoday.nl/oauth2/authorize?response_type=code&prompt=login&redirect_uri=${REDIRECT_URI}&client_id=${CLIENT_ID}&state=sompp&response_type=code&scope=openid&tenant_uuid=${SCHOOL_UUID}&session=no_session&code_challenge_method=S256&code_challenge=${challenge}`; | |
spawn("librewolf", [url]); | |
} | |
function askForInput() { | |
readline.question( | |
"Please enter code from Somtoday login callback: \n", | |
(code) => { | |
getAccessToken(code); | |
readline.close(); | |
} | |
); | |
} | |
function getAccessToken(codeFromLoginWindow) { | |
let url = `https://inloggen.somtoday.nl/oauth2/token`; | |
let body = new URLSearchParams({ | |
grant_type: "authorization_code", | |
redirect_uri: REDIRECT_URI, | |
code_verifier: verifier, | |
code: codeFromLoginWindow, | |
scope: "openid", | |
client_id: CLIENT_ID, | |
}); | |
axios({ | |
url: url, | |
method: "POST", | |
data: body, | |
}).then(function (response) { | |
console.log(response.data); | |
}); | |
} | |
login(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated version at https://gist.github.com/RobinBoers/f57164c20f05bafa3f847910c5d784e4