The Login Trigger
👉 Attach this function to your "Login" button. It packages your app's ID and securely redirects the user to the SSO portal.
function login() {
const CLIENT_ID = "your_client_id";
const REDIRECT_URI = "your_redirect_uri";
const url = new URL("https://sso-production-d29b.up.railway.app/oauth/authorize");
url.searchParams.set("client_id", CLIENT_ID);
url.searchParams.set("redirect_uri", REDIRECT_URI);
url.searchParams.set("response_type", "code");
url.searchParams.set("scope", "openid email profile");
url.searchParams.set("state", "random_state");
window.location.href = url.toString();
}
The SSO Redirect (Handshake)
You don't need to write code for this part.
The user enters their credentials on our secure server. Once
authenticated, we automatically bounce them back to the
REDIRECT_URI you provided in Step 1 (e.g., your
auth.html page).
We attach a secret code to
the URL, making it look like this: your_redirect_uri?code=abc123XYZ
The Token Exchange
👉 This is the logic for your callback page. Put your constants right
at the top so the function can use them. It extracts the
?code= from the URL and securely exchanges it for the
user's data.
const CLIENT_ID = "your_client_id";
const CLIENT_SECRET = "your_client_secret";
const REDIRECT_URI = "your_redirect_uri";
function handleOAuth() {
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
console.log("CODE:", code);
// If no code exists, or we already processed it, stop here.
if (!code || sessionStorage.getItem("oauth_done")) return;
sessionStorage.setItem("oauth_done", "true");
fetch("https://sso-production-d29b.up.railway.app/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
code,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
}),
})
.then((res) => res.json())
.then((data) => {
console.log("TOKEN:", data);
// Extract User Info and save it
const user = JSON.parse(atob(data.id_token.split(".")[1]));
localStorage.setItem("user", JSON.stringify(user));
console.log("Logged in:", user.email);
// Clean the URL bar so the "?code=" disappears
window.history.replaceState({}, document.title, "/auth.html");
})
.catch(console.error);
}
*Note: In a true production environment, you should move this Step to a backend server so your CLIENT_SECRET is never visible in the browser.
Executing The Flow (Recovery Loop)
👉 Defining the function isn't enough; you must run it. Because some browsers drop the first network request on new user flows, we run a stacked timeout loop. This guarantees the login completes successfully.
// 🔥 RUN MULTIPLE TIMES (THIS FIXES NEW USER FLOW) handleOAuth(); setTimeout(handleOAuth, 300); setTimeout(handleOAuth, 800);