feat(auth): enhance tenant resolution in JWT handling
CI / changes (push) Successful in 4s
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 58s
CI / commitlint (push) Skipped
CI / go (push) Successful in 1m3s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 4m15s
CI / changes (push) Successful in 4s
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 58s
CI / commitlint (push) Skipped
CI / go (push) Successful in 1m3s
CI / bird2 (push) Successful in 16s
CI / release (push) Successful in 4m15s
Updated the authentication logic to prioritize tenant resolution from JWT claims, specifically using `tenants.bgp` or `bgp_tenant_id` as the primary source. If these claims are absent, the system will fallback to the configured `EVOBGP_PORTAL_TENANT_ID`. This change improves the flexibility of tenant management in the authentication process. Additionally, updated related documentation to reflect these changes and added tests to ensure proper functionality.
This commit is contained in:
1 parent
b871d62de6
commit
b28ad88b22
6 files changed
+109
-7
No files matched your search
@@ -181,6 +181,83 @@ func TestAuthJWTMissingPermissionRejected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthJWTTenantFromClaimWithoutEnv(t *testing.T) {
|
||||
srv, err := New(Options{
|
||||
SeedDemo: true,
|
||||
BundleSeedHex: testBundleSeed,
|
||||
JWTSecret: testJWTSecret,
|
||||
AuthIssuer: testIssuer,
|
||||
AuthPortalURL: "https://portal.test.local",
|
||||
AuthRequired: true,
|
||||
// No PortalTenantID — must come from JWT claim.
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer srv.Close()
|
||||
tenant, _, _, _, _ := srv.Store().DemoIDs()
|
||||
|
||||
ts := httptest.NewServer(srv.Handler())
|
||||
defer ts.Close()
|
||||
|
||||
token := signTestJWT(t, jwt.MapClaims{
|
||||
"iss": testIssuer,
|
||||
"sub": "user-1",
|
||||
"apps": []string{"bgp"},
|
||||
"permissions": []string{"bgp:modules:read"},
|
||||
"bgp_tenant_id": tenant,
|
||||
"exp": time.Now().Add(time.Hour).Unix(),
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, ts.URL+"/v1/modules", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
resp, err := ts.Client().Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
b, _ := io.ReadAll(resp.Body)
|
||||
t.Fatalf("status=%d body=%s", resp.StatusCode, b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthJWTRejectedWhenTenantMissing(t *testing.T) {
|
||||
srv, err := New(Options{
|
||||
SeedDemo: true,
|
||||
BundleSeedHex: testBundleSeed,
|
||||
JWTSecret: testJWTSecret,
|
||||
AuthIssuer: testIssuer,
|
||||
AuthPortalURL: "https://portal.test.local",
|
||||
AuthRequired: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer srv.Close()
|
||||
|
||||
ts := httptest.NewServer(srv.Handler())
|
||||
defer ts.Close()
|
||||
|
||||
token := signTestJWT(t, jwt.MapClaims{
|
||||
"iss": testIssuer,
|
||||
"sub": "user-1",
|
||||
"apps": []string{"bgp"},
|
||||
"exp": time.Now().Add(time.Hour).Unix(),
|
||||
})
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, ts.URL+"/v1/modules", nil)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
resp, err := ts.Client().Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode != http.StatusServiceUnavailable {
|
||||
t.Fatalf("status=%d want 503", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthConfigPublic(t *testing.T) {
|
||||
srv, _ := newJWTTestServer(t)
|
||||
defer srv.Close()
|
||||
|
||||
Reference in new issue
Block a user