2023-10-28 19:25:51 -04:00
|
|
|
package controllers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"git.preston-baxter.com/Preston_PLB/capstone/frontend-service/config"
|
2023-11-03 01:01:33 -04:00
|
|
|
"git.preston-baxter.com/Preston_PLB/capstone/frontend-service/db/models"
|
2023-10-28 19:25:51 -04:00
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
|
|
)
|
|
|
|
|
2023-10-29 19:10:32 -04:00
|
|
|
const USER_OBJ_KEY = "userObj"
|
|
|
|
|
2023-10-28 19:25:51 -04:00
|
|
|
type AuthClaims struct {
|
|
|
|
Subject string `json:"sub"`
|
|
|
|
Expires int64 `json:"exp"`
|
|
|
|
IssuedAt int64 `json:"iat"`
|
|
|
|
NotBefore int64 `json:"nbf"`
|
|
|
|
Issuer string `json:"iss"`
|
|
|
|
Audience string `json:"aud"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetExpirationTime() (*jwt.NumericDate, error) {
|
|
|
|
time := time.Unix(claims.Expires, 0)
|
|
|
|
return jwt.NewNumericDate(time), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetIssuedAt() (*jwt.NumericDate, error) {
|
|
|
|
time := time.Unix(claims.IssuedAt, 0)
|
|
|
|
return jwt.NewNumericDate(time), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetNotBefore() (*jwt.NumericDate, error) {
|
|
|
|
time := time.Unix(claims.NotBefore, 0)
|
|
|
|
return jwt.NewNumericDate(time), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetIssuer() (string, error) {
|
|
|
|
return claims.Issuer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetSubject() (string, error) {
|
|
|
|
return claims.Subject, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (claims AuthClaims) GetAudience() (jwt.ClaimStrings, error) {
|
|
|
|
return []string{claims.Subject}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func AuthMiddleware(strict bool) gin.HandlerFunc {
|
|
|
|
conf := config.Config()
|
|
|
|
return func(c *gin.Context) {
|
|
|
|
//check for cookie
|
|
|
|
token, err := c.Cookie("authorization")
|
|
|
|
if err != nil {
|
|
|
|
if err == http.ErrNoCookie {
|
|
|
|
if strict {
|
|
|
|
c.Redirect(301, "/login")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.WithError(err).Error("Unable to get cookie from browser")
|
|
|
|
c.AbortWithError(504, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
claims := &AuthClaims{}
|
|
|
|
|
|
|
|
parsedToken, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (any, error) {
|
|
|
|
return []byte(conf.JwtSecret), nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
2023-11-01 22:40:50 -04:00
|
|
|
if err == jwt.ErrTokenExpired {
|
2023-10-29 18:56:05 -04:00
|
|
|
log.Warn("Redirecting, jwt expired")
|
2023-10-28 19:25:51 -04:00
|
|
|
c.Redirect(301, "/login")
|
|
|
|
return
|
2023-11-01 22:40:50 -04:00
|
|
|
} else {
|
2023-10-29 18:56:05 -04:00
|
|
|
if strict {
|
|
|
|
log.Warnf("Redirecting, jwt issue: %s", err)
|
|
|
|
c.Redirect(301, "/login")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
log.Warnf("Jwt is invalid, but auth is not strict. Reason: %s", err)
|
|
|
|
return
|
|
|
|
}
|
2023-10-28 19:25:51 -04:00
|
|
|
}
|
|
|
|
}
|
2023-10-29 18:56:05 -04:00
|
|
|
|
2023-11-01 22:40:50 -04:00
|
|
|
if !parsedToken.Valid {
|
2023-10-28 19:25:51 -04:00
|
|
|
if strict {
|
|
|
|
log.Warn("Redirecting, jwt invalid")
|
|
|
|
c.Redirect(301, "/login")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
log.Warn("Jwt is invalid, but auth is not strict")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
user, err := mongo.FindUserById(claims.Subject)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Errorf("Unable to get user: %s from DB", claims.Subject)
|
2023-11-02 21:06:35 -04:00
|
|
|
c.AbortWithError(502, err)
|
2023-10-28 19:25:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if user == nil {
|
|
|
|
log.Errorf("Unable to find user: %s in DB", claims.Subject)
|
2023-11-02 21:06:35 -04:00
|
|
|
c.AbortWithError(502, nil)
|
2023-10-28 19:25:51 -04:00
|
|
|
}
|
|
|
|
|
2023-10-29 19:10:32 -04:00
|
|
|
//store user object reference in session.
|
|
|
|
c.Set(USER_OBJ_KEY, user)
|
2023-10-28 19:25:51 -04:00
|
|
|
}
|
|
|
|
}
|
2023-11-03 01:01:33 -04:00
|
|
|
|
|
|
|
func getUserFromContext(c *gin.Context) *models.User {
|
|
|
|
if raw, exists := c.Get(USER_OBJ_KEY); exists {
|
|
|
|
if user, ok := raw.(*models.User); ok {
|
|
|
|
return user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|