Step-up auth: Enforce visibility constraints - only allow for private groups/namespaces
Proposal
Step-up authentication should only be applicable to private groups. Group maintainers/owners can currently configure step-up auth on any visibility level, creating a semantic inconsistency:
- Public/Internal groups: Accessible to unauthenticated or all authenticated users → step-up auth is meaningless
- Private groups: Only authorized users can access → step-up auth provides meaningful additional security
This proposal adds validation to ensure step-up authentication can only be configured on private groups and prevents visibility changes that would violate this constraint.
This issue builds on top of Issue: Step-up auth: Group-based OIDC Step-up Authenti... (#556943)
Related Issues and Merge Requests
- Epic: Step-Up Authentication (&16818)
- Issue: Step-up auth: Group-based OIDC Step-up Authenti... (#556943)
- Related MR finalizing the integration of the step-up authentication for groups: Step-up auth: Group protection (final integrati... (!199800 - merged)
Problem Statement
-
No model-level validation: Group owners can configure
step_up_auth_required_oauth_provideron public/internal groups, which is semantically invalid - No visibility change protection: Private groups with step-up auth can be changed to public/internal, breaking the security model
- Project inheritance concerns: Projects may have different visibility than their parent group with step-up auth, creating ambiguity about enforcement
-
Controller-only enforcement: Current implementation (!199800 (merged)) in
app/controllers/concerns/enforces_step_up_authentication_for_namespace.rbchecks visibility at runtime but doesn't prevent invalid configurations - Unclear semantics: Group owners don't receive clear guidance that step-up auth requires private visibility
Proposed Solution
1. Model Validation
- Add validation to
app/models/namespace_setting.rbpreventingstep_up_auth_required_oauth_provideron non-private groups - Add validation to
app/models/namespace.rbpreventing visibility changes from private when step-up auth is configured
2. API/GraphQL Validation
- Update
lib/api/groups.rbandMutations::Groups::Updateto return 400 Bad Request with clear error messages explaining the visibility constraint
3. UI Validation
- Disable step-up auth configuration for non-private groups in
app/assets/javascripts/pages/groups/settings/* - Show informational message: "Step-up authentication is only available for private groups"
- Prevent visibility changes when step-up auth is configured with warning message
4. Documentation
- Group settings and step-up auth feature docs: explain private-only requirement
- API docs: document validation error responses
- Troubleshooting guide: visibility-related configuration errors
- Administrator FAQ: why the constraint exists
Implementation Checklist
-
Model validation prevents setting step_up_auth_required_oauth_provideron non-private groups-
Add validation to app/models/namespace_setting.rb(~10 lines) -
Add RSpec tests to spec/models/namespace_setting_spec.rb(validation on private vs non-private groups, error messages)
-
-
Model validation prevents changing visibility from private to public/internal when step-up auth is configured -
Add validation to app/models/namespace.rb(~15 lines) -
Add RSpec tests to spec/models/namespace_spec.rb(visibility change validation, edge cases)
-
-
API and GraphQL return clear error messages (400 Bad Request) with explanation -
Update lib/api/groups.rbfor API error handling (~10 lines) -
Update GraphQL mutations: Mutations::Groups::Update(~10 lines) -
Add API tests to spec/requests/api/groups_spec.rb(error responses, proper status codes) -
Add GraphQL tests for mutation validation
-
-
Group settings UI disables step-up auth options for non-private groups -
Disable step-up auth UI elements for non-private groups (~30 lines in app/assets/javascripts/pages/groups/settings/*) -
Add informational tooltips and messages (~20 lines)
-
-
Group settings UI prevents visibility changes when step-up auth is configured -
Prevent visibility changes via UI when step-up auth configured -
Add JavaScript validation for immediate user feedback -
Add feature tests to spec/features/groups/settings/step_up_auth_spec.rb(UI behavior, warning messages)
-
-
Documentation updated across all relevant areas (feature docs, API docs, troubleshooting) -
Update group settings documentation (step-up auth section with visibility requirement) -
Update API documentation with validation error responses -
Add troubleshooting section for visibility constraints -
Create administrator FAQ entry explaining why step-up auth requires private visibility -
Add examples of valid and invalid configurations
-
-
Comprehensive test coverage for all validation scenarios -
Model validation tests cover all edge cases -
API/GraphQL tests verify error handling -
Feature tests validate UI behavior -
Test coverage > 95% for all new validation code
-
Open Questions:
-
Project Inheritance (High Priority) - Should projects under step-up auth groups be forced to private visibility? What happens when project visibility differs from parent? Review:
app/models/project.rb -
Existing Configurations - Are there invalid configurations? Query to check:
SELECT g.id, g.name, g.visibility_level, ns.step_up_auth_required_oauth_provider FROM namespaces g INNER JOIN namespace_settings ns ON g.id = ns.namespace_id WHERE ns.step_up_auth_required_oauth_provider IS NOT NULL AND g.visibility_level != 0 AND g.type = 'Group';Note: Migration not needed (feature behind flag)
-
API/GraphQL Coverage - Which endpoints besides
PUT /api/v4/groups/:idandMutations::Groups::Updateneed validation? -
Bulk Operations - How should group transfers, bulk visibility changes, and import/export handle step-up auth constraints? Review:
app/models/concerns/routable.rb -
Subgroups - Should subgroups inherit step-up auth settings? Should subgroup visibility be constrained by parent's step-up auth?
Technical Notes:
- Builds on #556943 (Group protection) and !199800 (merged) (final integration and testing)
- Feature behind
omniauth_step_up_auth_for_namespaceflag (not released, no migration needed) - Defense in depth: Keep controller-level checks from !199800 (merged) alongside model validations
- Validation messages must be user-friendly and actionable