Loggest thine Stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

147 lines
3.7 KiB

package httpapi
import (
"encoding/base64"
"encoding/json"
"git.aiterp.net/stufflog3/stufflog3/entities"
"git.aiterp.net/stufflog3/stufflog3/models"
"git.aiterp.net/stufflog3/stufflog3/usecases/auth"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
type loginInput struct {
Username string `json:"username"`
Password string `json:"password"`
RefreshToken string `json:"refreshToken"`
}
type setupInput struct {
Username string `json:"username"`
Password string `json:"password"`
Session string `json:"session"`
}
func Auth(g *gin.RouterGroup, service *auth.Service) {
g.GET("", handler("user", func(c *gin.Context) (interface{}, error) {
token := c.GetHeader("Authorization")
if len(token) < 8 {
return nil, models.PermissionDeniedError{}
}
return service.Provider.ValidateToken(c.Request.Context(), token[7:]), nil
}))
g.POST("/login", handler("auth", func(c *gin.Context) (interface{}, error) {
input := &loginInput{}
err := c.BindJSON(input)
if err != nil {
return nil, models.BadInputError{
Object: "LoginInput",
Problem: "Invalid JSON: " + err.Error(),
}
}
return service.Provider.LoginUser(c.Request.Context(), input.Username, input.Password)
}))
g.POST("/refresh", handler("auth", func(c *gin.Context) (interface{}, error) {
input := &loginInput{}
err := c.BindJSON(input)
if err != nil {
return nil, models.BadInputError{
Object: "LoginInput",
Problem: "Invalid JSON: " + err.Error(),
}
}
token := c.GetHeader("Authorization")
if len(token) < 8 || input.RefreshToken == "" {
return nil, models.BadInputError{
Object: "LoginInput",
Problem: "Missing token(s)",
}
}
return service.Provider.RefreshUser(c.Request.Context(), token[7:], input.RefreshToken)
}))
g.POST("/setup", handler("auth", func(c *gin.Context) (interface{}, error) {
input := &setupInput{}
err := c.BindJSON(input)
if err != nil {
return nil, models.BadInputError{
Object: "LoginInput",
Problem: "Invalid JSON: " + err.Error(),
}
}
return service.Provider.SetupUser(c.Request.Context(), input.Session, input.Username, input.Password)
}))
}
func DummyMiddleware(auth *auth.Service, uuid string) gin.HandlerFunc {
return func(c *gin.Context) {
c.Request = c.Request.WithContext(
auth.ContextWithUser(c.Request.Context(), entities.User{ID: uuid}),
)
}
}
func abortRequest(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusUnauthorized, Error{
Code: http.StatusUnauthorized,
Message: "You're not supposed to be here!",
})
}
// TrustingJwtParserMiddleware is meant to be put behind an AWS API gateway that has already
// verified this token.
func TrustingJwtParserMiddleware(auth *auth.Service) gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
split := strings.Split(authHeader, ".")
if len(split) >= 3 {
data, err := base64.RawStdEncoding.DecodeString(split[1])
if err != nil {
abortRequest(c)
return
}
fields := make(map[string]interface{})
err = json.Unmarshal(data, &fields)
if err != nil {
abortRequest(c)
return
}
if sub, ok := fields["sub"].(string); ok {
c.Request = c.Request.WithContext(
auth.ContextWithUser(c.Request.Context(), entities.User{ID: sub}),
)
} else {
abortRequest(c)
return
}
} else {
abortRequest(c)
}
}
}
// JwtValidatorMiddleware does check the JWT against the provider.
func JwtValidatorMiddleware(s *auth.Service) gin.HandlerFunc {
return func(c *gin.Context) {
header := c.GetHeader("Authorization")
if header != "" {
user := s.ValidateUser(c.Request.Context(), header[7:])
if user != nil {
c.Request = c.Request.WithContext(
s.ContextWithUser(c.Request.Context(), *user),
)
}
}
}
}