2024-03-09 11:21:24 +02:00
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// SPDX-FileCopyrightText: © 2015 LabStack LLC and Echo contributors
|
|
|
|
|
2016-04-28 06:08:06 +02:00
|
|
|
package middleware
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
2024-10-16 21:37:13 +02:00
|
|
|
"errors"
|
2016-04-28 06:08:06 +02:00
|
|
|
"net/http"
|
2016-09-23 07:53:44 +02:00
|
|
|
"net/http/httptest"
|
2017-11-21 01:57:41 +02:00
|
|
|
"strings"
|
2016-04-28 06:08:06 +02:00
|
|
|
"testing"
|
|
|
|
|
2019-01-30 12:56:56 +02:00
|
|
|
"github.com/labstack/echo/v4"
|
2016-04-28 06:08:06 +02:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestBasicAuth(t *testing.T) {
|
|
|
|
e := echo.New()
|
2024-10-16 21:37:13 +02:00
|
|
|
|
|
|
|
mockValidator := func(u, p string, c echo.Context) (bool, error) {
|
2016-04-28 06:08:06 +02:00
|
|
|
if u == "joe" && p == "secret" {
|
2017-05-27 12:10:51 +02:00
|
|
|
return true, nil
|
2016-04-28 06:08:06 +02:00
|
|
|
}
|
2017-05-27 12:10:51 +02:00
|
|
|
return false, nil
|
2016-04-28 06:08:06 +02:00
|
|
|
}
|
2018-02-21 20:44:17 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
// Define the test cases
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
authHeader string
|
|
|
|
expectedCode int
|
|
|
|
expectedAuth string
|
|
|
|
skipperResult bool
|
|
|
|
expectedErr bool
|
|
|
|
expectedErrMsg string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Valid credentials",
|
|
|
|
authHeader: basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")),
|
|
|
|
expectedCode: http.StatusOK,
|
|
|
|
skipperResult: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Case-insensitive header scheme",
|
|
|
|
authHeader: strings.ToUpper(basic) + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")),
|
|
|
|
expectedCode: http.StatusOK,
|
|
|
|
skipperResult: false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid credentials",
|
|
|
|
authHeader: basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:invalid-password")),
|
|
|
|
expectedCode: http.StatusUnauthorized,
|
|
|
|
expectedAuth: basic + ` realm="someRealm"`,
|
|
|
|
skipperResult: false,
|
|
|
|
expectedErr: true,
|
|
|
|
expectedErrMsg: "Unauthorized",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid base64 string",
|
|
|
|
authHeader: basic + " invalidString",
|
|
|
|
expectedCode: http.StatusBadRequest,
|
|
|
|
skipperResult: false,
|
|
|
|
expectedErr: true,
|
|
|
|
expectedErrMsg: "Bad Request",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Missing Authorization header",
|
|
|
|
expectedCode: http.StatusUnauthorized,
|
|
|
|
skipperResult: false,
|
|
|
|
expectedErr: true,
|
|
|
|
expectedErrMsg: "Unauthorized",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid Authorization header",
|
|
|
|
authHeader: base64.StdEncoding.EncodeToString([]byte("invalid")),
|
|
|
|
expectedCode: http.StatusUnauthorized,
|
|
|
|
skipperResult: false,
|
|
|
|
expectedErr: true,
|
|
|
|
expectedErrMsg: "Unauthorized",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Skipped Request",
|
|
|
|
authHeader: basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:skip")),
|
|
|
|
expectedCode: http.StatusOK,
|
|
|
|
skipperResult: true,
|
|
|
|
},
|
|
|
|
}
|
2016-04-28 06:08:06 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2022-05-27 18:44:51 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
|
|
res := httptest.NewRecorder()
|
|
|
|
c := e.NewContext(req, res)
|
2016-04-28 06:08:06 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
if tt.authHeader != "" {
|
|
|
|
req.Header.Set(echo.HeaderAuthorization, tt.authHeader)
|
|
|
|
}
|
2024-02-18 15:47:13 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
h := BasicAuthWithConfig(BasicAuthConfig{
|
|
|
|
Validator: mockValidator,
|
|
|
|
Realm: "someRealm",
|
|
|
|
Skipper: func(c echo.Context) bool {
|
|
|
|
return tt.skipperResult
|
|
|
|
},
|
|
|
|
})(func(c echo.Context) error {
|
|
|
|
return c.String(http.StatusOK, "test")
|
|
|
|
})
|
2024-02-18 15:47:13 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
err := h(c)
|
2024-02-18 15:47:13 +02:00
|
|
|
|
2024-10-16 21:37:13 +02:00
|
|
|
if tt.expectedErr {
|
|
|
|
var he *echo.HTTPError
|
|
|
|
errors.As(err, &he)
|
|
|
|
assert.Equal(t, tt.expectedCode, he.Code)
|
|
|
|
if tt.expectedAuth != "" {
|
|
|
|
assert.Equal(t, tt.expectedAuth, res.Header().Get(echo.HeaderWWWAuthenticate))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, tt.expectedCode, res.Code)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2016-04-28 06:08:06 +02:00
|
|
|
}
|