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-09-26 09:20:49 +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
|
|
|
|
}
|
|
|
|
|
|
|
|
type UserClaims struct {
|
|
|
|
jwt.RegisteredClaims
|
|
|
|
User AuthentikUser
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewEasyAuth(client Auth) (EasyAuth, error) {
|
|
|
|
e := EasyAuth{}
|
|
|
|
e.client = client
|
|
|
|
e.jwtSecret = []byte("hsajedogö")
|
|
|
|
return e, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2024-09-26 09:00:50 +00:00
|
|
|
return e.jwtSecret, nil
|
|
|
|
})
|
|
|
|
|
|
|
|
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(5 * time.Minute)
|
|
|
|
|
|
|
|
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)
|
|
|
|
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 09:45:47 +00:00
|
|
|
|
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 09:45:47 +00:00
|
|
|
}
|
|
|
|
|
2024-09-26 20:55:50 +00:00
|
|
|
http.Redirect(w, r, redirectUrlString, http.StatusTemporaryRedirect)
|
2024-09-26 09:45:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func getCookie(w http.ResponseWriter, r *http.Request, name string) (string, error) {
|
|
|
|
cookie, err := r.Cookie(name)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, http.ErrNoCookie) {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return cookie.Value, nil
|
2024-09-26 09:00:50 +00:00
|
|
|
}
|
|
|
|
|
2024-09-26 09:45:47 +00:00
|
|
|
func setCookie(w http.ResponseWriter, name, value string, expired time.Time) {
|
2024-09-26 09:00:50 +00:00
|
|
|
cookie := http.Cookie{}
|
|
|
|
cookie.Name = name
|
|
|
|
cookie.Value = value
|
|
|
|
cookie.Expires = expired
|
|
|
|
cookie.Path = "/"
|
|
|
|
cookie.MaxAge = int(time.Until(expired).Seconds())
|
|
|
|
cookie.Secure = true
|
|
|
|
cookie.HttpOnly = true
|
|
|
|
cookie.SameSite = http.SameSiteStrictMode
|
|
|
|
|
|
|
|
http.SetCookie(w, &cookie)
|
|
|
|
}
|