summaryrefslogtreecommitdiff
path: root/controllers
diff options
context:
space:
mode:
authorBobby <[email protected]>2026-02-11 14:53:34 +0530
committerBobby <[email protected]>2026-02-11 14:53:34 +0530
commit3360be86fb6a595659c17f272d0c6072e512c154 (patch)
tree4b78aa8120909b596f219a0159a3532200a05b1a /controllers
parentd87e08e0fc5911b2ff40604944448e1f0aaa31b7 (diff)
downloadcafe-3360be86fb6a595659c17f272d0c6072e512c154.tar.xz
cafe-3360be86fb6a595659c17f272d0c6072e512c154.zip
Implement OpenID authentication flow, including user session management and user info retrieval
Diffstat (limited to 'controllers')
-rw-r--r--controllers/auth.go129
1 files changed, 123 insertions, 6 deletions
diff --git a/controllers/auth.go b/controllers/auth.go
index 2d8d89b..964a22a 100644
--- a/controllers/auth.go
+++ b/controllers/auth.go
@@ -1,19 +1,136 @@
package controllers
import (
+ "cafe/models"
+ "cafe/repositories"
+ "cafe/services/openid"
+ "cafe/session"
"cafe/utils/auth"
- "cafe/utils/meta"
"cafe/utils/shortcuts"
+ "context"
+ "errors"
+ "log"
"github.com/gofiber/fiber/v2"
)
-func Authenticate(context *fiber.Ctx) error {
- if auth.IsAuthenticated(context) {
- return shortcuts.Redirect(context, "mainHall")
+func Login(ctx *fiber.Ctx) error {
+ if auth.IsAuthenticated(ctx) {
+ return shortcuts.Redirect(ctx, "mainHall")
}
- meta.SetPageTitle(context, "Open ID Authentication")
+ state, err := openid.GenerateState()
+ if err != nil {
+ log.Printf("Failed to generate state: %v", err)
+ return InternalServerError(ctx, errors.New("We couldn't start the login process. Please try again."))
+ }
+
+ sess, err := session.Store.Get(ctx)
+ if err != nil {
+ log.Printf("Failed to get session: %v", err)
+ return InternalServerError(ctx, errors.New("There was a problem with your session. Please try logging in again."))
+ }
+ sess.Set("oauth_state", state)
+ if err := sess.Save(); err != nil {
+ log.Printf("Failed to save session: %v", err)
+ return InternalServerError(ctx, errors.New("There was a problem with your session. Please try logging in again."))
+ }
+
+ authURL := openid.GetAuthURL(state)
+ return ctx.Redirect(authURL)
+}
+
+func Callback(ctx *fiber.Ctx) error {
+ state := ctx.Query("state")
+ code := ctx.Query("code")
+
+ if state == "" || code == "" {
+ return BadRequest(ctx, errors.New("The login response was incomplete. Please try logging in again."))
+ }
+
+ sess, err := session.Store.Get(ctx)
+ if err != nil {
+ log.Printf("Failed to get session: %v", err)
+ return InternalServerError(ctx, errors.New("There was a problem with your session. Please try logging in again."))
+ }
+
+ savedState := sess.Get("oauth_state")
+ if savedState == nil || savedState.(string) != state {
+ return Unauthorized(ctx, errors.New("Your login request could not be verified. Please try again."))
+ }
+
+ sess.Delete("oauth_state")
+
+ c := context.Background()
+ oauth2Token, err := openid.ExchangeCode(c, code)
+ if err != nil {
+ log.Printf("Failed to exchange code: %v", err)
+ return Unauthorized(ctx, errors.New("We couldn't verify your login with Cloudron. Please try again."))
+ }
+
+ rawIDToken, ok := oauth2Token.Extra("id_token").(string)
+ if !ok {
+ log.Printf("No id_token in response")
+ return Unauthorized(ctx, errors.New("Your login was incomplete. Please try again."))
+ }
+
+ idToken, err := openid.VerifyIDToken(c, rawIDToken)
+ if err != nil {
+ log.Printf("Failed to verify ID token: %v", err)
+ return Unauthorized(ctx, errors.New("We couldn't verify your identity. Please try logging in again."))
+ }
+
+ userInfo, err := openid.GetUserInfo(c, oauth2Token, idToken)
+ if err != nil {
+ log.Printf("Failed to extract user info: %v", err)
+ return InternalServerError(ctx, errors.New("We couldn't retrieve your account information. Please try again."))
+ }
+
+ user, err := repositories.GetUserByOpenID(userInfo.Sub)
+ isAdminUser := openid.IsAdmin(userInfo)
+
+ if err != nil {
+ user = &models.User{
+ OpenID: userInfo.Sub,
+ Username: userInfo.PreferredUsername,
+ Email: userInfo.Email,
+ DisplayName: userInfo.Name,
+ IsAdmin: isAdminUser,
+ }
+
+ if err := repositories.CreateUser(user); err != nil {
+ log.Printf("Failed to create user: %v", err)
+ return InternalServerError(ctx, errors.New("We couldn't create your account. Please contact an administrator."))
+ }
+ } else {
+ user.Email = userInfo.Email
+ user.DisplayName = userInfo.Name
+ user.IsAdmin = isAdminUser
+ if err := repositories.UpdateUser(user); err != nil {
+ log.Printf("Failed to update user: %v", err)
+ }
+ }
+
+ sess.Set("username", user.Username)
+
+ if err := sess.Save(); err != nil {
+ log.Printf("Failed to save session: %v", err)
+ return InternalServerError(ctx, errors.New("We couldn't complete your login. Please try again."))
+ }
+
+ return shortcuts.Redirect(ctx, "mainHall")
+}
+
+func Logout(ctx *fiber.Ctx) error {
+ sess, err := session.Store.Get(ctx)
+ if err != nil {
+ log.Printf("Failed to get session: %v", err)
+ return shortcuts.Redirect(ctx, "mainHall")
+ }
+
+ if err := sess.Destroy(); err != nil {
+ log.Printf("Failed to destroy session: %v", err)
+ }
- return shortcuts.Render(context, "pages/auth", nil)
+ return shortcuts.Redirect(ctx, "mainHall")
}