Throws a specific exception when a certificate is needed but not provided#24544
Throws a specific exception when a certificate is needed but not provided#24544rolfbjarne wants to merge 5 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds specific exception handling for scenarios where a server requests a client certificate but none is provided by the application. The implementation throws a structured exception chain (HttpRequestException → WebException → AuthenticationException) to help developers detect and handle missing certificate scenarios programmatically.
Changes:
- Modified NSUrlSessionHandler to throw a specific exception when a client certificate is requested but not available
- Added an AppContext switch to allow disabling the new behavior for backward compatibility
- Added two test methods to validate optional and required certificate scenarios
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| src/Foundation/NSUrlSessionHandler.cs | Adds exception handling logic when client certificate is missing, with AppContext switch for backward compatibility |
| tests/monotouch-test/System.Net.Http/MessageHandlers.cs | Adds two test methods: one for optional certificates (should succeed) and one for required certificates (should throw specific exception) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💻 [CI Build #df9f7f9] Tests on macOS arm64 - Mac Sequoia (15) passed 💻✅ All tests on macOS arm64 - Mac Sequoia (15) passed. Pipeline on Agent |
💻 [CI Build #df9f7f9] Tests on macOS M1 - Mac Monterey (12) passed 💻✅ All tests on macOS M1 - Mac Monterey (12) passed. Pipeline on Agent |
💻 [CI Build #df9f7f9] Tests on macOS X64 - Mac Sonoma (14) passed 💻✅ All tests on macOS X64 - Mac Sonoma (14) passed. Pipeline on Agent |
💻 [CI Build #df9f7f9] Tests on macOS M1 - Mac Ventura (13) passed 💻✅ All tests on macOS M1 - Mac Ventura (13) passed. Pipeline on Agent |
💻 [CI Build #df9f7f9] Tests on macOS arm64 - Mac Tahoe (26) passed 💻✅ All tests on macOS arm64 - Mac Tahoe (26) passed. Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
Verifies that when the Foundation.NSUrlSessionHandler.NoMissingCertificateHandling switch is enabled, the specific SecureChannelFailure exception is not thrown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
df9f7f9 to
4e047fd
Compare
| WebExceptionStatus.SecureChannelFailure, null)); | ||
| } | ||
| // We will still continue with a null credential, since some services uses optional client certificates and this will still let it succeed | ||
| completionHandler (NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, null!); |
There was a problem hiding this comment.
This branch uses PerformDefaultHandling but passes a null credential. Elsewhere in this method, PerformDefaultHandling uses challenge.ProposedCredential; using that here too avoids accidentally dropping a non-null ProposedCredential and matches the existing pattern.
| completionHandler (NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, null!); | |
| completionHandler (NSUrlSessionAuthChallengeDisposition.PerformDefaultHandling, challenge.ProposedCredential); |
| listener.SetStateChangedHandler ((state, error) => { | ||
| if (state == NWListenerState.Ready) | ||
| readyEvent.Set (); | ||
| if (state == NWListenerState.Failed) | ||
| readyEvent.Set (); | ||
| }); |
There was a problem hiding this comment.
CreateNWTlsListener unblocks the wait on both Ready and Failed, but it doesn’t check which state occurred. If the listener fails to start, this method will still return a listener and subsequent requests can fail in confusing ways/time out. Track the final state/error and throw when the state is Failed (and consider disposing the ManualResetEventSlim).
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
- Use challenge.ProposedCredential instead of null for PerformDefaultHandling. - Fix grammar: 'services uses' -> 'services use'. - Track listener error state and throw on Failed instead of silently returning a broken listener. - Dispose ManualResetEventSlim. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ [CI Build #cf677dc] Build passed (Build packages) ✅Pipeline on Agent |
✅ [CI Build #cf677dc] Build passed (Build macOS tests) ✅Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
🔥 [CI Build #cf677dc] Test results 🔥Test results❌ Tests failed on VSTS: test results 1 tests crashed, 6 tests failed, 138 tests passed. Failures❌ monotouch tests (macOS)🔥 Failed catastrophically on VSTS: test results - monotouch_macos (no summary found). Html Report (VSDrops) Download ❌ monotouch tests (tvOS)1 tests failed, 10 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Monterey (12) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Ventura (13) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Sonoma (14) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Sequoia (15) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download ❌ Tests on macOS Tahoe (26) tests1 tests failed, 4 tests passed.Failed tests
Html Report (VSDrops) Download Successes✅ cecil: All 1 tests passed. Html Report (VSDrops) Download macOS testsLinux Build VerificationPipeline on Agent |
🔥 [PR Build #cf677dc] Build failed (Detect API changes) 🔥Build failed for the job 'Detect API changes' (with job status 'Canceled') Pipeline on Agent |
|
🔥 Unable to find the contents for the comment: D:\a\1\s\change-detection\results\gh-comment.md does not exist :fire Pipeline on Agent |
Fixes #21688
This allows the user to detect the specific exception when a certificate is needed and react to it. Exceptions thrown are very similar to what
SocketsHttpHandlerand other handlers throw, while also following the pattern of other exceptions thrown byNSUrlSessionHandler.This is a re-creation of #24532 from @dotMorten (due to our CI not being able to build PRs from forks).