119 lines
3.5 KiB
Go
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)
|
|
}
|