feat(auth): integrate portal JWT for enhanced authentication and authorization
CI / changes (push) Successful in 6s
CI / commitlint (push) Skipped
CI / openapi (push) Successful in 27s
CI / web (push) Successful in 51s
CI / go (push) Successful in 2m19s
CI / bird2 (push) Successful in 13s
CI / release (push) Successful in 4m24s

Added support for portal JWT authentication, enabling single sign-on (SSO) capabilities. Updated the application to handle JWT claims for user permissions and roles, enhancing security and access control. Refactored relevant components and API routes to accommodate the new authentication flow, ensuring a seamless user experience. Updated documentation to reflect the new authentication requirements and configurations.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-18 23:23:52 +07:00
co-authored by Cursor
parent 2820cff988
commit 4d83b8d673
48 changed files with 1839 additions and 254 deletions
+30
View File
@@ -37,6 +37,11 @@ func main() {
BundleSeedHex: strings.TrimSpace(os.Getenv("EVOBGP_BUNDLE_SEED_HEX")),
CORSAllowedOrigins: strings.TrimSpace(os.Getenv("EVOBGP_CORS_ORIGINS")),
RuntimeLogsPolicyTenant: cfg.RuntimeLogsPolicyTenant,
JWTSecret: firstNonEmpty(os.Getenv("EVOBGP_AUTH_JWT_SECRET"), os.Getenv("AUTH_JWT_SECRET")),
AuthIssuer: firstNonEmpty(os.Getenv("EVOBGP_AUTH_ISSUER"), os.Getenv("AUTH_ISSUER")),
AuthPortalURL: firstNonEmpty(os.Getenv("EVOBGP_AUTH_PORTAL_URL"), os.Getenv("AUTH_PORTAL_URL")),
PortalTenantID: strings.TrimSpace(os.Getenv("EVOBGP_PORTAL_TENANT_ID")),
AuthRequired: boolFromEnv("EVOBGP_AUTH_REQUIRED", "AUTH_REQUIRED"),
}
srv, err := httpapi.New(opts)
if err != nil {
@@ -86,6 +91,31 @@ func main() {
log.Printf("%s stopped", platform.ServiceName("evobgp-all"))
}
func firstNonEmpty(candidates ...string) string {
for _, c := range candidates {
if v := strings.TrimSpace(c); v != "" {
return v
}
}
return ""
}
func boolFromEnv(keys ...string) bool {
for _, k := range keys {
v := strings.TrimSpace(os.Getenv(k))
if v == "" {
continue
}
switch strings.ToLower(v) {
case "1", "true", "yes", "on":
return true
case "0", "false", "no", "off":
return false
}
}
return false
}
func startBirdMetricsPoller(ctx context.Context) {
sock := strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_SOCKET"))
if sock == "" {
+30
View File
@@ -32,6 +32,11 @@ func main() {
SeedDemo: seedDemo,
BundleSeedHex: strings.TrimSpace(os.Getenv("EVOBGP_BUNDLE_SEED_HEX")),
CORSAllowedOrigins: strings.TrimSpace(os.Getenv("EVOBGP_CORS_ORIGINS")),
JWTSecret: firstNonEmpty(os.Getenv("EVOBGP_AUTH_JWT_SECRET"), os.Getenv("AUTH_JWT_SECRET")),
AuthIssuer: firstNonEmpty(os.Getenv("EVOBGP_AUTH_ISSUER"), os.Getenv("AUTH_ISSUER")),
AuthPortalURL: firstNonEmpty(os.Getenv("EVOBGP_AUTH_PORTAL_URL"), os.Getenv("AUTH_PORTAL_URL")),
PortalTenantID: strings.TrimSpace(os.Getenv("EVOBGP_PORTAL_TENANT_ID")),
AuthRequired: boolFromEnv("EVOBGP_AUTH_REQUIRED", "AUTH_REQUIRED"),
}
srv, err := httpapi.New(opts)
if err != nil {
@@ -78,6 +83,31 @@ func main() {
log.Printf("%s stopped", platform.ServiceName("evobgp-api"))
}
func firstNonEmpty(candidates ...string) string {
for _, c := range candidates {
if v := strings.TrimSpace(c); v != "" {
return v
}
}
return ""
}
func boolFromEnv(keys ...string) bool {
for _, k := range keys {
v := strings.TrimSpace(os.Getenv(k))
if v == "" {
continue
}
switch strings.ToLower(v) {
case "1", "true", "yes", "on":
return true
case "0", "false", "no", "off":
return false
}
}
return false
}
func startBirdMetricsPoller(ctx context.Context) {
sock := strings.TrimSpace(os.Getenv("EVOBGP_BIRDC_SOCKET"))
if sock == "" {