Skip to content

Requests missing the jwt do not result in 401 Unauthorized but instead in 400 Bad Request #38

Description

@turtletramp

In jwt.go:117 a custom error exists for this purpose to return 401

// ErrJWTMissing denotes an error raised when JWT token value could not be extracted from request
var ErrJWTMissing = echo.NewHTTPError(http.StatusUnauthorized, "missing or malformed jwt")

But when trying to extract the jwt instead of returning ErrJWTMissing another new error is created and returned with status 400.

jwt.go.258

if lastTokenErr == nil {
	return echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt").SetInternal(err)
}

I think the intention is to do the following instead

if lastTokenErr == nil {
	return ErrJWTMissing.SetInternal(err)
}

... not sure about the .SetInternal(err) though

This behavior seems to be against the definition of 401. Or is there a reason for that?

Activity

  1. aldas commented on Oct 21, 2025

    @aldas
    Contributor

    You definitely should not do ErrJWTMissing.SetInternal(err) because ErrJWTMissing is global and you could introduce data race by mutating it with SetInternal. This is because Go standard library HTTP server runs each request in separate goroutine.

  2. aldas commented on Oct 21, 2025

    @aldas
    Contributor

    have you tried creating your own config.ErrorHandler function and return whatever suits you?

  3. turtletramp commented on Nov 14, 2025

    @turtletramp
    Author

    Using the config.ErrorHandler works of course and is what I did for now.
    And you are right about the data race. Was stupid of myself sorry.

    But my main point is that it seems to me that echo-jwt is not reacting correctly on a missing jwt when looking at the mozilla definition: https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401

    Image

    Which means instead of this:

    			if lastTokenErr == nil {
    				return echo.NewHTTPError(http.StatusBadRequest, "missing or malformed jwt").SetInternal(err)
    			}
    
    
    			return echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt").SetInternal(err)

    We should do this

    			if lastTokenErr == nil {
    				// changing StatusBadRequest-->StatusUnauthorized
    				return echo.NewHTTPError(http.StatusUnauthorized, "missing or malformed jwt").SetInternal(err)
    			}
    
    
    			return echo.NewHTTPError(http.StatusUnauthorized, "invalid or expired jwt").SetInternal(err)

    Do you agree (which means I could provide a simple PR if wanted) or is there a reason why it should still return StatusBadRequest and not follow the Mozilla definition?

  4. aldas commented on Nov 20, 2025

    @aldas
    Contributor

    Next minor version will revert back to 401. See #39

  5. turtletramp commented on Nov 21, 2025

    @turtletramp
    Author

    Great and thanks for the update!

  6. aldas commented on Nov 21, 2025

    @aldas
    Contributor

    I'll tag/release new version on Monday. So those at work will not have Friday surprises and potential weekend incidents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions