@@ -191,11 +191,17 @@ def validate_url(self, field):
191191
192192class OIDCSettingsForm (FlaskForm ):
193193 display_name = StringField ('OIDC Display Name' , validators = [DataRequired (), Length (min = 1 , max = 100 )],
194- render_kw = {'placeholder' : 'e.g., Company SSO, Keycloak , etc.' })
194+ render_kw = {'placeholder' : 'e.g., VoidAuth, Company SSO, etc.' })
195195 client_id = StringField ('Client ID' , validators = [DataRequired (), Length (min = 1 , max = 500 )])
196196 client_secret = StringField ('Client Secret' , validators = [DataRequired (), Length (min = 1 , max = 500 )])
197- discovery_endpoint = StringField ('Discovery Endpoint URL' , validators = [DataRequired (), Length (min = 1 , max = 500 )],
197+ discovery_endpoint = StringField ('Discovery Endpoint URL (Leave blank if blocked/restricted) ' , validators = [Optional (), Length (max = 500 )],
198198 render_kw = {'placeholder' : 'https://your-idp.com/.well-known/openid-configuration' })
199+ authorization_endpoint = StringField ('Authorization Endpoint (Required if discovery blocked)' , validators = [Optional (), Length (max = 500 )],
200+ render_kw = {'placeholder' : 'https://void.madnessshell.com/oidc/authorize' })
201+ token_endpoint = StringField ('Token Endpoint (Required if discovery blocked)' , validators = [Optional (), Length (max = 500 )],
202+ render_kw = {'placeholder' : 'https://void.madnessshell.com/oidc/token' })
203+ userinfo_endpoint = StringField ('UserInfo Endpoint (Required if discovery blocked)' , validators = [Optional (), Length (max = 500 )],
204+ render_kw = {'placeholder' : 'https://void.madnessshell.com/oidc/userinfo' })
199205 user_mapping_field = SelectField ('User Mapping Field' ,
200206 choices = [('username' , 'Username' ),
201207 ('email' , 'Email' ),
@@ -206,10 +212,24 @@ class OIDCSettingsForm(FlaskForm):
206212 render_kw = {'placeholder' : 'e.g., preferred_username, sub, etc.' })
207213 is_enabled = BooleanField ('Enable OIDC Authentication' , default = False )
208214
209- def validate_discovery_endpoint (self , field ):
210- if not (field .data .startswith ('http://' ) or field .data .startswith ('https://' )):
211- raise ValidationError ('Discovery endpoint must start with http:// or https://' )
212-
213- def validate_custom_attribute (self , field ):
214- if self .user_mapping_field .data == 'custom' and not field .data :
215- raise ValidationError ('Custom attribute name is required when using custom mapping' )
215+ def validate (self , extra_validators = None ):
216+ if not super ().validate (extra_validators ):
217+ return False
218+
219+ # Either discovery endpoint OR all manual endpoints must be provided
220+ has_discovery = bool (self .discovery_endpoint .data )
221+ has_manual = bool (self .authorization_endpoint .data and self .token_endpoint .data and self .userinfo_endpoint .data )
222+
223+ if not has_discovery and not has_manual :
224+ self .discovery_endpoint .errors .append ('Either provide Discovery Endpoint OR all three manual endpoints (Authorization, Token, UserInfo)' )
225+ return False
226+
227+ if has_discovery and not (self .discovery_endpoint .data .startswith ('http://' ) or self .discovery_endpoint .data .startswith ('https://' )):
228+ self .discovery_endpoint .errors .append ('Discovery endpoint must start with http:// or https://' )
229+ return False
230+
231+ if self .user_mapping_field .data == 'custom' and not self .custom_attribute .data :
232+ self .custom_attribute .errors .append ('Custom attribute name is required when using custom mapping' )
233+ return False
234+
235+ return True
0 commit comments