Describe the bug
When using an OIDC IdP that doesn't populate an email field in the token, the /oidc/token endpoint will fail to populate the external connection schema's name field with a valid string, causing a traceback and 500.
To Reproduce
Steps to reproduce the behavior:
- With a self-hosted Kanidm instance, configure a public client for Appointment:
kanidm group create tba_users
kanidm group add-members tba_users example_username
kanidm system oauth2 create-public tba Appointment https://appt.example.com
kanidm system oauth2 add-redirect-url tba https://appt.example.com/post-login/
kanidm system oauth2 update-scope-map tba tba_users email openid profile
- Configure
backend/.env for OIDC:
AUTH_SCHEME=oidc
OIDC_CLIENT_ID=tba
OIDC_TOKEN_INTROSPECTION_URL=https://kanidm.example.com/oauth2/token/introspect
(No OIDC_CLIENT_SECRET; this is a public client.)
- Configure
frontend/.env for OIDC:
VITE_AUTH_SCHEME=oidc
VITE_OIDC_CLIENT_ID=tba
VITE_OIDC_ROOT_URL=https://kanidm.example.com/oauth2/openid/tba
- Visit your TBA instance and, when redirected to Kanidm, log in.
Expected behavior
You should be redirected into TBA's flow to configure your new subscriber account.
Actual behavior
You receive a blank browser page, and the backend outputs a traceback ending with:
File "/app/appointment/routes/auth.py", line 625, in oidc_token
external_connection_schema = schemas.ExternalConnection(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/pydantic/main.py", line 263, in __init__
validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 1 validation error for ExternalConnection
name
Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]
For further information visit https://errors.pydantic.dev/2.13/v/string_type
Additional context
routes/auth.py attempts to populate external_connection_schema.name with the value of token_data.get('email'). It doesn't handle cases where that value is missing or empty. Replacing that line with name=email, (since email has been set with more robust logic) works around this problem, but I don't know if it actually follows the intended logic here.
I'm still trying to troubleshoot why token_data doesn't end up containing an email field.
(Thanks for making this open source and self-hostable!)
Describe the bug
When using an OIDC IdP that doesn't populate an
emailfield in the token, the/oidc/tokenendpoint will fail to populate the external connection schema'snamefield with a valid string, causing a traceback and 500.To Reproduce
Steps to reproduce the behavior:
backend/.envfor OIDC:(No
OIDC_CLIENT_SECRET; this is a public client.)frontend/.envfor OIDC:Expected behavior
You should be redirected into TBA's flow to configure your new subscriber account.
Actual behavior
You receive a blank browser page, and the backend outputs a traceback ending with:
Additional context
routes/auth.pyattempts to populateexternal_connection_schema.namewith the value oftoken_data.get('email'). It doesn't handle cases where that value is missing or empty. Replacing that line withname=email,(sinceemailhas been set with more robust logic) works around this problem, but I don't know if it actually follows the intended logic here.I'm still trying to troubleshoot why
token_datadoesn't end up containing anemailfield.(Thanks for making this open source and self-hostable!)