-
-
Notifications
You must be signed in to change notification settings - Fork 40
0.7.0 alpha Draft - Addresses ToDo(s), Security Improvements, & OP Interoperability #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
modified: custom_components/auth_oidc/config/const.py
modified: custom_components/auth_oidc/config/schema.py
modified: custom_components/auth_oidc/tools/helpers.py
modified: custom_components/auth_oidc/tools/oidc_client.py
- Add `enable_verbose_debug_mode` option to CONFIG_SCHEMA (captures full
request/response text to `<config_dir>/custom_components/auth_oidc/verbose_debug/`
for discovery/JWKS/token/userinfo debugging; gated logs + dir creation).
- Implement `compute_allowed_signing_algs()` helper: prioritizes configured alg
(warn if unsupported), falls back to OP discovery `id_token_signing_alg_values_supported`
or ['RS256']; supports all OIDC algs (HS/RS/ES/PS/EdDSA) via joserfc.
- Refactor OIDCClient: reuse `self.id_token_signing_alg` w/ DEFAULT_ID_TOKEN_SIGNING_ALGORITHM
fallback; pass to DiscoveryClient; flexible `_parse_id_token()` (header alg check +
`algorithms=[alg]` verify per OIDC Core §3.1.3.7.6/7.8; HS uses client_secret).
- Relax discovery validation to warn-only for alg mismatches.
- Update `__init__.py` to pass new option; add `email` to REQUIRED_SCOPES.
- Full spec compliance: JWTClaimsRegistry (aud/iss/sub/exp/nbf/iat + leeway=5),
nonce post-decode, HS/oct key resolution.
Updated kid handling and user info parsing.
Resolved issues with instancing & leaks/collisions
modified: custom_components/auth_oidc/__init__.py
modified: custom_components/auth_oidc/config/const.py
modified: custom_components/auth_oidc/config/schema.py
modified: custom_components/auth_oidc/stores/code_store.py
modified: custom_components/auth_oidc/tools/helpers.py
modified: custom_components/auth_oidc/tools/oidc_client.py
* Implemented userinfo fallback for cases where OP imits userinfo endpoint in discovery document
- New const: NETWORK_USERINFO_FALLBACK (boolean) supplied by "userinfo_fallback" in HA configuration.yaml
* fixed at_hash calculation to hash the entire access token (matching OpenID Connect Core §3.1.3.6)
- Fixes rejection of valid tokens from compliant OPs (e.g., Google, Authentik). No breakage for non-at_hash OPs.
* made authorization state values single-use by popping them when completing the token flow
- also upgraded the code store’s one-time tokens to secrets.token_urlsafe(16) for greater entropy; 128-bits.
- Guards against brute-force since the prior implementation needed only 1 million possibilities whilst
- also used as bearer tokens in the browser...
* Moved verbose_debug_logging to dedicated helper function to reduce code duplication / code cleanup.
* Improved handling in situations where 'kid' is missing from the ID token header
- Now checks all allowed signing algorithms from discovery document to verify the token signature.
- Priority 1: Exact "kid" match.
- 2: Matching key["alg"]
- 3: Attempt match with all keys.
|
Hi @btbutts, thank you for your improvements. I will probably take some time to review the code as I don't have that much time for open source right now, sorry for that in advance. I'm prioritizing breaking bugs and security fixes. However, I don't like the inclusion of the More importantly, supporting I am fine with adding better instructions for the Furthermore, I don't think supporting userinfo that way is the best solution, as it's a very specific guess (other IdP's might have other paths). I am more in favor of allowing the user to override any endpoint (auth, token, userinfo etc) using the configuration, as suggested by #110. For your IdP from #173, this might then require passing the additional scope Again thank you for your contributions and time debugging! Hopefully we can find a solution we're both happy with! |
|
Hi @christiaangoossens . Thanks for your feedback. It's appreciated. Understood regarding the email scope. That's easy enough to move it out of the default scopes and just include a config template for IdP's like OneLogin. I see that's something that you already started. My mods are no where complete yet (there's a few things I've found I need to work out and complete some more testing), which is why I haven't submitted the PR for review yet. I really just wanted to get it on the radar for feedback whilst I work through it all (perhaps on what you all might value more). For your userinfo comment, I think that makes perfect sense, rather than writing a static fallback endpoint into the project, it might make sense just to make that an option users can add in themselves, if needed. IdP's are not required by spec to provide the userinfo endpoint in the discovery doc; They are, however, required to support the userinfo endpoint. These IdP's will provide a static link which can be manually added to the user/org's RP config. Thus, this is why I added the fallback option. I actually don't need this for my own IdP. Both OneLogin and CSE already have it in their discovery documents so its not something I need myself for my own implementation. However, I did notice it, and figured its not too difficult since it's something I've come accross a lot at my day job. 😃 We're doing a lot in the SaaS space these days (ZTNA, SASE, and SSE). The rest primary targets some ToDo's I found throught the project in the source, some of which I would benefit from, so I started building them out. I had already completed a working implementation of a lot of this on the 0.6.3 release, but figured since 0.7.0 seems to be the active branch, it makes sense to port a lot of it over to 0.7.0 before I continue further. Troubleshooting capability logging was one deficit I found. The hardest SSO integrations, I find, are the ones that don't have an option for detailed logs. Whilst there are logs and specific exceptions already implemented throughout the codebase, some of that would be more helpful for debugging than troubleshooting a failing implementation. This is why I added an option for the The rest of the ToDo's really focused around certain areas of cryptography and randomization. I don't have time to go into more detail about that right now but basically, you already had a well working implementation. I really just saw some ways it could be strengthened for those IdP's that support it, yet should still function identically to how the integration did for those that don't. Anyways. Thanks again for your response. It's well received. Cheers! |
Here's a detailed list of improvements I've been working on in my fork of 0.7.0. I am still working on some ruff cleanup todo's as there too many lines in oidc_client.py, some lines are too long, and other things it won't correc itself, and some other minor changes I need to make.
The following should give you an idea of what I've worked on since I saw for several of the features you're working on for the 0.7.0 release, you'd marked them as help wanted.
custom_components/auth_oidc/__init__.pycustom_components/auth_oidc/config/const.pycustom_components/auth_oidc/config/schema.pyAdded Imports for New Configuration Constants: Included
VERBOSE_DEBUG_MODEandNETWORK_USERINFO_FALLBACKfrom the configuration module.- VERBOSE_DEBUG_MODE (boolean default False) const is set via
enable_verbose_debug_modein HA configuration.yaml. The purpose is to provide a very intential switch users may enable to not only increase log verbosity, but also capture OIDC auth flows that would otherwise be discarded, but are significatnly helpful for troubleshooting failed RP > OP integration configs. Whilst it is possible to use browser-based capturing extensions, these had some limitations in my experience, and also don't decode all relevant info in the flows. Secondly, whilst it is possible to set the default log level for the integration via HA, this would pose a security risk if inadervtently left enabled. Providing a specific swtich makes capturing this info this very intentional. This switch will log content that would otherwise be discarded.- Reference: Relates to OIDC Core §3.1.2.1 (Authentication Request) for scope handling and general client robustness, though primarily a best practice for implementation diagnostics.
- NETWORK_USERINFO_FALLBACK (boolean default False) is set via
network.userinfo_fallbackin HA configuration.yaml. Not all OPs provide a userinfo endpoint in their discovery document See: OIDC Discovery §3 (Provider Configuration Response), thus necessitating RP resiliency via robust client behavior. If setTrue, the userinfo endpoint is constructed from the issuer endpoint via <Issuer_FQDN>/userinfo.- Reference: OIDC Discovery §2 (OpenID Provider Metadata) notes that certain fields like
userinfo_endpointare RECOMMENDED but not REQUIRED, justifying fallbacks.Expanded Required Scopes: Updated
REQUIRED_SCOPESto include email in addition to openid and profile.- Ensures retrieval of email claims by default, enhancing user identification and claim processing without requiring custom configurations. Though email is not a required scope, it is standard among OPs. In fact, many don't even include the username or preferred_username claims, given that those OPs use emails as their own internal username reference. For this, they are not governed by OIDC spec for what they do outside of the OIDC protocol, or even necessarily what values they pass to a given claim. That said, given HA doesn't use emails, in fact the Nabu Casa team discourages it, I've added some processing to strip the "@" and everything following it whenever configuration.yaml's
claims.usernameis set to email or e-mail, thus allowing flexibility with more OPs, whilst also keeping with HA norms (even without HA currently supporting extenral AuthProviders).- Passed New Parameters to
OIDCClientInitializationNo breaking changes; the file maintains compatibility while extending functionality.
custom_components/auth_oidc/stores/code_store.pyrandom.choices(string.digits, k=6)withsecrets.token_urlsafe(16).secretsmodule follows Python's secure random generation best practices.No other changes; the modification is isolated and non-breaking.
custom_components/auth_oidc/tools/helpers.pyNew Function:
compute_allowed_signing_algs: Computes allowed ID token signing algorithms from configuration and discovery document, defaulting to RS256 if unspecified, with warnings for mismatches.algheader matches expected values. OIDC Discovery §2 specifiesid_token_signing_alg_values_supportedfor provider-advertised algorithms, justifying computation and fallback logic.New Function:
capture_auth_flows: Logs verbose debug messages and optionally captures request/response content to files for analysis, conditional on verbose mode.Existing functions (
get_urlandget_view) remain unchanged.custom_components/auth_oidc/tools/oidc_client.pyAdded Issuer Normalization and Mismatch Check in Discovery Validation: Normalizes and strictly compares the issuer from the discovery document against the expected value to prevent mismatch attacks.
issclaim matches the expected issuer. OIDC Discovery §3.1 (Authorization Server Metadata Validation) and RFC 8414 §3.1.2 (Issuer Identifier) emphasize exact matching of the issuer (scheme/host only, case-insensitive scheme).Added Verbose Debugging Integration: Incorporated
verbose_debug_modeandcapture_dirfor logging and file-based capture of flows (e.g., in fetch methods), initialized if enabled.Flexible Signing Algorithm Handling: Updated ID token validation to use computed allowed algorithms, warning on unsupported ones instead of failing, with fallbacks.
id_token_signing_alg_values_supported(OIDC Discovery §2).Added Caching for Discovery Document: Implemented instance-level caching with a 1-hour TTL to minimize repeated fetches.
Userinfo Endpoint Fallback: If
userinfo_endpointis absent in discovery, constructs it asissuer + "/userinfo"when fallback is enabled.userinfo_endpointas RECOMMENDED (not REQUIRED), permitting clients to derive it from the issuer per implementation conventions.Enhanced Exceptions and Logging: Added
OIDCIdTokenInvalidand detailed logging/captures in methods like_fetch_discovery_documentand_fetch_jwks.These changes focus on security, performance, and compatibility whilst avoiding breaking alterations.