mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 08:16:39 +00:00
[management, client] Fix SSH server audience validator (#5105)
* **New Features** * SSH server JWT validation now accepts multiple audiences with backward-compatible handling of the previous single-audience setting and a guard ensuring at least one audience is configured. * **Tests** * Test suites updated and new tests added to cover multiple-audience scenarios and compatibility with existing behavior. * **Other** * Startup logging enhanced to report configured audiences for JWT auth.
This commit is contained in:
@@ -176,9 +176,9 @@ type Server struct {
|
||||
|
||||
type JWTConfig struct {
|
||||
Issuer string
|
||||
Audience string
|
||||
KeysLocation string
|
||||
MaxTokenAge int64
|
||||
Audiences []string
|
||||
}
|
||||
|
||||
// Config contains all SSH server configuration options
|
||||
@@ -427,18 +427,25 @@ func (s *Server) ensureJWTValidator() error {
|
||||
return fmt.Errorf("JWT config not set")
|
||||
}
|
||||
|
||||
log.Debugf("Initializing JWT validator (issuer: %s, audience: %s)", config.Issuer, config.Audience)
|
||||
if len(config.Audiences) == 0 {
|
||||
return fmt.Errorf("JWT config has no audiences configured")
|
||||
}
|
||||
|
||||
log.Debugf("Initializing JWT validator (issuer: %s, audiences: %v)", config.Issuer, config.Audiences)
|
||||
validator := jwt.NewValidator(
|
||||
config.Issuer,
|
||||
[]string{config.Audience},
|
||||
config.Audiences,
|
||||
config.KeysLocation,
|
||||
true,
|
||||
)
|
||||
|
||||
// Use custom userIDClaim from authorizer if available
|
||||
audience := ""
|
||||
if len(config.Audiences) != 0 {
|
||||
audience = config.Audiences[0]
|
||||
}
|
||||
extractorOptions := []jwt.ClaimsExtractorOption{
|
||||
jwt.WithAudience(config.Audience),
|
||||
jwt.WithAudience(audience),
|
||||
}
|
||||
if authorizer.GetUserIDClaim() != "" {
|
||||
extractorOptions = append(extractorOptions, jwt.WithUserIDClaim(authorizer.GetUserIDClaim()))
|
||||
@@ -475,8 +482,8 @@ func (s *Server) validateJWTToken(tokenString string) (*gojwt.Token, error) {
|
||||
if err != nil {
|
||||
if jwtConfig != nil {
|
||||
if claims, parseErr := s.parseTokenWithoutValidation(tokenString); parseErr == nil {
|
||||
return nil, fmt.Errorf("validate token (expected issuer=%s, audience=%s, actual issuer=%v, audience=%v): %w",
|
||||
jwtConfig.Issuer, jwtConfig.Audience, claims["iss"], claims["aud"], err)
|
||||
return nil, fmt.Errorf("validate token (expected issuer=%s, audiences=%v, actual issuer=%v, audience=%v): %w",
|
||||
jwtConfig.Issuer, jwtConfig.Audiences, claims["iss"], claims["aud"], err)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("validate token: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user