feat: enhance JWT error handling by returning unauthorized status for missing or malformed JWT
Build and Release / release (push) Successful in 1m54s
Build and Release / release (push) Successful in 1m54s
This commit is contained in:
@@ -29,6 +29,60 @@ func NewAuthController(svc services.AuthService, oauth *oauth2.Config) *AuthCont
|
|||||||
return &AuthController{service: svc, oauth: oauth}
|
return &AuthController{service: svc, oauth: oauth}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authCookieSecure() bool {
|
||||||
|
return config.GetBoolConfigWithDefault("COOKIE_SECURE", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func authCookieDomain() string {
|
||||||
|
return config.GetConfigWithDefault("COOKIE_DOMAIN", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func authCookieSameSite() string {
|
||||||
|
if authCookieSecure() {
|
||||||
|
return "None"
|
||||||
|
}
|
||||||
|
return "Lax"
|
||||||
|
}
|
||||||
|
|
||||||
|
func setAuthCookie(c fiber.Ctx, name string, value string, duration time.Duration) {
|
||||||
|
cookie := &fiber.Cookie{
|
||||||
|
Name: name,
|
||||||
|
Value: value,
|
||||||
|
Expires: time.Now().Add(duration),
|
||||||
|
MaxAge: int(duration.Seconds()),
|
||||||
|
HTTPOnly: true,
|
||||||
|
Secure: authCookieSecure(),
|
||||||
|
SameSite: authCookieSameSite(),
|
||||||
|
Path: "/",
|
||||||
|
}
|
||||||
|
if domain := authCookieDomain(); domain != "" {
|
||||||
|
cookie.Domain = domain
|
||||||
|
}
|
||||||
|
c.Cookie(cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearAuthCookie(c fiber.Ctx, name string) {
|
||||||
|
cookie := &fiber.Cookie{
|
||||||
|
Name: name,
|
||||||
|
Value: "",
|
||||||
|
Expires: time.Now().Add(-time.Hour),
|
||||||
|
MaxAge: -1,
|
||||||
|
HTTPOnly: true,
|
||||||
|
Secure: authCookieSecure(),
|
||||||
|
SameSite: authCookieSameSite(),
|
||||||
|
Path: "/",
|
||||||
|
}
|
||||||
|
if domain := authCookieDomain(); domain != "" {
|
||||||
|
cookie.Domain = domain
|
||||||
|
}
|
||||||
|
c.Cookie(cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setAuthCookies(c fiber.Ctx, res *response.AuthResponse) {
|
||||||
|
setAuthCookie(c, "access_token", res.AccessToken, constants.AccessTokenDuration)
|
||||||
|
setAuthCookie(c, "refresh_token", res.RefreshToken, constants.RefreshTokenDuration)
|
||||||
|
}
|
||||||
|
|
||||||
// Signin godoc
|
// Signin godoc
|
||||||
// @Summary Sign in a user
|
// @Summary Sign in a user
|
||||||
// @Description Authenticate user credentials and return access/refresh tokens
|
// @Description Authenticate user credentials and return access/refresh tokens
|
||||||
@@ -61,25 +115,7 @@ func (h *AuthController) Signin(c fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
setAuthCookies(c, res)
|
||||||
Name: "access_token",
|
|
||||||
Value: res.AccessToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.AccessTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "refresh_token",
|
|
||||||
Value: res.RefreshToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.RefreshTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
||||||
Status: true,
|
Status: true,
|
||||||
@@ -118,25 +154,7 @@ func (h *AuthController) Signup(c fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
setAuthCookies(c, res)
|
||||||
Name: "access_token",
|
|
||||||
Value: res.AccessToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.AccessTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "refresh_token",
|
|
||||||
Value: res.RefreshToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.RefreshTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
||||||
Status: true,
|
Status: true,
|
||||||
@@ -184,25 +202,7 @@ func (h *AuthController) RefreshToken(c fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
setAuthCookies(c, res)
|
||||||
Name: "access_token",
|
|
||||||
Value: res.AccessToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.AccessTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "refresh_token",
|
|
||||||
Value: res.RefreshToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.RefreshTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
||||||
Status: true,
|
Status: true,
|
||||||
@@ -348,15 +348,20 @@ func (h *AuthController) GoogleLogin(c fiber.Ctx) error {
|
|||||||
b, _ := json.Marshal(data)
|
b, _ := json.Marshal(data)
|
||||||
encoded := base64.URLEncoding.EncodeToString(b)
|
encoded := base64.URLEncoding.EncodeToString(b)
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
oauthCookie := &fiber.Cookie{
|
||||||
Name: "oauth_state",
|
Name: "oauth_state",
|
||||||
Value: state,
|
Value: state,
|
||||||
Expires: time.Now().Add(15 * time.Minute),
|
Expires: time.Now().Add(15 * time.Minute),
|
||||||
|
MaxAge: int((15 * time.Minute).Seconds()),
|
||||||
HTTPOnly: true,
|
HTTPOnly: true,
|
||||||
Secure: true,
|
Secure: authCookieSecure(),
|
||||||
SameSite: "None",
|
SameSite: authCookieSameSite(),
|
||||||
Path: "/",
|
Path: "/",
|
||||||
})
|
}
|
||||||
|
if domain := authCookieDomain(); domain != "" {
|
||||||
|
oauthCookie.Domain = domain
|
||||||
|
}
|
||||||
|
c.Cookie(oauthCookie)
|
||||||
|
|
||||||
url := h.oauth.AuthCodeURL(encoded)
|
url := h.oauth.AuthCodeURL(encoded)
|
||||||
return c.Redirect().To(url)
|
return c.Redirect().To(url)
|
||||||
@@ -393,7 +398,7 @@ func (h *AuthController) GoogleCallback(c fiber.Ctx) error {
|
|||||||
return c.Status(401).JSON(fiber.Map{"error": "Invalid state"})
|
return c.Status(401).JSON(fiber.Map{"error": "Invalid state"})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ClearCookie("oauth_state")
|
clearAuthCookie(c, "oauth_state")
|
||||||
|
|
||||||
code := c.Query("code")
|
code := c.Query("code")
|
||||||
|
|
||||||
@@ -427,25 +432,7 @@ func (h *AuthController) GoogleCallback(c fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
setAuthCookies(c, res)
|
||||||
Name: "access_token",
|
|
||||||
Value: res.AccessToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.AccessTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "refresh_token",
|
|
||||||
Value: res.RefreshToken,
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
SameSite: "None",
|
|
||||||
Path: "/",
|
|
||||||
Expires: time.Now().Add(constants.RefreshTokenDuration),
|
|
||||||
})
|
|
||||||
|
|
||||||
allowed := map[string]bool{
|
allowed := map[string]bool{
|
||||||
"http://localhost:3000": true,
|
"http://localhost:3000": true,
|
||||||
@@ -491,23 +478,8 @@ func (h *AuthController) Logout(c fiber.Ctx) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
clearAuthCookie(c, "access_token")
|
||||||
Name: "access_token",
|
clearAuthCookie(c, "refresh_token")
|
||||||
Value: "",
|
|
||||||
Expires: time.Now().Add(-time.Hour),
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
Path: "/",
|
|
||||||
})
|
|
||||||
|
|
||||||
c.Cookie(&fiber.Cookie{
|
|
||||||
Name: "refresh_token",
|
|
||||||
Value: "",
|
|
||||||
Expires: time.Now().Add(-time.Hour),
|
|
||||||
HTTPOnly: true,
|
|
||||||
Secure: true,
|
|
||||||
Path: "/",
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
return c.Status(fiber.StatusOK).JSON(response.CommonResponse{
|
||||||
Status: true,
|
Status: true,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ func jwtSuccessRefresh() fiber.Handler {
|
|||||||
|
|
||||||
func jwtError(c fiber.Ctx, err error) error {
|
func jwtError(c fiber.Ctx, err error) error {
|
||||||
if err.Error() == "Missing or malformed JWT" {
|
if err.Error() == "Missing or malformed JWT" {
|
||||||
return c.Status(fiber.StatusBadRequest).
|
return c.Status(fiber.StatusUnauthorized).
|
||||||
JSON(response.CommonResponse{
|
JSON(response.CommonResponse{
|
||||||
Status: false,
|
Status: false,
|
||||||
Message: "Missing or malformed JWT",
|
Message: "Missing or malformed JWT",
|
||||||
|
|||||||
Reference in New Issue
Block a user