OAuth2??!
This commit is contained in:
parent
f0b527eb39
commit
42ca222049
|
@ -0,0 +1,3 @@
|
||||||
|
config.ini
|
||||||
|
config.ini.example
|
||||||
|
database.db
|
63
main
63
main
|
@ -72,6 +72,12 @@ def check_username_taken(username):
|
||||||
return None
|
return None
|
||||||
return post["id"]
|
return post["id"]
|
||||||
|
|
||||||
|
async def oauth2_token_refresh(secret, appId):
|
||||||
|
while True:
|
||||||
|
conn = get_db_connection()
|
||||||
|
conn.execute("UPDATE logins SET code = ?, nextcode = ? WHERE appId = ? AND secret = ?", (str(conn.execute("SELECT nextcode FROM logins WHERE appId = ? AND secret = ?", (str(appId), str(secret))).fetchone())), str(secrets.token_hex(512)), str(appId), str(secret))
|
||||||
|
await asyncio.sleep(3600)
|
||||||
|
|
||||||
# Disable CORS
|
# Disable CORS
|
||||||
@app.after_request
|
@app.after_request
|
||||||
async def add_cors_headers(response):
|
async def add_cors_headers(response):
|
||||||
|
@ -193,32 +199,79 @@ async def apiauthenticate():
|
||||||
data = await request.get_json()
|
data = await request.get_json()
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
appId = data["appId"]
|
appId = data["appId"]
|
||||||
|
state = data["state"]
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
user = get_user(userCookie["id"])
|
user = get_user(userCookie["id"])
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
secretkey = {
|
secretkey = str(secrets.token_hex(512))
|
||||||
"key": str(conn.execute("SELECT secret FROM userdata WHERE appId = ? AND creator = ? LIMIT 1", (str(appId),int(user["id"]))))
|
|
||||||
}
|
clientidcheck = str(conn.execute("SELECT appId FROM oauth WHERE appId = ?", (str(appId)))).fetchone()
|
||||||
|
if not str(clientidcheck) == str(appId):
|
||||||
|
return {}, 401
|
||||||
|
|
||||||
|
conn.execute("INSERT INTO logins (appId, authed, secret, code, nextcode, creator) VALUES (?, ?, ?, ?, ?, ?)",
|
||||||
|
(str(appId), int(int(time.time()) + 3600), int(0), str(secretkey), str(secrets.token_hex(512)), str(secrets.token_hex(512)), int(user["id"])))
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
if secretkey:
|
if secretkey:
|
||||||
return secretkey, 200
|
return secretkey, 200
|
||||||
else:
|
else:
|
||||||
return {}, 400
|
return {}, 400
|
||||||
|
|
||||||
|
@app.route("/api/tokenauth", methods=("GET", "POST"))
|
||||||
|
async def apitokenexchange():
|
||||||
|
if request.method == "POST":
|
||||||
|
data = await request.get_json()
|
||||||
|
secret = data["client_secret"]
|
||||||
|
appId = data["client_id"]
|
||||||
|
code = data["code"]
|
||||||
|
|
||||||
|
conn = get_db_connection()
|
||||||
|
access_token = {
|
||||||
|
"access_token": str(conn.execute("SELECT secret FROM logins WHERE appId = ? AND code = ?", (str(appId), str(code))).fetchone()),
|
||||||
|
"token_type": "bearer",
|
||||||
|
"expires_in": 3600,
|
||||||
|
"refresh_token": str(conn.execute("SELECT nextcode FROM logins WHERE appId = ? AND code = ?", (str(appId), str(code))).fetchone())
|
||||||
|
}
|
||||||
|
|
||||||
|
clientidcheck = str(conn.execute("SELECT appId FROM oauth WHERE appId = ?", (str(appId)))).fetchone()
|
||||||
|
if not str(clientidcheck) == str(appId):
|
||||||
|
return {}, 401
|
||||||
|
|
||||||
|
secretcheck = str(conn.execute("SELECT secret FROM oauth WHERE appId = ?", (str(appId)))).fetchone()
|
||||||
|
if not str(secretcheck) == str(secret):
|
||||||
|
return {}, 402
|
||||||
|
|
||||||
|
if secretkey:
|
||||||
|
asyncio.run(oauth2_token_refresh(str(conn.execute("SELECT secret FROM logins WHERE appId = ? AND code = ?", (str(appId), str(code))).fetchone()), appId))
|
||||||
|
return access_token, 200
|
||||||
|
else:
|
||||||
|
return {}, 400
|
||||||
|
|
||||||
@app.route("/api/newauth", methods=("GET", "POST"))
|
@app.route("/api/newauth", methods=("GET", "POST"))
|
||||||
async def apicreateauth():
|
async def apicreateauth():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = await request.get_json()
|
data = await request.get_json()
|
||||||
appId = data["appId"]
|
appId = data["appId"]
|
||||||
secretKey = data["secretKey"]
|
secretKey = data["secretKey"]
|
||||||
secret = secrets.token_hex(512)
|
secret = str(secrets.token_hex(512))
|
||||||
|
while True:
|
||||||
|
if not secret == str(conn.execute("SELECT secret FROM oauth WHERE secret = ?", (str(secret)))).fetchone():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
secret = str(secrets.token_hex(512))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if clientId == str(conn.execute("SELECT secret FROM oauth WHERE clientId = ?", (str(clientId)))).fetchone():
|
||||||
|
return 401
|
||||||
|
|
||||||
userCookie = get_session(secretKey)
|
userCookie = get_session(secretKey)
|
||||||
user = get_user(userCookie["id"])
|
user = get_user(userCookie["id"])
|
||||||
|
|
||||||
conn = get_db_connection()
|
conn = get_db_connection()
|
||||||
conn.execute("INSERT INTO userdata (appId, creator, secret) VALUES (?, ?, ?)",
|
conn.execute("INSERT INTO keys (appId, creator, secret) VALUES (?, ?, ?)",
|
||||||
(str(appId),int(user["id"]),str(secret)))
|
(str(appId),int(user["id"]),str(secret)))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
|
@ -21,3 +21,12 @@ CREATE TABLE sessions (
|
||||||
id INTEGER NOT NULL,
|
id INTEGER NOT NULL,
|
||||||
device TEXT NOT NULL DEFAULT "?"
|
device TEXT NOT NULL DEFAULT "?"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE logins (
|
||||||
|
appId TEXT NOT NULL,
|
||||||
|
authed INTEGER NOT NULL,
|
||||||
|
secret TEXT NOT NULL,
|
||||||
|
code TEXT NOT NULL,
|
||||||
|
nextcode TEXT NOT NULL,
|
||||||
|
creator INTEGER NOT NULL
|
||||||
|
)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
|
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
|
||||||
window.location.replace("../app")
|
window.location.replace("/app" + window.location.search)
|
||||||
document.body.innerHTML = "Redirecting..."
|
document.body.innerHTML = "Redirecting..."
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("DONOTSHARE-password") !== null) {
|
if (localStorage.getItem("DONOTSHARE-password") !== null) {
|
||||||
window.location.replace("../app")
|
window.location.replace("/app" + window.location.search)
|
||||||
document.body.innerHTML = "Redirecting..."
|
document.body.innerHTML = "Redirecting..."
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ signupButton.addEventListener("click", (event) => {
|
||||||
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
||||||
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
||||||
|
|
||||||
window.location.href = "../app"
|
window.location.href = "/app" + window.location.search
|
||||||
}
|
}
|
||||||
else if (response.status == 401) {
|
else if (response.status == 401) {
|
||||||
console.log("Trying oldhash")
|
console.log("Trying oldhash")
|
||||||
|
@ -163,7 +163,7 @@ signupButton.addEventListener("click", (event) => {
|
||||||
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
||||||
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
||||||
|
|
||||||
window.location.href = "../app/"
|
window.location.href = "/app" + window.location.search
|
||||||
}
|
}
|
||||||
else if (response.status == 401) {
|
else if (response.status == 401) {
|
||||||
statusBox.innerText = "Wrong username or password..."
|
statusBox.innerText = "Wrong username or password..."
|
||||||
|
@ -197,3 +197,19 @@ backButton.addEventListener("click", (event) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
showInput(0)
|
showInput(0)
|
||||||
|
|
||||||
|
document.getElementById("signuprdirButton").addEventListener("click", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var queryString = window.location.search;
|
||||||
|
var newURL = "/signup" + queryString;
|
||||||
|
window.location.href = newURL;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("privacyButton").addEventListener("click", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var queryString = window.location.search;
|
||||||
|
var newURL = "/privacy" + queryString;
|
||||||
|
window.location.href = newURL;
|
||||||
|
});
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
|
if (localStorage.getItem("DONOTSHARE-secretkey") !== null) {
|
||||||
window.location.replace("../app")
|
window.location.replace("/app" + window.location.search)
|
||||||
document.body.innerHTML = "Redirecting..."
|
document.body.innerHTML = "Redirecting..."
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
if (localStorage.getItem("DONOTSHARE-password") !== null) {
|
if (localStorage.getItem("DONOTSHARE-password") !== null) {
|
||||||
window.location.replace("../app")
|
window.location.replace("/app" + window.location.search)
|
||||||
document.body.innerHTML = "Redirecting..."
|
document.body.innerHTML = "Redirecting..."
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ signupButton.addEventListener("click", (event) => {
|
||||||
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
localStorage.setItem("DONOTSHARE-secretkey", responseData["key"])
|
||||||
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
localStorage.setItem("DONOTSHARE-password", await hashwasm.sha512(password))
|
||||||
|
|
||||||
window.location.href = "../app"
|
window.location.href = "/app" + window.location.search
|
||||||
}
|
}
|
||||||
else if (response.status == 409) {
|
else if (response.status == 409) {
|
||||||
statusBox.innerText = "Username already taken!"
|
statusBox.innerText = "Username already taken!"
|
||||||
|
@ -107,3 +107,19 @@ signupButton.addEventListener("click", (event) => {
|
||||||
}
|
}
|
||||||
doStuff()
|
doStuff()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("loginButton").addEventListener("click", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var queryString = window.location.search;
|
||||||
|
var newURL = "/login" + queryString;
|
||||||
|
window.location.href = newURL;
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("privacyButton").addEventListener("click", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var queryString = window.location.search;
|
||||||
|
var newURL = "/privacy" + queryString;
|
||||||
|
window.location.href = newURL;
|
||||||
|
});
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
<button id="backButton" class="hidden">Back</button>
|
<button id="backButton" class="hidden">Back</button>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<p>Don't have an account? If so, <a href="../signup">Create one here!</a></p>
|
<p>Don't have an account? If so, <a href="#" id="signuprdirButton">Create one here!</a></p>
|
||||||
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
|
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
|
||||||
<a href="../privacy/index.html">Privacy & Terms</a>
|
<a href="#" id="privacyButton">Privacy & Terms</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="../static/js/login.js"></script>
|
<script type="text/javascript" src="../static/js/login.js"></script>
|
||||||
|
|
|
@ -1 +1,52 @@
|
||||||
Ok, logged in
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Send Data to example.org</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Send Data to example.org</h1>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Function to parse URL parameters
|
||||||
|
function getUrlParameter(name) {
|
||||||
|
name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
|
||||||
|
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
|
||||||
|
var results = regex.exec(location.search);
|
||||||
|
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get URL parameters
|
||||||
|
var client_id = getUrlParameter('client_id');
|
||||||
|
var redirect_uri = getUrlParameter('redirect_uri');
|
||||||
|
var response_type = getUrlParameter('response_type');
|
||||||
|
var state = getUrlParameter('state');
|
||||||
|
|
||||||
|
// Get DONOTSHARE-secretkey from localStorage
|
||||||
|
var secret_key = localStorage.getItem("DONOTSHARE-secretkey");
|
||||||
|
|
||||||
|
// Create data object to send
|
||||||
|
var data = {
|
||||||
|
client_id: client_id,
|
||||||
|
secretKey: secret_key,
|
||||||
|
state: state
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send data to example.org using POST request
|
||||||
|
fetch("https://auth.hectabit.org/api/auth", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
window.location.replace(redirect_uri + "?code=" + response + "&state=" + state)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
alert("Error sending data: " + error.message);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
<input id="usernameBox" type="text" placeholder="Username">
|
<input id="usernameBox" type="text" placeholder="Username">
|
||||||
<input id="passwordBox" type="password" placeholder="Password"><br>
|
<input id="passwordBox" type="password" placeholder="Password"><br>
|
||||||
<button id="signupButton">Signup</button><br><br>
|
<button id="signupButton">Signup</button><br><br>
|
||||||
<p>Already have an account? If so, <a href="../login">Login</a> instead!</p>
|
<p>Already have an account? If so, <a href="#" id="loginButton">Login</a> instead!</p>
|
||||||
<p>Please note that it's impossible to reset your password, do not forget it!</p>
|
<p>Please note that it's impossible to reset your password, do not forget it!</p>
|
||||||
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
|
<div style="display: flex;"><p id="homeserver">Your homeserver is loading... </p><div style="display: flex;flex-direction: column;justify-content: center;"><a href="/homeserver">Change</a></div></div>
|
||||||
<a href="../privacy/index.html">Privacy & Terms</a>
|
<a href="#" id="privacyButton">Privacy & Terms</a>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="../static/js/signup.js"></script>
|
<script type="text/javascript" src="../static/js/signup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Reference in New Issue