Jade/login.go
2024-05-09 19:20:14 +02:00

119 lines
3.5 KiB
Go

package main
import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
"github.com/gofiber/fiber/v2"
)
const EDGEDB_AUTH_BASE_URL = "http://127.0.0.1:10700/db/main/ext/auth"
func generatePKCE() (string, string) {
fmt.Println("Generating PKCE")
verifier := make([]byte, 32)
_, err := rand.Read(verifier)
if err != nil {
panic(err)
}
challenge := sha256.Sum256(verifier)
var URLEncoding = base64.NewEncoding("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_")
var RawURLEncoding = URLEncoding.WithPadding(base64.NoPadding)
encodedVerifier := RawURLEncoding.EncodeToString(verifier)
encodedChallenge := RawURLEncoding.EncodeToString(challenge[:])
fmt.Println("verifier: " + encodedVerifier)
fmt.Println("challenge: " + encodedChallenge)
return encodedVerifier, encodedChallenge
}
func handleUiSignIn(c *fiber.Ctx) error {
verifier, challenge := generatePKCE()
fmt.Println("handleUiSignIn verifier: " + verifier)
fmt.Println("handleUiSignIn challenge: " + challenge)
cookie := new(fiber.Cookie)
cookie.Name = "jade-edgedb-pkce-verifier"
cookie.Value = verifier
cookie.Expires = time.Now().Add(10 * time.Minute)
c.Cookie(cookie)
return c.Redirect(fmt.Sprintf("%s/ui/signup?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge), fiber.StatusTemporaryRedirect)
}
func handleUiSignUp(c *fiber.Ctx) error {
verifier, challenge := generatePKCE()
fmt.Println("handleUiSignUp verifier: " + verifier)
fmt.Println("handleUiSignUp challenge: " + challenge)
cookie := new(fiber.Cookie)
cookie.Name = "jade-edgedb-pkce-verifier"
cookie.Value = verifier
cookie.Expires = time.Now().Add(10 * time.Minute)
c.Cookie(cookie)
return c.Redirect(fmt.Sprintf("%s/ui/signup?challenge=%s", EDGEDB_AUTH_BASE_URL, challenge), fiber.StatusTemporaryRedirect)
}
func handleCallback(c *fiber.Ctx) error {
code := c.Query("code")
if code == "" {
error := c.Query("error")
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("OAuth callback is missing 'code'. OAuth provider responded with error: %s", error))
}
verifier := c.Cookies("jade-edgedb-pkce-verifier")
if verifier == "" {
return c.Status(fiber.StatusBadRequest).SendString("Could not find 'verifier' in the cookie store. Is this the same user agent/browser that started the authorization flow?")
}
fmt.Println("handleCallback code: " + code)
fmt.Println("handleCallback verifier: " + verifier)
codeExchangeURL := fmt.Sprintf("%s/token?code=%s&verifier=%s", EDGEDB_AUTH_BASE_URL, code, verifier)
fmt.Println("codeExchangeURL: " + codeExchangeURL)
resp, err := http.Get(codeExchangeURL)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", err.Error()))
}
defer resp.Body.Close()
if resp.StatusCode != fiber.StatusOK {
body, _ := io.ReadAll(resp.Body)
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error from the auth server: %s", string(body)))
}
var tokenResponse struct {
AuthToken string `json:"auth_token"`
}
err = json.NewDecoder(resp.Body).Decode(&tokenResponse)
if err != nil {
return c.Status(fiber.StatusBadRequest).SendString(fmt.Sprintf("Error decoding auth server response: %s", err.Error()))
}
c.Cookie(&fiber.Cookie{
Name: "edgedb-auth-token",
Value: tokenResponse.AuthToken,
HTTPOnly: true,
Path: "/",
Secure: true,
SameSite: "Strict",
})
fmt.Println("Login successful")
fmt.Println("edgedb-auth-token: " + tokenResponse.AuthToken)
return c.SendStatus(fiber.StatusNoContent)
}