diff options
| author | Bobby <[email protected]> | 2026-02-11 14:53:34 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2026-02-11 14:53:34 +0530 |
| commit | 3360be86fb6a595659c17f272d0c6072e512c154 (patch) | |
| tree | 4b78aa8120909b596f219a0159a3532200a05b1a /controllers | |
| parent | d87e08e0fc5911b2ff40604944448e1f0aaa31b7 (diff) | |
| download | cafe-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.go | 129 |
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") } |
