github.com/soulteary/pocket-bookcase@v0.0.0-20240428065142-0b5a9a0fc98a/internal/http/middleware/auth.go (about)

     1  package middleware
     2  
     3  import (
     4  	"net/http"
     5  	"strings"
     6  
     7  	"github.com/gin-gonic/gin"
     8  	"github.com/soulteary/pocket-bookcase/internal/dependencies"
     9  	"github.com/soulteary/pocket-bookcase/internal/http/context"
    10  	"github.com/soulteary/pocket-bookcase/internal/http/response"
    11  	"github.com/soulteary/pocket-bookcase/internal/model"
    12  )
    13  
    14  // AuthMiddleware provides basic authentication capabilities to all routes underneath
    15  // its usage, only allowing authenticated users access and set a custom local context
    16  // `account` with the account model for the logged in user.
    17  func AuthMiddleware(deps *dependencies.Dependencies) gin.HandlerFunc {
    18  	return func(c *gin.Context) {
    19  		token := getTokenFromHeader(c)
    20  		if token == "" {
    21  			token = getTokenFromCookie(c)
    22  		}
    23  
    24  		account, err := deps.Domains.Auth.CheckToken(c, token)
    25  		if err != nil {
    26  			return
    27  		}
    28  
    29  		c.Set(model.ContextAccountKey, account)
    30  	}
    31  }
    32  
    33  // AuthenticationRequired provides a middleware that checks if the user is logged in, returning
    34  // a 401 error if not.
    35  func AuthenticationRequired() gin.HandlerFunc {
    36  	return func(c *gin.Context) {
    37  		ctx := context.NewContextFromGin(c)
    38  		if !ctx.UserIsLogged() {
    39  			response.SendError(c, http.StatusUnauthorized, nil)
    40  			return
    41  		}
    42  	}
    43  }
    44  
    45  // getTokenFromHeader returns the token from the Authorization header, if any.
    46  func getTokenFromHeader(c *gin.Context) string {
    47  	authorization := c.GetHeader(model.AuthorizationHeader)
    48  	if authorization == "" {
    49  		return ""
    50  	}
    51  
    52  	authParts := strings.SplitN(authorization, " ", 2)
    53  	if len(authParts) != 2 && authParts[0] != model.AuthorizationTokenType {
    54  		return ""
    55  	}
    56  
    57  	return authParts[1]
    58  }
    59  
    60  // getTokenFromCookie returns the token from the token cookie, if any.
    61  func getTokenFromCookie(c *gin.Context) string {
    62  	cookie, err := c.Cookie("token")
    63  	if err != nil {
    64  		return ""
    65  	}
    66  
    67  	return cookie
    68  }