# Description
Adopt
[`System.TimeProvider`](https://learn.microsoft.com/dotnet/api/system.timeprovider)
across the stack so that every place that creates timers, runs duration
math, or schedules periodic work is mockable, deterministic in tests,
and immune to wall-clock changes.
The migration touches Core, Core.Types, Server, Client, PubSub,
Configuration, Gds (server + client), Lds, and the Quickstarts/Console
reference apps. Per-component changes follow the same pattern:
1. Add a `private readonly TimeProvider m_timeProvider;` field.
2. Accept a nullable `TimeProvider? timeProvider = null` as the **last**
constructor parameter (new overload; legacy constructor stays for binary
compatibility and delegates with `timeProvider: null`).
3. Initialise the field with `m_timeProvider = timeProvider ??=
TimeProvider.System;`.
4. Replace `new Timer(...)`, `Stopwatch`, `HiResClock.*`,
`DateTime.UtcNow`-based duration math, and `Task.Delay(delay, ct)` in
timing loops with the matching `m_timeProvider` API (`CreateTimer`,
`GetTimestamp` / `GetElapsedTime`, `GetUtcNow().UtcDateTime`,
`Task.Delay(delay, m_timeProvider, ct)`).
5. Wire the provider through DI: `AddOpcUaServerBuilder` /
`AddOpcUaClientBuilder` register `TimeProvider.System` via
`TryAddSingleton<TimeProvider>()` so tests can swap in
`Microsoft.Extensions.Time.Testing.FakeTimeProvider`.
`HiResClock` itself is kept (so the
`ApplicationConfiguration.DisableHiResClock` schema flag still
round-trips), but **every public member** is now `[Obsolete]` with a
single shared message pointing to the new migration-guide section. The
few internal call sites that still need to set/read `HiResClock` are
wrapped with `#pragma warning disable CS0618`.
### Highlights per component
- **Core / Stack** — `Opc.Ua.Core`, `Opc.Ua.Core.Types`, channel
pipeline (`UaSCBinaryClientChannel`, `ChannelToken`,
`UaSCBinaryChannel`), `ApplicationConfiguration`, certificate
validators, `JwksIssuerKeyResolver`, `TimeProviderExtensions` polyfills
(`GetTimestampMilliseconds`, `GetTickCount`,
`CancellationTokenSource(timeout, timeProvider)`, `Task.Delay(delay,
provider, ct)` polyfill for older TFMs).
- **Server** — session lockout, subscription pipeline
(publish/sample/keep-alive/lifetime), `MonitoredItemQueue`, alarm
sampling rate, `IntervalRunner`, server diagnostics, configuration state
machines, hosted services.
- **Client** — `Session`, managed/V2 subscription engines, reconnect
handlers, channel keep-alive, periodic publishing, complex-type
discovery polling.
- **PubSub** — `IntervalRunner` pipeline, message-receive timers,
MQTT/UDP keep-alive, publishers/readers.
- **Gds / Lds** — `LdsServer`, `LinqApplicationsDatabase` expiry
housekeeping, GDS clients (push, pull), `DirectoryCertificateStore`,
`ConnectionStateMachine`, classic subscription engine.
- **Quickstarts / Console samples** — `SampleNodeManager`,
`ReferenceNodeManager`, `AlarmNodeManager`, `BoilerState`,
`MemoryBufferState`, `PublishedValuesWrites`. Samples resolve via
`(Server as ITimeProviderProvider)?.TimeProvider ?? TimeProvider.System`
so existing ctor signatures stay binary-compatible.
- **Tests** — `Opc.Ua.PubSub.Tests` adds `IntervalRunnerTests`; existing
`SubscriptionTests`, `UaPublisherTests`, and `TestDataSystem` move off
`HiResClock`. Added `Microsoft.Extensions.TimeProvider.Testing` package
for `FakeTimeProvider` (project-load warning surfaces on net48/net472
only — runtime is .NET 8+).
### Migration guide
New section [**Time and Timer abstraction
(`TimeProvider`)**](Docs/MigrationGuide.md#time-and-timer-abstraction-timeprovider)
documents:
- The canonical replacement table (`HiResClock.UtcNow` →
`timeProvider.GetUtcNow().UtcDateTime`, `HiResClock.TickCount64` →
`timeProvider.GetTimestamp()`, `new Timer` → `timeProvider.CreateTimer`,
`Task.Delay(delay, ct)` → `Task.Delay(delay, timeProvider, ct)`, …).
- The `TimeProvider? timeProvider = null` + `??=` constructor pattern.
- DI wiring and how to swap in `FakeTimeProvider` in tests.
- Before/after snippets for `HiResClock.TickCount64`,
`HiResClock.UtcNow`, and `new Timer(...)`.
## Related Issues
- Fixes#2458
## Checklist
- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [ ] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [ ] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [ ] I have addressed **all** PR feedback received.
# Description
Introduces a pluggable user-identity provider model covering all OPC UA
Part 6 §6.5 mechanisms (Anonymous, UserName, X509, IssuedToken/JWT) on
both client and server, with full
`Microsoft.Extensions.DependencyInjection` integration, plus the Part 12
§9 `AuthorizationService` two-phase token-request flow **including
refresh-token rotation**, the Part 12 §8 KeyCredential Push model, and a
clean provider model for OPC 10000-12 §7.2 `ApplicationSelfAdmin`. The
work is split across phase-by-phase commits so it can be reviewed
independently; nothing here changes wire-level behaviour or forces
existing applications to migrate.
### Documentation
All under `Docs/`:
- `IdentityProviders.md` — full developer guide: three-layer model,
recipes, configuration reference, "what gets auto-wired" matrix, JWS
algorithm table, identity-augmenters section, **"Implementing your own
provider"** how-to subsections for Entra / OIDC / Windows / AspNetCore
(sibling files merged in per review feedback).
- `DependencyInjection.md` — `Identity` sections with `appsettings.json`
examples, identity-extension matrix, `WithAuthorizationService` +
`WithKeyCredentialPush` + `AddIdentityAugmenter` extensions documented.
- `RoleBasedUserManagement.md` — claim-criteria callout describing
`IIdentityClaims` probe surface.
- `AuthorizationService.md` — Architecture diagram +
`IAccessTokenProvider` conceptual narrative restored from master; modern
`StartRequestToken` / `FinishRequestToken` flow leads; refresh-token
recipe added.
- `KeyCredentialService.md` — Push model + Pull vs Push vs Bridge
decision matrix + Hybrid (Push + Pull) section; explicit experimental
warning for the bridge.
- `GDS.md` — KeyCredential Push, `StartRequestToken`,
`GdsApplicationSelfAdminProvider`, **shipped Refresh-token support with
rotation policy and audit semantics** all documented.
- `MigrationGuide.md` — User Identity Providers section listing
`[Obsolete]` markers + mechanical recipes; SelfAdmin migration via
`IIdentityAugmenter`; `EnableRefreshTokens` default note.
- `README.md` index entries.
## Checklist
- [x] I have signed the
[CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf)
and read the
[CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md)
doc.
- [x] I have added tests that prove my fix is effective or that my
feature works and increased code coverage.
- [x] I have added all necessary documentation.
- [x] I have verified that my changes do not introduce (new) build or
analyzer warnings.
- [x] I ran **all** tests locally using the **UA.slnx** solution against
at least .net **framework** and .net **10**, and all passed.
- [x] I fixed **all** failing and flaky tests in the CI pipelines and
**all** CodeQL warnings.
- [x] I have addressed **all** PR feedback received.
## Proposed changes
This PR updates the server monitored-item pipeline to be
`IAsyncNodeManager`-aware and introduces channel-based FIFO queueing in
the monitored-node path to improve behavior under load.
It also includes follow-up fixes from review/CI feedback:
- Adjusted
`AsyncCustomNodeManagerTests.WriteAsync_PublishesValueToMonitoredItemQueueAsync`
to account for channel-based delivery timing/coalescing while still
asserting the written value is observed.
- Merged latest `master` into this branch and resolved merge conflicts
(notably in `ConfigurationNodeManager`), keeping async address-space
lookup behavior intact.
- Applied small compile-safety corrections needed for successful
validation.
Drive the solution to zero warnings / zero errors with analyzers on,
promote the consistently-fixed rules to error, and lock in coverage
on the only line of new logic.
* GC reduction via IPooledEncodeable activator pooling
Add opt-in activator-level pooling for IEncodeable instances decoded
during V2 subscription publish dispatch. The design replaces the
earlier IAllocator-on-IServiceMessageContext approach (which had a
cross-contamination hazard for non-publish decodes) with a clean
factory-based model where pooling lives on the encodeable activator.
New public API:
- IPooledEncodeable : IEncodeable - opt-in marker with Reuse() method
- PooledEncodeableType<T> : EncodeableType<T> - activator base with
BoundedObjectPool<T> (lock-free, no new package dependency)
- ISubscriptionManager.PoolNotifications { get; set; }
- ManagedSessionOptions.PoolNotifications { get; init; }
- ManagedSessionBuilder.WithPoolNotifications(bool)
Source-gen:
- All concrete non-abstract structure types (including service
request/response types) are generated with PooledEncodeableType<T>
activators and IPooledEncodeable.Reuse() bodies by default
- Derived types use 'new' to hide inherited Reuse/ClearPooledSentinel
so each concrete type routes through its own activator's pool
- No changes to external design XML files (UA Core Services.xml etc.)
- poolable selection is hardcoded in the generator
Benchmarks (MonitoredItemNotification, 1000 ops):
- Allocations: 128 KB -> 408 B (~315x reduction)
- Gen0 collections: 29.75 -> 0.09 per 1000 ops
No interface changes to IEncodeable, IDecoder, IServiceMessageContext,
or ISubscriptionNotificationHandler. Handlers retain by copy when
pooling is enabled.
Call IPooledEncodeable.Reuse() on decoded IServiceRequest and
IServiceResponse after the server is done with them:
- TcpTransportListener.OnRequestReceivedAsync: reuse both request
and response in a finally block after ProcessRequestAsync +
SendResponse complete
- EndpointBase.InvokeServiceAsync (HTTPS path): same pattern after
ProcessRequestAsync + BinaryEncoder.EncodeMessage
Walk acknowledged, overflow-evicted, and disposed NotificationMessage
objects and call IPooledEncodeable.Reuse() on their notification
payloads (MonitoredItemNotification, DataChangeNotification,
EventFieldList, EventNotificationList).
Insertion points in Subscription.cs:
- Acknowledge(): after RemoveAt from m_sentMessages
- InnerPublish() overflow: before RemoveRange/Clear on m_sentMessages
- Dispose(): before m_sentMessages.Clear()
- InnerPublish() unsent-message overflow: before RemoveRange on
the messages list
Replace new T() with XxxActivator.Instance.CreateInstance() for all
server-side notification payload types so instances are rented from
the activator pool instead of heap-allocated:
New static helper ReuseNotificationPayloads() walks the
NotificationMessage.NotificationData, extracts DataChangeNotification
and EventNotificationList via TryGetValue, iterates their items, and
calls Reuse() on each pooled payload.
* New certificate and secrete abstraction with certificate infrastructure and certificate/secret stores.
* leak testing for certificate resources to validate new ref counting in every test assembly
* Migration guide updated and documentation added for all
* Remove IDisposable from Nodestate and UserIdentity.
* UserCertificateTokenHandler now just points into certificate registry/stores, no dispose required
* Fix CA2000 warnings and cleanup of other diagnostics, increase warning levels in .editorconfig
new DataValue(42) silently resolved to DataValue(StatusCode) instead of
DataValue(Variant) due to C# 'better conversion target' rule — StatusCode
wins because it implicitly converts to Variant, making it 'more specific'.
This caused m_value = Variant.Null and downstream BadTypeMismatch failures.
Changes:
- Add [OverloadResolutionPriority(1)] on DataValue(Variant) constructor
- Obsolete DataValue(StatusCode) and DataValue(StatusCode, DateTimeUtc)
- Add DataValue.FromStatusCode() static factory methods (2 overloads)
- Delete DataValue(DataValue) copy constructor
- Add DataValue.Copy() instance method using base.MemberwiseClone()
- Rewrite Clone()/MemberwiseClone() to delegate to Copy()
- Migrate all call sites across 14 files
- Add tests verifying new DataValue(42) wraps value correctly
- Update MigrationGuide.md
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* make most ptojects aot compatible
* Remove newtonsoft
* Migrate all projects from Mono.Options to System.CommandLine 2.0.5
* Fix array clone
* Replace serializers for storage using new attribute driven type geberator
* Add new AOT integration tests covering all functional areas
* Documentation updates
Use RequestLifetime throughout the server stack for unified request lifetime and cancellation management. Update all service method signatures, OperationContext, and request processing logic to use RequestLifetime, enabling precise tracking of cancellation reasons with UA StatusCodes. Remove obsolete synchronous request handling and legacy delegates. Update code generation, tests, and interfaces to support the new model. This change improves cancellation, timeout, and abort handling, and prepares the server for advanced request management features.
- implement RequestQueue using Channels
- add event load test
- add event integration test verifying event from server object is received
- fix Client Reconnect Test
- fix DiagnosticsNodeManager not creating RootNotifier for Server object
- add Benchmarks for MonitoredItem.QueueEvent
- add serveral UnitTest for DiagnosticsNodeManager
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
Co-authored-by: Marc Schier <marcschier@users.noreply.github.com>
* fix(SubscriptionManager): replace List with ConcurrentDictionary for abandoned subscriptions (#3612)
* replace the semaphore-protected `List<ISubscription>` used for abandoned subscriptions with a `readonly ConcurrentDictionary<uint, ISubscription>`, eliminating three separate lock acquisitions in `SessionClosed`, `DeleteSubscription`, and the publish loop
* add `DeleteAbandonedSubscriptionsConcurrentlyAsync` integration test to cover the concurrent-delete scenario.
* Fix build
---------
Co-authored-by: Marc Schier <marcschier@hotmail.com>
* Refactor MonitoredItem.ValueChanged & cert validation
Refactored MonitoredItem.ValueChanged for correctness, performance, and comprehensive test coverage, including improved deadband and array handling. Rewrote equality logic for Variants and arrays. Made certificate validation thread-safe using ConcurrentDictionary and proper semaphore usage. Added extensive unit tests and benchmarks for value change detection.
* Implement DiagnosticsNodeManager using AsyncCustomNodeManager
* Implement CoreNodeManager using AsyncCustomNodeManager
Refactored MonitoredItem.ValueChanged for correctness, performance, and comprehensive test coverage, including improved deadband and array handling. Rewrote equality logic for Variants and arrays. Made certificate validation thread-safe using ConcurrentDictionary and proper semaphore usage. Added extensive unit tests and benchmarks for value change detection.
* Add namespace index lookup for NamespaceMetadataState
Added GetNamespaceMetadataState(ushort) to ConfigurationNodeManager and interface for efficient lookup by namespace index. Switched to ConcurrentDictionary for thread safety. Updated AsyncCustomNodeManager to use index-based lookup. Cleared index cache in Clear method.
* Refactor Variant and ServiceResult handling for speed
- Use WrappedValue assignment for DataValue in MonitoredNode and NodeState to align with updated Variant usage.
- Return ServiceResult objects instead of raw StatusCodes for bad attribute IDs.
- Update ServiceResult exception handling: include stack trace only in DEBUG, message only in release.
- Optimize StatusCode to ServiceResult conversion by returning static Good/Bad instances.
* Add Read Limited load test
* Optimize MonitoredItem.IsReadToPublish
* Add Subscription unit tests and improve triggering logic
Added SubscriptionTests to verify PublishTimerExpired behavior, including timer expiry, monitored item readiness, keep-alive, and triggering scenarios. Updated Subscription.cs only process triggering if triggered items are configured, improving correctness and efficiency.
* CR feedback
* Use Interfaces Introduced with 1.5.378
Refactor to use interfaces for node managers and server
Replaced concrete types with interfaces (e.g., IMasterNodeManager, ICoreNodeManager, IDiagnosticsNodeManager, IConfigurationNodeManager, IServerBase) across method signatures, properties, and internal structures to improve abstraction and flexibility.
* Refactor CoreNodeManager to be Based on CustomNodeManager2
* Add Test
* Add INodeManager3 with role permission validation
Introduce INodeManager3 interface extending INodeManager2, adding synchronous role permission validation methods. Update all node manager interfaces and classes to use INodeManager3. Extend IAsyncNodeManager with async permission validation methods and update adapters for sync/async bridging. Deprecate FindNodeInAddressSpace in favor of new async FindNodeInAddressSpaceAsync. Refactor MonitoredNode2 to use thread-safe collections and locking for monitored items. Enhance event reporting with security and permission checks. Update constructors and documentation to reflect new interfaces and best practices.
* Implement AsyncCustomNodeManager
* fix comment
* fix
* Add tests
* fix
* Implement better locking strategy
* fix
* Add more tests
* Add tests
* Add tests
* Add Tests
* cleanup
* cleanup
* Add tests that verifies for AnalogItemState the instrument range is checked brefore writing
* only assign new NodeID in default factory if NodeId isNull
* Run all tests also with sampling groups
* Add Docs
* cleanup
* Add chaos test
* fix test
* Use AsyncCustomNodeManager for ReferenceNodeManger & imrpove ReadAttributes method of NodeState
* fixes
* fixes and code review comments
Generate stack and application code using source generators
Change built in types to readonly structs
Update localized text implementation to use JSON text serializer
Status code with symbolic names
Immutable node ids
No boxing for all built in types <= 8 bytes in Variant.
Split user identity token and token handling via token handler
Add migration guide for breaking changes
This pull request modernizes the OPC UA .NET codebase and tests, removes .NET Standard 2.0 support from certificate/security code, and updates test code to use C# 12 and .NET 8+ features for clarity and maintainability.
- Certificate and BouncyCastle interop files (e.g., CertificateBuilder.cs, X509Extensions.cs, X509SignatureFactory.cs) are refactored to drop NETSTANDARD2_0 support and use modern .NET APIs and conditional compilation.
- Test code across the codebase is updated to use default, strongly-typed Parse methods, collection expressions, and improved async/await patterns.
- Exception handling and assertions in tests are modernized, and test method naming is made consistent with Async suffixes.
- The project and build files are updated to clarify Roslynator analyzer usage and remove obsolete netstandard tags.
- General code and test cleanup includes improved null safety, type safety, and removal of deprecated or unused code.
* Improve logging and fix UserNameIdentityToken to return BadIdentityTokenInvalid for failed verification
Refactor DataChangeQueueHandler to return overflow status from QueueValue and Enqueue, updating MonitoredItem to log overflows accurately. Update IDataChangeQueueHandler interface accordingly. Enhance ConsoleTelemetry logger configuration management and ensure proper disposal of old logger factories.
Change UserNameIdentityToken password/nonce failure to return BadIdentityTokenInvalid for more precise error reporting. To prevent the leakage of information useful to attackers, Servers shall ensure that the process of validating UserIdentityTokens completes in a fixed interval independent of whether an error occurs or not. The process of validation includes decrypting, check for padding and checking for a valid nonce. If any errors occur the return code is Bad_IdentityTokenInvalid.
* fix GDS ApplicationNames to include the Locale
* fix ctt testcase by allowing faster sampling for XmlNodeNode
* Initial plan
* Fix ObjectDisposedException in SubscriptionManager background tasks
Add ObjectDisposedException handling in PublishSubscriptionsAsync and ConditionRefreshWorkerAsync to gracefully handle shutdown race condition where semaphore/events are disposed while background tasks are still running.
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
* Update log messages to differentiate normal and disposed shutdown paths
Added clarification in log messages to indicate when tasks exit due to ObjectDisposedException during shutdown, making it easier to distinguish from normal shutdown in logs.
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: romanett <7413710+romanett@users.noreply.github.com>
Refactor to make OPC UA server subscription and monitored item management fully asynchronous, improving scalability and responsiveness. All key methods in ISubscription, ISubscriptionManager, and related classes are now async, with synchronous counterparts removed.
This change adds a **new Opc.Ua.Types** nuget that contains core types that do not rely on generated code. Why the name? Because almost all code that was in the Types subfolder is part of it, and because we do not want to change the name of the Opc.Ua.Core nuget/assembly because code relies on it. Any other name like base or bootstrap felt out of place due to the current structure already defining the name "types". Key design is to depend on only a small set of libraries with limited transitive dependencies, that includes hashcode, logging.abstraction, and for non standard20 builds System.Text.Json (needed for localizedText mul parsing). Also, key is to support .netstd 2.0 to support source generators and to allow removal of EEC_SUPPORT defines by removing std2.0 from core and all libraries.
The changes are mostly restructuring, and thus small but contain some key changes:
- **Status code** struct now comes with a Symbol field, which is used to carry symbols in case the code is not generated. Currently (until generated) the status code struct must be manually created with a symbol or the ToSymbolicId extension must be called in the core project. Future will generate Status code constants just like NodeId that contain the symbol which also removes the reflection-based lookup. Several tests needed to be adjusted as they checked the status code symbol strings instead of the code.
- **Core identifiers** are copied as they were needed for code to compile, that includes attributes, a subset of status codes and node identifiers. These will never change so no need to generate them.
- The types folder now contains **encoders**, except for json which is still in core. Once the json encoder is ported to system.text.json it will also be included and Newtonsoft.Json dropped as dependency (-> #3329).
- Since types relies on **IOperationContext** and **ISystemContext**, and these export IUserIdentity which relies on crypto, these were split and extended in core with ISessionOperationContext and ISessionSystemContext, which mean changes to ServerSystemContext and introduction of SessionOperationContext and SessionSystemContext classes that extend OperationContext and SystemContext. Some runtime checks in the server are therefore needed to get at the session and auth info, however, those are anyway optional fields and are not on the critical paths, and thus a type check is in order (and was done in the past already, but against OperationContext class).
- **Manifest resources** are now split between Core (nodeset zip, some generated resoures) and Types (built in bsd/xsds). This needs to be revisited later if the bsd/xsd need to be regenerated during type generation. Note that the embedded resource names changed as a result. Since these are only used internally and do not constitute public API this feels reasonable vs duplication of resources in 2 assemblies.
- Reflection however now needs to load not just the built in **encodeables** from Opc.Ua.Types assembly, but also the generated encodeables from Opc.Ua.Core assembly. For this a new helper Utils method was added to get the Core assembly when linked against Opc.Ua.Core otherwise null.
- Whatever utils methods needed to be split out into the new Opc.Ua.Types assembly, they are now in **CoreUtils** static class in Opc.Ua.Types, and Utils.xxxx forwards to them to ensure minimal changes. Later we would want to obsolete them in favor of CoreUtils, although it might make sense to split them again into domain specific utilities, such as networking, files, etc
* Refactor SessionPublishQueue for improved Throughput by removing locking on Subscription Enumeration
* fix Send Keepalive on first publish
* resolve threading issue with same subscription being assigned to multiple publish requests
- Remove ConnectAsync from lock. Useable means m_channel is set, not useable means it is null.
- Add comments on lock behavior during connection.
- Remove callback log from validator
- Change TCS creation to specify run continuations async
- Fix encoder factory reflecting every time it is created.
- Allow setting ReturnDiagnostics on the session factory to ensure the diagnostic settings are part of "Create" also. Set them to SymbolicIdAndText by default.
- Better logging in unit tests, now also logs to progress including exception traces, also prefixes SERVER and TEST on console to attach the logs to the server or client side.
- GDS client stability improvements to ensure client reliably reconnects between calls when connection is lost.
- Do not dispose the application certificate when it is updated from GDS client to avoid existing sessions to crash with CryptographicException. This needs more improvements later on because it is rather hacky today.
- Remove the certificate cache in CertificateFactory (as per discussion and agreement) which allowed re-enabling the older UserIdentity API
- Logging improvements here and there to analyze issues in unit tests better
* Server: fix Subscription Keepalive being sent on first publish / Client: Disable Subscription cleanup if subscriptions are being created
* Improve Test stability and increase test timeout
* Update Nuget Packages