2023-03-31 12:44:22 +02:00
|
|
|
package middleware
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/golang-jwt/jwt"
|
|
|
|
|
|
|
|
"github.com/netbirdio/netbird/management/server"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2023-09-01 18:09:59 +02:00
|
|
|
audience = "audience"
|
|
|
|
userIDClaim = "userIDClaim"
|
|
|
|
accountID = "accountID"
|
|
|
|
domain = "domain"
|
|
|
|
userID = "userID"
|
|
|
|
tokenID = "tokenID"
|
|
|
|
PAT = "PAT"
|
|
|
|
JWT = "JWT"
|
|
|
|
wrongToken = "wrongToken"
|
2023-03-31 12:44:22 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var testAccount = &server.Account{
|
|
|
|
Id: accountID,
|
|
|
|
Domain: domain,
|
|
|
|
Users: map[string]*server.User{
|
|
|
|
userID: {
|
|
|
|
Id: userID,
|
|
|
|
PATs: map[string]*server.PersonalAccessToken{
|
|
|
|
tokenID: {
|
|
|
|
ID: tokenID,
|
|
|
|
Name: "My first token",
|
|
|
|
HashedToken: "someHash",
|
2023-04-03 15:09:35 +02:00
|
|
|
ExpirationDate: time.Now().UTC().AddDate(0, 0, 7),
|
2023-03-31 12:44:22 +02:00
|
|
|
CreatedBy: userID,
|
2023-04-03 15:09:35 +02:00
|
|
|
CreatedAt: time.Now().UTC(),
|
|
|
|
LastUsed: time.Now().UTC(),
|
2023-03-31 12:44:22 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func mockGetAccountFromPAT(token string) (*server.Account, *server.User, *server.PersonalAccessToken, error) {
|
|
|
|
if token == PAT {
|
|
|
|
return testAccount, testAccount.Users[userID], testAccount.Users[userID].PATs[tokenID], nil
|
|
|
|
}
|
|
|
|
return nil, nil, nil, fmt.Errorf("PAT invalid")
|
|
|
|
}
|
|
|
|
|
|
|
|
func mockValidateAndParseToken(token string) (*jwt.Token, error) {
|
|
|
|
if token == JWT {
|
|
|
|
return &jwt.Token{}, nil
|
|
|
|
}
|
|
|
|
return nil, fmt.Errorf("JWT invalid")
|
|
|
|
}
|
|
|
|
|
|
|
|
func mockMarkPATUsed(token string) error {
|
|
|
|
if token == tokenID {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return fmt.Errorf("Should never get reached")
|
|
|
|
}
|
|
|
|
|
2023-03-31 12:45:10 +02:00
|
|
|
func TestAuthMiddleware_Handler(t *testing.T) {
|
2023-03-31 12:44:22 +02:00
|
|
|
tt := []struct {
|
|
|
|
name string
|
|
|
|
authHeader string
|
|
|
|
expectedStatusCode int
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Valid PAT Token",
|
|
|
|
authHeader: "Token " + PAT,
|
|
|
|
expectedStatusCode: 200,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid PAT Token",
|
|
|
|
authHeader: "Token " + wrongToken,
|
|
|
|
expectedStatusCode: 401,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Valid JWT Token",
|
|
|
|
authHeader: "Bearer " + JWT,
|
|
|
|
expectedStatusCode: 200,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid JWT Token",
|
|
|
|
authHeader: "Bearer " + wrongToken,
|
|
|
|
expectedStatusCode: 401,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Basic Auth",
|
|
|
|
authHeader: "Basic " + PAT,
|
|
|
|
expectedStatusCode: 401,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
// do nothing
|
|
|
|
})
|
|
|
|
|
2023-09-01 18:09:59 +02:00
|
|
|
authMiddleware := NewAuthMiddleware(mockGetAccountFromPAT, mockValidateAndParseToken, mockMarkPATUsed, audience, userIDClaim)
|
2023-03-31 12:44:22 +02:00
|
|
|
|
|
|
|
handlerToTest := authMiddleware.Handler(nextHandler)
|
|
|
|
|
|
|
|
for _, tc := range tt {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
|
|
req := httptest.NewRequest("GET", "http://testing", nil)
|
|
|
|
req.Header.Set("Authorization", tc.authHeader)
|
|
|
|
rec := httptest.NewRecorder()
|
|
|
|
|
|
|
|
handlerToTest.ServeHTTP(rec, req)
|
|
|
|
|
2023-09-04 17:03:44 +02:00
|
|
|
result := rec.Result()
|
|
|
|
defer result.Body.Close()
|
|
|
|
if result.StatusCode != tc.expectedStatusCode {
|
|
|
|
t.Errorf("expected status code %d, got %d", tc.expectedStatusCode, result.StatusCode)
|
2023-03-31 12:44:22 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|