auth/easyauth.go

150 lines
3.4 KiB
Go
Raw Normal View History

2024-09-26 09:06:17 +00:00
package auth
2024-09-26 09:00:50 +00:00
import (
2024-09-26 20:55:50 +00:00
"context"
2024-11-21 18:26:13 +00:00
"errors"
2024-09-26 20:55:50 +00:00
"fmt"
2024-09-26 09:00:50 +00:00
"net/http"
"time"
2024-09-26 20:55:50 +00:00
session "github.com/go-session/session/v3"
2024-09-26 09:00:50 +00:00
"github.com/golang-jwt/jwt/v5"
)
type EasyAuth struct {
client Auth
JwtSecret []byte
TimeUntilJWTExpired time.Duration
2024-09-26 09:00:50 +00:00
}
type UserClaims struct {
jwt.RegisteredClaims
User AuthentikUser
}
func NewEasyAuth(client Auth) (EasyAuth, error) {
e := EasyAuth{}
e.client = client
e.JwtSecret = []byte("hsajedogö")
e.TimeUntilJWTExpired = 120 * time.Minute
2024-09-26 09:00:50 +00:00
return e, nil
}
func (e EasyAuth) CheckUser(w http.ResponseWriter, r *http.Request) (AuthentikUser, error) {
user, con, err := e.GetUser(w, r)
if err != nil {
return AuthentikUser{}, err
}
if !con {
return AuthentikUser{}, ErrUserNeedRedirect
}
return user, nil
}
2024-11-21 18:26:13 +00:00
func (e EasyAuth) Middelware(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
user, err := e.CheckUser(w, r)
if err != nil {
if !errors.Is(err, ErrUserNeedRedirect) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(fmt.Sprintf("panic doing auth: %v", err.Error())))
}
return
}
ctx := context.WithValue(r.Context(), "user", user)
next.ServeHTTP(w, r.WithContext(ctx)) // call ServeHTTP on the original handler
})
}
2024-09-26 09:00:50 +00:00
func (e EasyAuth) GetUser(w http.ResponseWriter, r *http.Request) (AuthentikUser, bool, error) {
2024-09-26 20:55:50 +00:00
store, err := session.Start(context.Background(), w, r)
2024-09-26 09:00:50 +00:00
if err != nil {
return AuthentikUser{}, false, err
}
2024-09-26 20:55:50 +00:00
if r.Method == http.MethodGet {
store.Set("url", r.URL.String())
2024-09-26 21:33:59 +00:00
store.Save()
2024-09-26 20:55:50 +00:00
}
jwtData, ok := store.Get("jwt")
if !ok {
2024-09-26 09:20:49 +00:00
e.redirectAuth(w, r)
2024-09-26 09:00:50 +00:00
return AuthentikUser{}, false, nil
}
2024-09-26 20:55:50 +00:00
jwtString := fmt.Sprintf("%s", jwtData)
parsedAccessToken, _ := jwt.ParseWithClaims(jwtString, &UserClaims{}, func(token *jwt.Token) (interface{}, error) {
return e.JwtSecret, nil
2024-09-26 09:00:50 +00:00
})
2024-09-26 23:12:34 +00:00
if !parsedAccessToken.Valid {
e.redirectAuth(w, r)
return AuthentikUser{}, false, nil
}
2024-09-26 09:00:50 +00:00
claims := parsedAccessToken.Claims.(*UserClaims)
return claims.User, true, nil
}
2024-09-26 09:20:49 +00:00
func (e EasyAuth) redirectAuth(w http.ResponseWriter, r *http.Request) error {
redirectURL, err := e.client.GetAuthorizationURL("")
if err != nil {
return err
}
http.Redirect(w, r, redirectURL, http.StatusTemporaryRedirect)
return nil
}
2024-09-26 09:00:50 +00:00
func (e EasyAuth) AuthHTTPHandler(w http.ResponseWriter, r *http.Request) {
token, err := e.client.GetTokenFromCode(r.URL.Query().Get("code"))
if err != nil {
panic(err) // TODO: Deal with error
}
user := AuthentikUser{}
err = e.client.GetUserInfo(token.AccessToken, &user)
if err != nil {
panic(err) // TODO: Deal with error
}
expired := time.Now().Add(e.TimeUntilJWTExpired)
2024-09-26 09:00:50 +00:00
claims := UserClaims{}
claims.Issuer = "EasyAuth"
claims.Subject = user.Nickname
claims.IssuedAt = jwt.NewNumericDate(time.Now())
claims.ExpiresAt = jwt.NewNumericDate(expired)
claims.NotBefore = jwt.NewNumericDate(time.Now())
claims.User = user
jwtToken := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
jwtString, err := jwtToken.SignedString(e.JwtSecret)
2024-09-26 09:00:50 +00:00
if err != nil {
panic(err) // TODO: Deal with error
}
2024-09-26 20:55:50 +00:00
store, err := session.Start(context.Background(), w, r)
2024-09-26 09:00:50 +00:00
if err != nil {
panic(err) // TODO: Deal with error
}
2024-09-26 20:55:50 +00:00
store.Set("jwt", jwtString)
2024-09-26 21:33:59 +00:00
store.Save()
2024-09-26 20:55:50 +00:00
redirectURL, ok := store.Get("url")
redirectUrlString := "/"
if ok {
redirectUrlString = fmt.Sprintf("%s", redirectURL)
}
2024-09-26 20:55:50 +00:00
http.Redirect(w, r, redirectUrlString, http.StatusTemporaryRedirect)
}