diff --git a/server/account/account.go b/server/account/account.go index 541401a731022..0e377329f4fe2 100644 --- a/server/account/account.go +++ b/server/account/account.go @@ -47,6 +47,7 @@ func (s *Server) UpdatePassword(ctx context.Context, q *account.UpdatePasswordRe // check for permission is user is trying to change someone else's password // assuming user is trying to update someone else if username is different or issuer is not Argo CD if updatedUsername != username || issuer != session.SessionManagerClaimsIssuer { + log.Printf("Claims: %+v", ctx.Value("claims")) // this line for debug if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceAccounts, rbacpolicy.ActionUpdate, q.Name); err != nil { return nil, fmt.Errorf("permission denied: %w", err) } diff --git a/server/account/account_test.go b/server/account/account_test.go index 2e7f9ab669e9d..f127eb7c6a7c2 100644 --- a/server/account/account_test.go +++ b/server/account/account_test.go @@ -82,30 +82,51 @@ func getAdminAccount(mgr *settings.SettingsManager) (*settings.Account, error) { } func adminContext(ctx context.Context) context.Context { - // nolint:staticcheck - return context.WithValue(ctx, "claims", &jwt.RegisteredClaims{Subject: "admin", Issuer: sessionutil.SessionManagerClaimsIssuer}) + claims := jwt.MapClaims{ + "sub": "admin", + "iss": sessionutil.SessionManagerClaimsIssuer, + "groups": []string{"role:admin"}, + "federated_claims": map[string]interface{}{ + "user_id": "admin", + }, + } + ctx = context.WithValue(ctx, sessionutil.ClaimsKey(), claims) + ctx = context.WithValue(ctx, "claims", claims) + return ctx } func ssoAdminContext(ctx context.Context, iat time.Time) context.Context { - // nolint:staticcheck - return context.WithValue(ctx, "claims", &jwt.RegisteredClaims{ - Subject: "admin", - Issuer: "https://myargocdhost.com/api/dex", - IssuedAt: jwt.NewNumericDate(iat), - }) + claims := jwt.MapClaims{ + "sub": "admin", + "iss": "https://myargocdhost.com/api/dex", + "iat": jwt.NewNumericDate(iat), + "groups": []string{"role:admin"}, // Add admin group + "federated_claims": map[string]interface{}{ + "user_id": "admin", + }, + } + // Set both context values + ctx = context.WithValue(ctx, sessionutil.ClaimsKey(), claims) + ctx = context.WithValue(ctx, "claims", claims) + + return ctx } func projTokenContext(ctx context.Context) context.Context { - // nolint:staticcheck - return context.WithValue(ctx, "claims", &jwt.RegisteredClaims{ - Subject: "proj:demo:deployer", - Issuer: sessionutil.SessionManagerClaimsIssuer, - }) + claims := jwt.MapClaims{ + "sub": "proj:demo:deployer", + "iss": sessionutil.SessionManagerClaimsIssuer, + "groups": []string{"proj:demo:deployer"}, + } + ctx = context.WithValue(ctx, sessionutil.ClaimsKey(), claims) + ctx = context.WithValue(ctx, "claims", claims) + return ctx } func TestUpdatePassword(t *testing.T) { accountServer, sessionServer := newTestAccountServer(context.Background()) ctx := adminContext(context.Background()) + var err error // ensure password is not allowed to be updated if given bad password diff --git a/util/oidc/oidc_test.go b/util/oidc/oidc_test.go index 5c3b22a6afab6..2aebddaf7a706 100644 --- a/util/oidc/oidc_test.go +++ b/util/oidc/oidc_test.go @@ -861,7 +861,6 @@ func TestGetUserInfo(t *testing.T) { }, "groups": []interface{}{"githubOrg:engineers"}, } - // json.NewEncoder(w).Encode(response) if err := json.NewEncoder(w).Encode(response); err != nil { t.Errorf("failed to encode response: %v", err) } @@ -910,7 +909,6 @@ func TestGetUserInfo(t *testing.T) { "sub": "sub-only-user", "groups": []interface{}{"githubOrg:engineers"}, } - // json.NewEncoder(w).Encode(response) if err := json.NewEncoder(w).Encode(response); err != nil { t.Errorf("failed to encode response: %v", err) } @@ -970,7 +968,6 @@ func TestGetUserInfo(t *testing.T) { }, "groups": []interface{}{"githubOrg:engineers"}, } - // json.NewEncoder(w).Encode(response) if err := json.NewEncoder(w).Encode(response); err != nil { t.Errorf("failed to encode response: %v", err) } diff --git a/util/session/sessionmanager.go b/util/session/sessionmanager.go index 0cc48c6cb1d73..e79f25fd249ff 100644 --- a/util/session/sessionmanager.go +++ b/util/session/sessionmanager.go @@ -160,16 +160,19 @@ func (mgr *SessionManager) Create(subject string, secondsBeforeExpiry int64, id // Create a new token object, specifying signing method and the claims // you would like it to contain. now := time.Now().UTC() - claims := jwt.RegisteredClaims{ - IssuedAt: jwt.NewNumericDate(now), - Issuer: SessionManagerClaimsIssuer, - NotBefore: jwt.NewNumericDate(now), - Subject: subject, - ID: id, + claims := jwt.MapClaims{ + "iat": now.Unix(), + "iss": SessionManagerClaimsIssuer, + "nbf": now.Unix(), + "sub": subject, + "jti": id, + "federated_claims": map[string]interface{}{ + "user_id": "", // Empty for local auth + }, } if secondsBeforeExpiry > 0 { expires := now.Add(time.Duration(secondsBeforeExpiry) * time.Second) - claims.ExpiresAt = jwt.NewNumericDate(expires) + claims["exp"] = expires.Unix() } return mgr.signClaims(claims) @@ -641,6 +644,11 @@ type contextKey struct{} var claimsKey = contextKey{} +// ClaimsKey returns the context key used for claims +func ClaimsKey() interface{} { + return claimsKey +} + func mapClaims(ctx context.Context) (jwt.MapClaims, bool) { claims, ok := ctx.Value(claimsKey).(jwt.Claims) if !ok {