Skip to content

Commit

Permalink
feat: added AuthenticateFromHeader and AuthenticateFromCookie functio…
Browse files Browse the repository at this point in the history
…ns to Authenticator interface and implementation

* Added AuthenticateFromHeader and AuthenticateFromCookie functions to Authenticator interface and implementation
* Upgraded dependencies
  • Loading branch information
ralvarezdev committed Feb 1, 2025
1 parent f1af465 commit 46814f5
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 15 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.23.4

require (
github.com/ralvarezdev/go-flags v0.3.2
github.com/ralvarezdev/go-jwt v0.4.9
github.com/ralvarezdev/go-jwt v0.4.10
github.com/ralvarezdev/go-logger v0.4.6
github.com/ralvarezdev/go-reflect v0.2.4
github.com/ralvarezdev/go-validator v0.5.29
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ github.com/ralvarezdev/go-flags v0.3.2 h1:l3f62CD5NysLAJH5XqSRGiakU/dn4pTGdX4yaB
github.com/ralvarezdev/go-flags v0.3.2/go.mod h1:R3yVBYvzwqfOp26LidaiJ/zftVAnPC3pKunVpV/vosE=
github.com/ralvarezdev/go-jwt v0.4.9 h1:YPXGm05uhLaQgVHMYYGFLoAU4knt/MriB6yDEJl7x5k=
github.com/ralvarezdev/go-jwt v0.4.9/go.mod h1:/6Bd1Y/5+x5bjoaZXEHuRSntK0od4nNIzJF+s4SFBAs=
github.com/ralvarezdev/go-jwt v0.4.10/go.mod h1:/6Bd1Y/5+x5bjoaZXEHuRSntK0od4nNIzJF+s4SFBAs=
github.com/ralvarezdev/go-logger v0.4.6 h1:eZalm0WAdNuhzbaVh5D7gC6AFztdpqE/GQfjH2pipyE=
github.com/ralvarezdev/go-logger v0.4.6/go.mod h1:zxuMDHqtV2eoJYtmo219lima0ZSk4p/AGj/cCc390P8=
github.com/ralvarezdev/go-reflect v0.2.4 h1:PLyzbrdNvUiRzpxSHuI9b7hJEhFes22gjNLZkbjn5AQ=
Expand Down
5 changes: 5 additions & 0 deletions http/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import (
)

var (
ErrCodeCookieNotFound *string
)

var (
ErrCookieNotFound = errors.New("cookie not found")
ErrNilRequestBody = errors.New("request body cannot be nil")
ErrInvalidRequestBody = "invalid request body type, expected: %v"
ErrInDevelopment = errors.New("in development")
Expand Down
12 changes: 10 additions & 2 deletions http/middleware/auth/authenticator.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package auth

import (
gojwtinterception "github.com/ralvarezdev/go-jwt/token/interception"
gojwttoken "github.com/ralvarezdev/go-jwt/token"
"net/http"
)

// Authenticator interface
type Authenticator interface {
Authenticate(
interception gojwtinterception.Interception,
token gojwttoken.Token,
rawToken string,
) func(next http.Handler) http.Handler
AuthenticateFromHeader(
token gojwttoken.Token,
) func(next http.Handler) http.Handler
AuthenticateFromCookie(
token gojwttoken.Token,
cookieName string,
) func(next http.Handler) http.Handler
}
76 changes: 64 additions & 12 deletions http/middleware/auth/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
gojwt "github.com/ralvarezdev/go-jwt"
gojwtnethttp "github.com/ralvarezdev/go-jwt/net/http"
gojwtnethttpctx "github.com/ralvarezdev/go-jwt/net/http/context"
gojwtinterception "github.com/ralvarezdev/go-jwt/token/interception"
gojwttoken "github.com/ralvarezdev/go-jwt/token"
gojwtvalidator "github.com/ralvarezdev/go-jwt/token/validator"
gonethttp "github.com/ralvarezdev/go-net/http"
gonethttphandler "github.com/ralvarezdev/go-net/http/handler"
gonethttpjwtvalidator "github.com/ralvarezdev/go-net/http/jwt/validator"
gonethttpresponse "github.com/ralvarezdev/go-net/http/response"
"net/http"
"strings"
)
Expand Down Expand Up @@ -45,7 +47,35 @@ func NewMiddleware(

// Authenticate return the middleware function that authenticates the request
func (m *Middleware) Authenticate(
interception gojwtinterception.Interception,
token gojwttoken.Token,
rawToken string,
) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Validate the token and get the validated claims
claims, err := m.validator.ValidateClaims(
rawToken,
token,
)
if err != nil {
m.jwtValidatorFailHandler(w, err)
return
}

// Set the token claims to the context
r = gojwtnethttpctx.SetCtxTokenClaims(r, claims)

// Call the next handler
next.ServeHTTP(w, r)
},
)
}
}

// AuthenticateFromHeader return the middleware function that authenticates the request from the header
func (m *Middleware) AuthenticateFromHeader(
token gojwttoken.Token,
) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(
Expand All @@ -68,21 +98,43 @@ func (m *Middleware) Authenticate(
// Get the raw token from the header
rawToken := parts[1]

// Validate the token and get the validated claims
claims, err := m.validator.GetValidatedClaims(
rawToken,
interception,
)
// Call the Authenticate function
m.Authenticate(token, rawToken)(next).ServeHTTP(w, r)
},
)
}
}

// AuthenticateFromCookie return the middleware function that authenticates the request from the cookie
func (m *Middleware) AuthenticateFromCookie(
token gojwttoken.Token,
cookieName string,
) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
// Get the cookie
cookie, err := r.Cookie(cookieName)

// Return an error if the cookie is missing
if err != nil {
m.jwtValidatorFailHandler(w, err)
m.jwtValidatorFailHandler(
w,
gonethttpresponse.NewCookieError(
cookieName,
gonethttp.ErrCookieNotFound,
http.StatusUnauthorized,
gonethttp.ErrCodeCookieNotFound,
),
)
return
}

// Set the token claims to the context
r = gojwtnethttpctx.SetCtxTokenClaims(r, claims)
// Get the raw token from the cookie
rawToken := cookie.Value

// Call the next handler
next.ServeHTTP(w, r)
// Call the Authenticate function
m.Authenticate(token, rawToken)(next).ServeHTTP(w, r)
},
)
}
Expand Down
40 changes: 40 additions & 0 deletions http/response/request_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ type (
httpStatus int
errorCode *string
}

// CookieError struct
CookieError struct {
name string
err string
httpStatus int
errorCode *string
}
)

// NewFieldError creates a new field error
Expand Down Expand Up @@ -90,6 +98,38 @@ func (h *HeaderError) ErrorCode() *string {
return h.errorCode
}

// NewCookieError creates a new cookie error
func NewCookieError(
name, err string, httpStatus int, errorCode *string,
) *CookieError {
return &CookieError{
name,
err,
httpStatus,
errorCode,
}
}

// Name returns the cookie name
func (c *CookieError) Name() string {
return c.name
}

// Error returns the cookie error as a string
func (c *CookieError) Error() string {
return c.err
}

// HTTPStatus returns the HTTP status
func (c *CookieError) HTTPStatus() int {
return c.httpStatus
}

// ErrorCode returns the error code
func (c *CookieError) ErrorCode() *string {
return c.errorCode
}

// NewRequestErrorBodyData creates a new request errors body data
func NewRequestErrorBodyData(
requestError RequestError,
Expand Down

0 comments on commit 46814f5

Please sign in to comment.