Repository: labstack/echo (go)

Issue:
BasicAuth middleware returns 500 InternalServerError on invalid base64 strings
### Issue Description

When using the provided BasicAuth middleware handler, it returns `500 InternalServerError` when the authorization string is not base64. This is just bad input, so I expected to get a 401 instead of an unexpected 500.

Didn't do a deep dive testing, but I assume this is because [the middleware code just returns the base64 decode error](https://github.com/labstack/echo/blob/master/middleware/basic_auth.go#L77). I can do a PR if we want to just change it to a 401.

### Checklist

- [x] Dependencies installed
- [x] No typos
- [x] Searched existing issues and docs

### Expected behaviour

I expected `401 Not Authorized`

### Actual behaviour

`500 InternalServerError` 

### Steps to reproduce

Compile the code below, run the executable, and then execute the following commands. Notice the second curl has a slightly modified auth string.

```
$ echo "username:password" | base64
dXNlcm5hbWU6cGFzc3dvcmQK
$ curl localhost:1234 -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQK"
all good%
$ curl localhost:1234 -H "Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ"
{"message":"Internal Server Error"}
```

### Working code to debug

```go
package main

import (
	"net/http"

	echo "github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	e := echo.New()
	e.Use(
		middleware.BasicAuth(
			func(username, password string, ctx echo.Context) (bool, error) {
				return true, nil
			},
		),
	)
	e.GET("/", func(ctx echo.Context) error {
		return ctx.String(http.StatusOK, "all good")
	})
	e.Start("localhost:1234")
}

```

### Version/commit
github.com/labstack/echo/v4 v4.7.2
go version go1.18.1 darwin/amd64

Pull request description:
fix: basic auth invalid base64 string
fixes #2170

Patch:
diff --git a/middleware/basic_auth.go b/middleware/basic_auth.go
index 8cf1ed9..52ef104 100644
--- a/middleware/basic_auth.go
+++ b/middleware/basic_auth.go
@@ -4,6 +4,7 @@ import (
 	"encoding/base64"
 	"strconv"
 	"strings"
+	"net/http"
 
 	"github.com/labstack/echo/v4"
 )
@@ -74,10 +75,13 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc {
 			l := len(basic)
 
 			if len(auth) > l+1 && strings.EqualFold(auth[:l], basic) {
+				// Invalid base64 shouldn't be treated as error
+				// instead should be treated as invalid client input
 				b, err := base64.StdEncoding.DecodeString(auth[l+1:])
 				if err != nil {
-					return err
+					return echo.NewHTTPError(http.StatusBadRequest).SetInternal(err)
 				}
+
 				cred := string(b)
 				for i := 0; i < len(cred); i++ {
 					if cred[i] == ':' {


Test patch:
diff --git a/middleware/basic_auth_test.go b/middleware/basic_auth_test.go
index 76039db..4c355aa 100644
--- a/middleware/basic_auth_test.go
+++ b/middleware/basic_auth_test.go
@@ -58,6 +58,12 @@ func TestBasicAuth(t *testing.T) {
 	assert.Equal(http.StatusUnauthorized, he.Code)
 	assert.Equal(basic+` realm="someRealm"`, res.Header().Get(echo.HeaderWWWAuthenticate))
 
+	// Invalid base64 string
+	auth = basic + " invalidString"
+	req.Header.Set(echo.HeaderAuthorization, auth)
+	he = h(c).(*echo.HTTPError)
+	assert.Equal(http.StatusBadRequest, he.Code)
+
 	// Missing Authorization header
 	req.Header.Del(echo.HeaderAuthorization)
 	he = h(c).(*echo.HTTPError)