Compare commits

..

4 Commits

1 changed files with 39 additions and 92 deletions

131
main.go
View File

@ -12,13 +12,11 @@ import (
"encoding/base64" "encoding/base64"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"encoding/json"
"encoding/pem" "encoding/pem"
"errors" "errors"
"fmt" "fmt"
"log" "log"
"math/big" "math/big"
"net/http"
"os" "os"
"regexp" "regexp"
"strconv" "strconv"
@ -148,13 +146,13 @@ func checkUsernameTaken(username string) (int, bool, error) {
err := conn.QueryRow("SELECT id FROM users WHERE lower(username) = ? LIMIT 1", username).Scan(&id) err := conn.QueryRow("SELECT id FROM users WHERE lower(username) = ? LIMIT 1", username).Scan(&id)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return 0, false, nil return 0, true, nil
} else { } else {
return 0, true, err return 0, true, err
} }
} }
return id, true, nil return id, false, nil
} }
func init_db() { func init_db() {
@ -307,12 +305,6 @@ func main() {
gin.SetMode(gin.ReleaseMode) gin.SetMode(gin.ReleaseMode)
router := gin.New() router := gin.New()
store := cookie.NewStore([]byte(SECRET_KEY)) store := cookie.NewStore([]byte(SECRET_KEY))
store.Options(sessions.Options{
MaxAge: 300,
HttpOnly: true,
Secure: true,
SameSite: 3,
})
router.Use(sessions.Sessions("currentSession", store)) router.Use(sessions.Sessions("currentSession", store))
// Enable CORS // Enable CORS
@ -821,8 +813,6 @@ func main() {
nonce := c.Request.URL.Query().Get("nonce") nonce := c.Request.URL.Query().Get("nonce")
deny := c.Request.URL.Query().Get("deny") deny := c.Request.URL.Query().Get("deny")
session := sessions.Default(c)
var appIdCheck, redirectUriCheck string var appIdCheck, redirectUriCheck string
err := conn.QueryRow("SELECT appId, rdiruri FROM oauth WHERE appId = ? LIMIT 1", appId).Scan(&appIdCheck, &redirectUriCheck) err := conn.QueryRow("SELECT appId, rdiruri FROM oauth WHERE appId = ? LIMIT 1", appId).Scan(&appIdCheck, &redirectUriCheck)
@ -862,13 +852,13 @@ func main() {
} }
} }
_, userId, err := getSession(secretKey) _, userid, err := getSession(secretKey)
if err != nil { if err != nil {
c.String(401, "Invalid session") c.String(401, "Invalid session")
return return
} }
_, username, _, sub, err := getUser(userId) _, username, _, sub, err := getUser(userid)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
c.String(400, "User does not exist") c.String(400, "User does not exist")
return return
@ -900,58 +890,38 @@ func main() {
tokenTemp := jwt.NewWithClaims(jwt.SigningMethodRS256, dataTemplate) tokenTemp := jwt.NewWithClaims(jwt.SigningMethodRS256, dataTemplate)
tokenTemp.Header["kid"] = "burgerauth" tokenTemp.Header["kid"] = "burgerauth"
openIdToken, err := tokenTemp.SignedString(privateKey) jwt_token, err := tokenTemp.SignedString(privateKey)
if err != nil { if err != nil {
log.Println("[ERROR] Unknown in /api/auth openIdToken at", strconv.FormatInt(time.Now().Unix(), 10)+":", err) log.Println("[ERROR] Unknown in /api/auth jwt_token at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-JWTCANNOTSIGN") c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-JWTCANNOTSIGN")
return return
} }
secretTemp := jwt.NewWithClaims(jwt.SigningMethodRS256, dataTemplateTwo) secretTemp := jwt.NewWithClaims(jwt.SigningMethodRS256, dataTemplateTwo)
secretTemp.Header["kid"] = "burgerauth" secretTemp.Header["kid"] = "burgerauth"
oauthToken, err := secretTemp.SignedString(privateKey) secret_token, err := secretTemp.SignedString(privateKey)
if err != nil { if err != nil {
log.Println("[ERROR] Unknown in /api/auth oauthToken at", strconv.FormatInt(time.Now().Unix(), 10)+":", err) log.Println("[ERROR] Unknown in /api/auth secret_token at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-JWTCANNOTSIGN.") c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-JWTCANNOTSIGN.")
return return
} }
exchangeKey, err := genSalt(512) randomBytes, err := genSalt(512)
if err != nil { if err != nil {
log.Println("[ERROR] Unknown in /api/auth exchangeKey at", strconv.FormatInt(time.Now().Unix(), 10)+":", err) log.Println("[ERROR] Unknown in /api/auth randomBytes at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-RANDOMBYTES.") c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-RANDOMBYTES.")
return return
} }
sessionInfo := map[string]any{ _, err = conn.Exec("INSERT INTO logins (appId, secret, nextsecret, code, nextcode, creator, openid, nextopenid, pkce, pkcemethod) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", appId, randomBytes, "none", secret_token, "none", userid, jwt_token, "none", code, codeMethod)
"iat": time.Now().Unix(),
"session": secretKey,
"appId": appId,
"exchangeKey": exchangeKey,
"creator": userId,
"PKCECode": code,
"PKCEMethod": codeMethod,
}
c.SetSameSite(3)
c.SetCookie("oauthToken", oauthToken, 300, "/", "", true, true)
c.SetCookie("openIdToken", openIdToken, 300, "/", "", true, true)
sessionInfoStr, err := json.Marshal(sessionInfo)
if err != nil { if err != nil {
log.Println("[ERROR] Unknown in /api/auth sessionInfoStr at", strconv.FormatInt(time.Now().Unix(), 10)+":", err) log.Println("[ERROR] Unknown in /api/auth insert at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-SESSIONINFO.") c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-INSERT.")
return
}
session.Set("activeLogin", sessionInfoStr)
err = session.Save()
if err != nil {
log.Println("[ERROR] Client-Server unknown in /api/auth session save at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.String(400, "Something went wrong, but we don't know who's fault it is (because we are mean coders, the error code says it's yours). If you deliberately caused this error (well done), please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and give us more info on how it happened. Your error code is: UNKNOWN-API-AUTH-SESSIONSAVE.")
return return
} }
if exchangeKey != "" { if randomBytes != "" {
c.Redirect(302, redirect_uri+"?code="+exchangeKey+"&state="+state) c.Redirect(302, redirect_uri+"?code="+randomBytes+"&state="+state)
} else { } else {
c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-REDIRECT.") c.String(500, "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-AUTH-REDIRECT.")
log.Println("[ERROR] Secret key not found at", strconv.FormatInt(time.Now().Unix(), 10)) log.Println("[ERROR] Secret key not found at", strconv.FormatInt(time.Now().Unix(), 10))
@ -971,8 +941,6 @@ func main() {
code_verify := data.Get("code_verifier") code_verify := data.Get("code_verifier")
secret := data.Get("client_secret") secret := data.Get("client_secret")
session := sessions.Default(c)
var verifyCode bool var verifyCode bool
if code_verify == "" { if code_verify == "" {
verifyCode = false verifyCode = false
@ -980,8 +948,9 @@ func main() {
verifyCode = true verifyCode = true
} }
var appIdCheck, secretCheck string var appIdCheck, secretCheck, openid, loginCode, PKCECode, PKCEMethod string
err = conn.QueryRow("SELECT appId, secret FROM oauth WHERE appId = ? LIMIT 1;", appId).Scan(&appIdCheck, &secretCheck)
err = conn.QueryRow("SELECT o.appId, o.secret, l.openid, l.code, l.pkce, l.pkcemethod FROM oauth AS o JOIN logins AS l ON o.appId = l.appId WHERE o.appId = ? AND l.secret = ? LIMIT 1;", appId, code).Scan(&appIdCheck, &secretCheck, &openid, &loginCode, &PKCECode, &PKCEMethod)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
c.JSON(401, gin.H{"error": "OAuth screening failed"}) c.JSON(401, gin.H{"error": "OAuth screening failed"})
@ -996,44 +965,6 @@ func main() {
return return
} }
activeLogin := session.Get("activeLogin")
if activeLogin == nil {
c.JSON(401, gin.H{"error": "The token has expired or was never created"})
return
}
var activeLoginMap map[string]any
err = json.Unmarshal([]byte(activeLogin.(string)), &activeLoginMap)
PKCECode, PKCEMethod, loginCode := activeLoginMap["PKCECode"].(string), activeLoginMap["PKCEMethod"].(string), activeLoginMap["exchangeKey"].(string)
if loginCode != code {
c.JSON(401, gin.H{"error": "Another login attempt is in progress or the login was never started"})
return
}
oauthCode, err := c.Cookie("oauthToken")
if err != nil {
if errors.Is(err, http.ErrNoCookie) {
c.JSON(401, gin.H{"error": "The token has expired or was never created"})
return
} else {
log.Println("[ERROR] Unknown in /api/tokenauth oauth cookie at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-TOKENAUTH-OAUTHTOKEN"})
return
}
}
openid, err := c.Cookie("openIdToken")
if err != nil {
if errors.Is(err, http.ErrNoCookie) {
c.JSON(401, gin.H{"error": "The token has expired or was never created"})
return
} else {
log.Println("[ERROR] Unknown in /api/tokenauth openid cookie at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-TOKENAUTH-OAUTHTOKEN"})
return
}
}
if verifyCode { if verifyCode {
if PKCECode == "none" { if PKCECode == "none" {
c.JSON(400, gin.H{"error": "Attempted PKCECode exchange with non-PKCECode authentication"}) c.JSON(400, gin.H{"error": "Attempted PKCECode exchange with non-PKCECode authentication"})
@ -1041,16 +972,16 @@ func main() {
} else { } else {
if PKCEMethod == "S256" { if PKCEMethod == "S256" {
if sha256Base64(code_verify) != PKCECode { if sha256Base64(code_verify) != PKCECode {
c.JSON(403, gin.H{"error": "Invalid PKCECode"}) c.JSON(403, gin.H{"error": "Invalid PKCECode code"})
return return
} }
} else if PKCEMethod == "plain" { } else if PKCEMethod == "plain" {
if code_verify != PKCECode { if code_verify != PKCECode {
c.JSON(403, gin.H{"error": "Invalid PKCECode"}) c.JSON(403, gin.H{"error": "Invalid PKCECode code"})
return return
} }
} else { } else {
c.JSON(403, gin.H{"error": "Attempted PKCECode exchange without supported PKCECode verification method"}) c.JSON(403, gin.H{"error": "Attempted PKCECode exchange without supported PKCECode token method"})
return return
} }
} }
@ -1061,7 +992,14 @@ func main() {
} }
} }
c.JSON(200, gin.H{"access_token": oauthCode, "token_type": "bearer", "expires_in": 2592000, "id_token": openid}) _, err = conn.Exec("DELETE FROM logins WHERE code = ?", loginCode)
if err != nil {
log.Println("[ERROR] Unknown in /api/tokenauth delete at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-TOKENAUTH-DELETE"})
return
}
c.JSON(200, gin.H{"access_token": loginCode, "token_type": "bearer", "expires_in": 2592000, "id_token": openid})
}) })
router.POST("/api/deleteauth", func(c *gin.Context) { router.POST("/api/deleteauth", func(c *gin.Context) {
@ -1250,6 +1188,15 @@ func main() {
} }
} }
_, err = conn.Exec("DELETE FROM logins WHERE creator = ?", id)
if err != nil {
if !errors.Is(err, sql.ErrNoRows) {
log.Println("[ERROR] Unknown in /api/deleteaccount logins at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-DELETEACCT-LOGINS"})
return
}
}
_, err = conn.Exec("DELETE FROM oauth WHERE creator = ?", id) _, err = conn.Exec("DELETE FROM oauth WHERE creator = ?", id)
if err != nil { if err != nil {
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
@ -1262,7 +1209,7 @@ func main() {
_, err = conn.Exec("DELETE FROM users WHERE id = ?", id) _, err = conn.Exec("DELETE FROM users WHERE id = ?", id)
if err != nil { if err != nil {
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
log.Println("[ERROR] Unknown in /api/deleteuser users at", strconv.FormatInt(time.Now().Unix(), 10)+":", err) log.Println("[ERROR] Unknown in /api/deleteuser logins at", strconv.FormatInt(time.Now().Unix(), 10)+":", err)
c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-DELETEUSER-USERS"}) c.JSON(500, gin.H{"error": "Something went wrong on our end. Please report this bug at https://centrifuge.hectabit.org/hectabit/burgerauth and refer to the docs for more info. Your error code is: UNKNOWN-API-DELETEUSER-USERS"})
return return
} }