(function (global, factory) {
typeof exports === "object" && typeof module !== "undefined"
? factory()
: typeof define === "function" && define.amd
? define(factory)
: (global.HamsooID = factory())
})(this, function () {
"use strict"
const defaults = {
client_id: "",
redirect_uri: "",
scope: "openid profile email",
response_mode: "redirect",
onSuccess: () => {},
onError: () => {},
}
let config = { ...defaults }
function renderButton(container, customHtml = null) {
const btn = document.createElement("button")
btn.type = "button"
btn.className = "hamsoo-signin-button"
btn.innerHTML = customHtml || /*html*/ `Sign in with Hamsoo`
btn.style.cssText = [
"width:100%",
"margin-top:20px",
"padding:12px",
"background:#2f6df6",
"color:#fff",
"border:none",
"border-radius:10px",
"font-size:15px",
"cursor:pointer",
"font-family:-apple-system,BlinkMacSystem,Segoe UI,Tahoma,sans-serif",
].join(";")
btn.addEventListener("click", handleClick)
container.innerHTML = ""
container.appendChild(btn)
}
function handleClick() {
const params = new URLSearchParams({
client_id: config.client_id,
response_type: "code",
redirect_uri: config.redirect_uri,
scope: config.scope,
response_mode: config.response_mode,
state: crypto.randomUUID(),
code_challenge_method: "S256",
})
let url = "/oauth/authorize?" + params.toString()
if (config.response_mode === "web_message") {
url += "&prompt=login"
}
const isPopup = config.response_mode === "web_message"
let width = 600,
height = 800
if (isPopup) {
width = 600
height = 800
const left = (screen.width - width) / 2
const top = (screen.height - height) / 2
const win = window.open(
url,
"HamsooSignIn",
`width=${width},height=${height},left=${left},top=${top},menubar=no,toolbar=no,status=no`
)
if (win) {
listenForMessage(win)
} else {
config.onError(new Error("Popup blocked"))
}
} else {
window.location.href = url
}
}
function listenForMessage(win) {
const listener = (event) => {
if (
event.data &&
event.data.type === "authorization_response" &&
event.origin.startsWith("http://") &&
event.origin.includes("hamsoo.me")
) {
const { code, state } = event.data
if (code) {
unlistenForMessage()
config.onSuccess({ code, state })
} else if (event.data.error) {
unlistenForMessage()
config.onError(new Error(event.data.error))
}
}
}
function unlistenForMessage() {
window.removeEventListener("message", listener)
}
window.addEventListener("message", listener)
// Auto-close after 10s if no message received
const timer = setTimeout(() => {
unlistenForMessage()
config.onError(new Error("Authorization timed out"))
win.close()
}, 10000)
}
return {
init: (options) => {
config = { ...defaults, ...options }
const container = document.getElementById("hamsoo-signin-root") || document.body
renderButton(container)
},
render: (customHtml) => {
const container = document.getElementById("hamsoo-signin-root") || document.body
renderButton(container, customHtml)
},
setConfig: (options) => {
config = { ...config, ...options }
},
}
})