# Description Implements the **Asset Administration Shell** companion specifications on top of `marcschier/wot-type-binding`, in two halves that a Server chooses between: * **AAS V3** — the [draft](https://github.com/marcschier/opcua-drafts/tree/main/companion-specs/AAS) (`http://opcfoundation.org/UA/I4AAS/v3/`), all sixteen conformance units: the metamodel, the registry built on the abstract xRegistry base, generational materialization, federation, packages with digest-bound integrity, the Digital Product Passport vocabulary, and the Annex F bridge to WoT Thing Descriptions. * **AAS V2** — the published [OPC 30270](https://reference.opcfoundation.org/specs/OPC-30270/full) (`http://opcfoundation.org/UA/I4AAS/`), which maps the AAS V2.0.1 metamodel: object model, ingestion of XML, JSON and AASX, materialization, server and client. The two are different metamodel generations rather than two revisions of one model — V2 keeps `Asset` as a first-class Identifiable, `identification.idType`, Views and ordered collections, none of which survive into V3 — so they are **alternatives**. A Server hosts one or the other; this is documented rather than enforced at startup. Each is named for the generation it maps (`Opc.Ua.Aas.V2`, `Opc.Ua.Aas.V3`, `AddAasV2Server`, `AddAasV3Server`), and what genuinely serves both carries no marker and sits at the root of `Opc.Ua.Aas`: the deterministic NodeId encoding and idShortPath conventions, `AasOptional<T>`, the digest rule, the materialization diagnostics, the AASX container walk, and the value and operation providers, which are keyed on `NodeId` and `Variant` and so carry no version at all. ## What is in here **New libraries**: `Opc.Ua.Aas`, `Opc.Ua.Aas.Server`, `Opc.Ua.Aas.Client`, `Opc.Ua.Aas.WoT`, plus `samples/Aas` and `docs/Aas.md`. **Enabling changes to existing code**, each needed by the above: * The OPC UA `Decimal` DataType added to `Opc.Ua.Types`, with its Part 6 §5.1.10 wire encoding. `BinaryDecoder` gained one internal member, `TryReadRemainingBodyBytes`, because a trailing field with no self-describing length cannot otherwise be read; `Decimal.Decode` is its only caller. Part 6 Table 3 types the unscaled `Value` as an **OctetString whose byte count is `Length` − 2**, not a length-prefixed `ByteString`, so it carries no length of its own — `DecimalEncodingTests` pins the body byte-for-byte against that mistake, and against the `Length ≤ 2` values the same table calls invalid. * The xRegistry projection engine extracted into `Opc.Ua.XRegistry.Server` and `Opc.Ua.WotCon.Server` migrated onto it (−848/+387 lines), with the WoT Connectivity tests passing **unedited**. * Two source-generator fixes, both of which made a model impossible to build (see below). ## Defects found and fixed along the way Running the stack end to end, rather than trusting per-area test suites, surfaced defects that no unit test caught. The ones worth a maintainer's attention: * **The generator emitted non-terminating constructors.** A structure field with no declared default was initialized with `new T()`, so a self-referential DataType (`AASReferenceDataType.referredSemanticId`) recursed until the stack overflowed and `AddOpcUaAas` could not load the model at all. The test host *died* rather than failing. Only the field that closes a cycle is now left null. * **The generator omitted `new` on a redeclared placeholder.** `AASOrderedSubmodelElementCollectionType` redeclares the `SubmodelElement` slot of its base type, and the generated `Add` method hid the base one without saying so, so the V2 model would not compile. No existing model could have hit either defect — both are build failures, so anything that builds today is unaffected. * **The metamodel half had never worked outside its unit tests**: the emitted NodeSet declared no reference-type aliases and was rejected by the loader; the Mandatory `Invoke` Method was never emitted, because a NodeSet is imported as written rather than instantiated from its type; the runtime bound at the authored namespace index instead of the one the Server assigns; and `MethodDeclarationId` was addressed in the wrong namespace. Every materializer test inspected the in-memory object graph, which cannot see whether the graph is loadable — two tests now import it exactly as `RuntimeNodeSetNodeManager` does. * **The client could not see any Property member.** It browsed `HasComponent` with subtypes, but `HasProperty` is a sibling under `Aggregates`, so reading a value failed and invoking failed argument validation. * **Every repeated registry write forked a duplicate group and resource** instead of adding a version, because the identifier was re-derived against a sibling set that already contained the entity itself. This also made the persistence bounds unreachable. * `.gitignore`'s `**/packages/*` silently swallowed the whole package-integrity implementation and its tests, which would have vanished on a fresh clone. ## Specification findings Nine findings against the V3 draft are fixed in [marcschier/opcua-drafts#75](https://github.com/marcschier/opcua-drafts/pull/75). The substantive one: clause 6.1.5's absent-versus-empty rule was **unsatisfiable** for five container fields that materialize as parent components with no node of their own, which made `AAS-LosslessRoundTrip` unachievable. OPC 30270 contradicts itself twice. Both are recorded in `AasV2ConformanceUnits.cs` and the documentation rather than smoothed over: Table 83 spells the unit `I4AAS MultiLangaugeProperty` where Table 85 spells it correctly, and Table 85 lists an `I4AAS Security` unit that Table 83 never defines. Table 84, which would assign profile URIs, is empty, so `ServerProfileArray` gains no I4AAS entry. ## Known limitation Calling an `Operation` **with arguments** answers `BadTooManyArguments`. Method resolution works from both the instance NodeId and the `MethodDeclarationId`, and the argument definitions are published, but `NodeState.AddChild` does not route through `MethodState.FindChild`, so a Method imported from a NodeSet leaves its typed `InputArguments` null. Closing this means changing how the shared NodeSet import claims typed children, which affects every consumer of runtime NodeSets and is out of scope here. It is documented in `docs/Aas.md` §11, the conformance matrix marks `AAS-OperationInvoke` partial rather than claiming it, and `samples/Aas` exercises the path and reports the status rather than working around it. V2 is unaffected — its `Operation` is an OptionalPlaceholder with no declared arguments. ## Related Issues - No tracking issue yet. Opening as a **draft** for design discussion first, per the ADR guidance below; happy to open one and link it once the shape is agreed. ## 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. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. ### Verification | Check | Result | |---|---| | AAS tests | **670 passed, 0 failed** on net472, net48, net8.0, net9.0, net10.0 | | Coverage | Client 80.8 %, Server 81.2 %, `Opc.Ua.Aas` 82.0 %, WoT 82.4 % — all above the 80 % gate | | Libraries | `Opc.Ua.Aas`, `.Server`, `.Client`, `.WoT` build clean on every target framework, zero warnings | | Regression | `Opc.Ua.Types` 8677, `Opc.Ua.WotCon` 1094, `Opc.Ua.XRegistry` 198, `Opc.Ua.Server` 4050 — all green | | Sample | `samples/Aas` builds warning-free and runs end to end | | Merge validation | Solution builds clean on net10.0 and net48; WoT Types 504, WotCon 1111, AAS 670, XRegistry 198 tests passed | | CI | All 99 checks green on `ff9298e44`; only the CLA signature status is outstanding | ### Review pass A full review against both specifications, and for API consistency and correctness, produced twelve fixes. Each one has a test that fails without it. | Defect | Where | Why it mattered | |---|---|---| | V2 projection aborted on **every** `File` read from a document | `AasV2EnvironmentRuntime` | The runtime bound `File/Value` unconditionally, the materializer emitted it only with content, and the builder throws `BadNotFound` for an unknown NodeId — aborting the whole registration. No reader ever populates `AasFile.File`, so no AAS V2 document could be hosted at all. | | `aas-suppl` anchored on the wrong part | `AasxPackageReaderCore`, `AasxPackageWriter` | IDTA and the Package Explorer anchor it on the environment part; we used the origin part. Every real `.aasx` returned zero supplementary files, silently. Affects both halves. | | Federation failed closed on pooled connections | `AasFederation` | `ConnectCallback` fires only for new connections, so the second fetch to an origin — and all of net472/net48/netstandard2.1 — failed with a security-flavoured error. The peer is now validated *inside* the callback, which makes reuse safe by construction. | | Malformed `Decimal` escaped as `ArgumentOutOfRangeException` | `BinaryDecoder` | A declared body shorter than `Scale` produced a negative read length. Two of the three test cases had been passing for the wrong reason. | | V2 and V3 cross-wired their value providers | `OpcUaAasServerBuilderExtensions` | Both registered `IAasValueProvider`; whichever was added first served both AddressSpaces. V2 now has its own contract, so co-hosting is harmless rather than silently wrong. `EnvironmentFolder` was also bound and ignored on the V2 path. | | Export filter skipped three nesting kinds | `AasEnvironmentExporter` | Content under `Entity`, `AnnotatedRelationshipElement` and `Operation` was exported unevaluated *and* stamped with a Digest presenting it as complete (clause 6.5.10). List authorization paths also shifted after a denial. | | Concealment held at the Method but not in the projection | `AasRegistryModel` | `GetSubmodel` answered `BadNotFound` while an anonymous Browse revealed the node, its identifier, semanticId and digest (clause 6.5.7). | | File handles were unsynchronized and unowned | `AasElementFileManager` | The async node manager holds no lock, so concurrent Calls raced a bare `Dictionary`; sequential handles let any Session read, seek or commit another's. Writes were also unbounded. | | Projection host was unimplementable outside the stack | `AasEnvironmentProjection` | The handle demanded a type with an internal constructor — our own tests used `FormatterServices.GetUninitializedObject` to get round it. Now mirrors WotCon's interface-typed registration. | | Embedded `FileType` omitted 7 of 10 Mandatory members | `AasEnvironmentMaterializer` (V2) | OPC 10000-3 6.4.4 requires them all; without `Size` and `OpenCount` a Client cannot size a read or detect an abandoned handle. | | Round-trip oracle ignored most of the model | `AasRoundTripComparer` | `Blob`, `File`, `ReferenceElement` and `BasicEventElement` had no case arm, so their fields compared equal by falling off the switch; `valueType`, `semanticId`, `entityType` and `Key.type` were never read. The clause 6.4 losslessness claim rested on it. | Known, unchanged: calling an `Operation` with arguments answers `BadTooManyArguments`, because `NodeState.AddChild` does not route through `MethodState.FindChild`. Documented in `docs/Aas.md` §11. Not addressed in this pass, and worth a maintainer decision: OPC 30270 §9.2 says all NodeIds of Nodes not defined in the companion specification **shall not** use the standard namespaces, and Table 87 marks a vendor-specific instance namespace Mandatory. Both halves currently mint instances in the companion namespace. Separating them touches NodeId minting, the runtime and the client together, so it is better done deliberately than folded into a review pass. This is a large change and touches shared code (`Opc.Ua.Types`, the source generator, the xRegistry projection). It is deliberately a draft: the enabling changes are separable if maintainers would prefer them split into their own PRs. The latest `master` is merged into this branch in `0dd0ff0e1`. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9e6a5abf-3299-4cd1-9855-010fedbf0ad8 Copilot-Session: c3d88950-4a65-4ff6-87d2-1f545a875c9b Copilot-Session: b8ab3763-b9bd-46ae-b0ef-045db26e5782
31 KiB
OPC UA Profiles and Facets Support
This document describes which OPC UA Profiles and Facets are implemented in the OPC UA .NET Standard Stack, and where in the codebase / documentation each one lives.
Overview
The OPC UA .NET Standard Stack is a reference implementation that targets OPC UA specification version 1.05.07. The stack has been certified for compliance through an OPC Foundation Certification Test Lab and is continuously tested for compliance using the latest Compliance Test Tool (CTT).
Version 2.0 substantially extends companion-spec coverage over the previous 1.5.378 version. The stack now ships full server- and client-side support for: Part 9 (Alarms & Conditions), Part 11 (Historical Access) + Part 13 (Aggregates), Part 16 (State Machines), Part 17 (Alias Names), Part 18 (Role Management), Part 20 (File Transfer), Part 100 (Device Integration / Software Update), OPC 30270 / OPC UA for Asset Administration Shell V2 plus the AAS V3 draft, OPC 10100-1 (WoT Connectivity), OPC 40001-1 (Industrial Automation), OPC 40010-1 (Robotics), and the Local Discovery Server. See What's New in 2.0 for the broader change narrative.
The canonical list of all OPC UA profile and facet URIs is maintained by the
OPC Foundation at https://profiles.opcfoundation.org/. Where this document
hyperlinks a URI, that URI is the same string the reference server
advertises in ServerProfileArray; URIs not yet present in a shipping
config are referred to by name and the reader should consult the OPC
Foundation registry for the canonical URI form.
Server Profiles
The reference server (samples/ConsoleReferenceServer) advertises the
following profiles in its ServerProfileArray:
Core Server Profiles
- Standard UA Server Profile (2017) — The core OPC UA Server profile that includes:
- Basic server capabilities
- Discovery services
- Session management
- Subscription management
- MonitoredItem services
- View services (Browse, BrowseNext, TranslateBrowsePathsToNodeIds)
- Attribute services (Read, Write, HistoryRead, HistoryUpdate)
- Query services
Functional Facets
- Data Access Server Facet — Variables, data types, and data-change notifications.
- Method Server Facet — Method calls on objects in the address space.
- Reverse Connect Facet — Server-initiated connections to a client (see Reverse Connect documentation).
- Client Redundancy Facet — Subscription transfer between sessions/servers; see Transfer Subscriptions.
- Historical Raw Data Server Facet (2022) — Historical read (and insert/replace/update/delete) of raw data values. The reference server historizes the full static scalar type set via
InMemoryHistorianProvider; see Historical Access. - Historical Aggregate Server Facet (2022) — Aggregate (processed) history reads computed from the raw values by
AggregateManager; see Aggregates.
Local Discovery Server (LDS) Profile
The Opc.Ua.Lds.Server library plus the ConsoleLdsServer reference
application implement the Local Discovery Server. The LDS application
advertises the Local Discovery Server 2017 Facet
(see samples/ConsoleLdsServer/Lds.Server.Config.xml).
Additional facets supported by the implementation (beyond the default advertised set)
Beyond the seven facets advertised by default in the reference server's
ServerProfileArray, the master branch implements the following facets in
the SDK. They can be enabled per-application by registering the
corresponding NodeManager and, where applicable, adding the matching URI to
ServerProfileArray (consult https://profiles.opcfoundation.org/ for the
canonical URI string before claiming a facet):
- Alarms and Conditions (Part 9) — Full server-side implementation
with latched / silenced / out-of-service alarms, alarm groups, a
suppression engine, and rate metrics. The reference server's
AlarmNodeManagerexposes a working sample. See Alarms and Conditions. - State Machine (Part 16) —
StateMachineBuilderand theFluentFiniteStateMachineStateextensibility insrc/Opc.Ua.Server/StateMachines/. The reference server'sBoilerStateMachineStateis an end-to-end sample. See State Machines. - File Access (Part 20) — Server-side
FileSystemNodeManager+IFileSystemProviderinsrc/Opc.Ua.Server/FileSystem/. The reference server enables it via theEnableFileSystemNodeManageroption. The matching System.IO-style client lives inFileSystemClient. - Node Management (Part 4 service set) —
INodeManagementAsyncNodeManageropt-in plus a per-NodeManagerAllowNodeManagementgate forAddNodes/DeleteNodes/AddReferences/DeleteReferences. See Node Management. - Alias Names (Part 17) —
AliasNameStoreand the optionalAliasNameNodeManagerforAliasNameCategory/FindAlias/FindAliasVerbose/AddAliasesToCategory/DeleteAliasesFromCategory/LastChange. The reference server wires the standard Aliases and Topics nodes viaConfigureAliasNameStore. See Alias Names. - WoT Connectivity (OPC 10100-1) —
Opc.Ua.WotCon/Opc.Ua.WotCon.Server/Opc.Ua.WotCon.Clientlibrary trio for surfacing OPC UA servers as Web-of-Things Thing Descriptions. See WoT Connectivity. - Asset Administration Shell —
Opc.Ua.Aas/Opc.Ua.Aas.Server/Opc.Ua.Aas.Client/Opc.Ua.Aas.WoTcarry two alternative halves: OPC 30270 / AAS V2 ingestion-only metamodel support and the AAS V3 draft model with serialization, metamodel server/client, xRegistry-based registry, packages, federation and WoT bridge. See Asset Administration Shell. - Device Integration (Part 100) —
Opc.Ua.Di/Opc.Ua.Di.Server/Opc.Ua.Di.Clientlibrary trio, including the lock service and the software-update package store. See Device Integration and Software Update. - Relative Spatial Location and Global Positioning (Parts 210 and 211) —
Opc.Ua.Positioning/Opc.Ua.Positioning.Server/Opc.Ua.Positioning.Clientimplement the released RSL and GPOS models, including RSL spatial lists and model changes plus the GPOS GlobalPosition, GlobalLocation, and Zones conformance units. See Positioning. - Robotics (OPC 40010-1) over Industrial Automation (OPC 40001-1) —
Opc.Ua.Robotics/Opc.Ua.Robotics.Server/Opc.Ua.Robotics.Clientlibrary trio implementing the released Robotics 1.02 model over IA and Device Integration, with validated fluent topology builders for motion device systems, controllers, motion devices, axes, power trains, motors, gears, drives, safety states, and task controls. See Robotics. - Role Management (Part 18) — Server-side role administration plus a
pluggable identity-provider model for anonymous,
username, X.509, and token-issuer flows. The server automatically
assigns the OPC UA Part 3 §4.9
TrustedApplicationrole; see also Role-Based User Management. - Auditing — The server raises audit events for security-relevant
service calls (channel/secure-channel/session/activate/cancel). The
audit and redaction APIs are provided by
Opc.Ua.Server. - Model Change Tracking — Server-side
ModelChangeAggregatorwith auto-emittedGeneralModelChangeEventfromCustomNodeManager; client-side per-nodeINodeCache.InvalidateNode. See Model Change Tracking. - Durable Subscriptions — Subscriptions that persist across reconnects. See Durable Subscriptions.
- Complex Types — Custom structures and enumerations; see Complex Types.
- Async server NodeManagers — TAP-based
AsyncCustomNodeManageris the recommended base for new NodeManagers, and every NodeManager shipped with the stack has migrated to it. See Async Server Support. - Server redundancy (Part 4 §6.6) —
AddServerRedundancy(...)publishes theServer.ServerRedundancyobject, drivesServer.ServiceLevel, and supports everyRedundancySupportmode (None / Cold / Warm / Hot / HotAndMirrored / Transparent). Non-transparent modes advertise theNTRSdiscovery capability and return the peer set fromFindServers;RequestServerStateChangesupports administrator-driven Maintenance / NoData failover. Opt-in distributed high availability — address-space, session, and subscription mirroring over an in-package CRDT (eventual) or Raft (strong) shared store, plus a Kubernetes deployment — is provided by theOpc.Ua.Redundancy,.Server,.Client, and.Kubernetespackages. See High Availability.
Client Profiles
The client (Opc.Ua.Client) supports the standard UA Client functionality
through two coexisting paths:
- Classic
Session— the lowest-level OPC UA session primitive, paired withSessionReconnectHandlerfor caller-driven reconnect. ManagedSession— recommended for new code. Encapsulates the connection state machine, reconnect policy, and pluggable subscription engine behind a fluent builder. See Sessions, Reconnection, and Subscription Engines.
Client-side feature coverage:
- Subscriptions and monitored items — Both the classic publish
engine and the V2 subscription engine (
ISubscriptionManager/DefaultSubscriptionEngine) are supported and selectable per session. The V2 surface includes a declarative + imperativeSetTriggeringAPI with N:M support and automatic replay on recreate / reconnect, plus anIStreamingSubscription(IAsyncEnumerable-based) facade for state-machine waits and short-lived monitoring (ManagedSession.DefaultStreaming,TakeUntilAsync/WithTimeoutAsynchelpers). See Subscriptions and Monitored Items. - Transfer Subscriptions — Subscription transfer between servers;
see Transfer Subscriptions. An opt-in
SubscriptionRecoveryPolicylets the client tolerateGood_SubscriptionTransferrednotifications from the server. - Reverse Connect — Client can accept connections initiated by the server; see Reverse Connect.
- Model Change Tracking — Client-side per-node cache invalidation driven by server-emitted model-change events; see Model Change Tracking.
- File System Operations — Async,
System.IO-style client over OPC UA file methods; see FileSystemClient. - Alarms and Conditions — Typed
AlarmClientevent records, fluentAlarmEventFilterBuilder, andIAsyncEnumerablealarm streaming viaAlarmStreamExtensions; see Alarms and Conditions. - Historical Access —
HistoryClient(session.Historian()) for raw, modified, at-time, processed (aggregate), and annotation reads / updates; see Historical Access. - State Machines — Streaming and read helpers
(
GetCurrentFiniteStateAsync,ObserveFiniteTransitionsAsync,WaitForStateAsync) on the source-generated*TypeClientproxies; see State Machines. - NodeSet Export — Extract a server's address space to NodeSet2 XML; see NodeSet Export.
- Source-generated typed proxies —
*TypeClientproxies for ObjectTypes inside loaded models give strongly-typed method-call signatures; see Source-Generated NodeManagers. - Complex types — Decode and consume server-defined structures and enumerations on the client; see Complex Types.
Transport Profiles
The stack implements the following transport profiles:
Client and server transports
-
UA TCP Transport (
opc.tcp://) — Primary OPC UA binary transport over TCP.- Full UA Secure Conversation (UASC)
- Binary encoding
- Reverse-connect capability
-
HTTPS Binary Transport (
opc.https://andhttps://) — OPC UA binary protocol over HTTPS with TLS. -
HTTPS JSON Transport (
opc.https://andhttps://) - OPC UA JSON (compact / reversible) over HTTPS (OPC UA Part 6 §7.4.5)- Compact JSON encoding (
application/opcua+uajson) - TLS/SSL encryption only — no UA SecureChannel layer
- Restricted to
MessageSecurityMode.None; transport security is provided exclusively by TLS
- Compact JSON encoding (
-
WebSocket Secure (UA Binary) (
opc.wss://andwss://) - UA Binary + UASC over secure WebSockets (OPC UA Part 6 §7.5.2, sub-protocolopcua+uacp)- Same UASC SecureChannel pipeline as
opc.tcpcarried over WebSocket binary frames (one frame per MessageChunk) - Supports all security modes (None / Sign / SignAndEncrypt)
- TLS/SSL encryption at the WebSocket layer
- Same UASC SecureChannel pipeline as
-
WebSocket Secure (JSON) (
opc.wss://andwss://) - OPC UA JSON over secure WebSockets (Part 6 §7.5.2, sub-protocolopcua+uajson)- Compact JSON encoding per WebSocket text frame
- TLS/SSL encryption only — no UA SecureChannel layer
- Restricted to
MessageSecurityMode.None
-
HTTPS OpenAPI (
opc.https://andhttps://) - OPC UA OpenAPI Mapping (Part 6 §G.3) — official OPC Foundation profile/2338, URIhttp://opcfoundation.org/UA-Profile/Transport/https-uajson-openapi- Path-routed REST surface:
POST /<service>(e.g./read,/browse,/createsubscription) - Body is the bare
<Service>Request/<Service>Response— no{UaTypeId, UaBody}envelope at the HTTPS layer - Compact (default, mandatory per §5.4.9) and Verbose JSON flavours selected via the
application/json; encoding=compact|verbosemedia-type parameter - TLS/SSL encryption only — no UA SecureChannel layer
- Restricted to
MessageSecurityMode.None - Authentication via Anonymous, Bearer JWT, HTTP Basic, or Mutual TLS (see WebApi.md)
- Server-side discovery emission:
HttpsServiceHostemits this sub-profile as a discovery-only twin alongside eachSecurityMode.NoneHTTPS-binary endpoint, so discovery-driven clients can find the OpenAPI endpoint without hard-coding the URL. - Shipped as part of the
OPCFoundation.NetStandard.Opc.Ua.Bindings.Httpspackage (net8+ only) - Surfaced via
Profiles.HttpsOpenApiTransport
- Path-routed REST surface:
-
WSS OpenAPI (
opc.wss://andwss://) - OPC UA OpenAPI Mapping over secure WebSockets (Part 6 §7.5.2, sub-protocolopcua+openapi/opcua+openapi+<accesstoken>) — official OPC Foundation profile/2339, URIhttp://opcfoundation.org/UA-Profile/Transport/wss-uajson-openapi- Same on-wire
{TypeId, Body}OPC UA JSON envelope asopcua+uajson, multiplexed over WebSocket text frames; distinguished by the negotiated sub-protocol and the advertised TransportProfileUri - Bearer-token variant negotiates the access token in the sub-protocol name (no
Authorizationheader — required for browser fetch compatibility); the server extracts the token from the sub-protocol name and feeds it through the standardISessionlessIdentityProviderpipeline - Server-side discovery emission: the WSS factories emit this sub-profile as a discovery-only twin alongside each
SecurityMode.NoneWSS binary endpoint, mirroring the HTTPS OpenAPI emission. - Client surface:
src/Opc.Ua.Client/WebApi/WebApiWssTransportChannel.cs; fluent shortcutManagedSessionBuilder.UseWssOpenApiEndpoint(url); DI registration viaservices.AddWebApiTransportChannel()(registers both HTTPS and WSS WebApi channel factories). - Surfaced via
Profiles.WssOpenApiTransport
- Same on-wire
PubSub transports
The PubSub library supports the following PubSub transport
facets (URIs surfaced by Profiles.PubSub*Transport constants in
src/Opc.Ua.Core/Security/Constants/SecurityConstants.cs). Facet
machinery and conformance unit semantics are defined by
Part 7 §4.3.
- PubSub UDP UADP — UDP transport with UADP message encoding.
- PubSub Ethernet UADP — Ethernet (Layer 2) transport with UADP message encoding (see PubSub transports).
- PubSub MQTT UADP — MQTT transport with UADP message encoding.
- PubSub MQTT JSON — MQTT transport with JSON message encoding.
- Datagram-v2 connection profile —
DatagramConnectionTransport2DataType(Part 14 §6.4.1.4) is honoured for UDP transports. TheDiscoveryAnnounceRate,DiscoveryMaxMessageSize, andQosCategoryfields drive discovery cadence and the IP DSCP TOS byte. - PubSub SKS pull / push —
Part 14 §8.5.1
/ §8.5.2: the
AddPubSubSecurityKeyServiceClientextension implements the pull client (callsGetSecurityKeyson a remote SKS), andAddPubSubSecurityKeyServiceServerhosts the in-memory SKS withGet/SetSecurityKeysandAddSecurityGroupmethods bound on the address space. - AES-128-CTR / AES-256-CTR with HMAC-SHA-256 —
Part 14 §8.4.3
message security. Profiles registered as
PubSubAes128CtrPolicy/PubSubAes256CtrPolicy; conformance to NIST SP 800-38A F.5.1 / F.5.5 is asserted by the test suite. - Anonymous certificate-based MQTT auth — the MQTT transport
exposes the
MqttClientAuthenticationOptionswith the certificate-based variant from Part 14 §6.4.2.2.4.
PubSub additionally supports certificate-based MQTT authentication and
considers WriterGroups in MQTT keep-alive calculations.
All transport profiles defined in OPC UA Part 6 §7.4 (HTTPS) and §7.5
(WebSockets) are supported, including the opcua+openapi and
opcua+openapi+<accesstoken> WebSocket sub-protocols (Part 6 §7.5.2
Table 81).
Security Profiles
The stack supports the following security profiles for secure
communication. The canonical set is defined in
src/Opc.Ua.Core/Security/Constants/SecurityPolicies.cs.
RSA-based security policies
- Basic256Sha256
- 256-bit AES encryption
- RSA-OAEP for key encryption
- HMAC-SHA256 for message authentication
- Minimum key size: 2048 bits
- Aes128_Sha256_RsaOaep
- 128-bit AES encryption
- RSA-OAEP for key encryption
- HMAC-SHA256 for message authentication
- Aes256_Sha256_RsaPss
- 256-bit AES encryption
- RSA-PSS signatures
- HMAC-SHA256 for message authentication
ECC-based security policies
ECC support is documented in detail in ECC Profiles.
Traditional ECC curves
- ECC_nistP256 — NIST P-256 with SHA-256
- ECC_nistP384 — NIST P-384 with SHA-384
- ECC_brainpoolP256r1 — Brainpool P-256r1 with SHA-256
- ECC_brainpoolP384r1 — Brainpool P-384r1 with SHA-384
Modern ECC curves (v2.0)
- ECC_curve25519 — Curve25519 with ChaCha20-Poly1305
- ECC_curve25519_AesGcm — Curve25519 with AES-GCM
- ECC_curve448 — Curve448 with ChaCha20-Poly1305
- ECC_curve448_AesGcm — Curve448 with AES-GCM
AES-GCM and ChaCha20-Poly1305 variants (v2.0)
Modern AEAD cipher alternatives for traditional ECC curves:
- ECC_nistP256_AesGcm, ECC_nistP256_ChaChaPoly
- ECC_nistP384_AesGcm, ECC_nistP384_ChaChaPoly
- ECC_brainpoolP256r1_AesGcm, ECC_brainpoolP256r1_ChaChaPoly
- ECC_brainpoolP384r1_AesGcm, ECC_brainpoolP384r1_ChaChaPoly
RSA Diffie-Hellman (v2.0)
- RSA_DH_AesGcm — RSA Diffie-Hellman key agreement with AES-GCM
- RSA_DH_ChaChaPoly — RSA Diffie-Hellman key agreement with ChaCha20-Poly1305
Platform requirements for ECC. ECC support is available on .NET
Framework 4.8, .NET Standard 2.1, and .NET 5.0 or later. Modern curves
(Curve25519, Curve448) and AEAD ciphers (AES-GCM, ChaCha20-Poly1305)
require .NET 8.0 or later (AesGcm.IsSupported /
ChaCha20Poly1305.IsSupported guard the runtime registration). Not all
curves are supported by every OS platform and .NET implementation.
Deprecated security policies
The following security policies are deprecated but still supported for backward compatibility:
- Basic256 — uses SHA-1
- Basic128Rsa15 — uses SHA-1 and RSA-PKCS#1 v1.5
Note. SHA-1 signed certificates are rejected by default
(RejectSHA1SignedCertificates configuration option). These deprecated
policies should only be enabled for compatibility with legacy systems.
Security policy None
- None — No security.
- For testing or isolated networks only.
- Not recommended for production environments.
User Authentication
The stack supports the following user authentication mechanisms:
- Anonymous — No user authentication.
- Username / Password — User credentials encrypted using the active security policy.
- X.509 Certificate — User authentication via X.509 certificates.
- Issued Token — Includes JSON Web Tokens (JWT) and other
IssuerEndpointUrl-driven flows (OAuth2 / OIDC / Entra). The
Identity Providers pluggable model
(
IClientIdentityProvider,IUserTokenAuthenticator,IAccessTokenProvider,ITokenIssuer,IIdentityClaims) is the recommended way to wire these in.
Certificate Types
The stack supports the following certificate types for application authentication:
RSA certificates
- RsaSha256ApplicationCertificateType — RSA with SHA-256 signatures
- Default minimum key size: 2048 bits
- Recommended for production use
ECC certificates
- EccNistP256ApplicationCertificateType
- EccNistP384ApplicationCertificateType
- EccBrainpoolP256r1ApplicationCertificateType
- EccBrainpoolP384r1ApplicationCertificateType
The RejectSHA1SignedCertificates configuration option (on by default)
prevents SHA-1 signed certificates from being accepted. See
Certificates and Certificate Manager
for storage, ref-counted lifetime, and the segregated-interface design.
Global Discovery Server (GDS)
The stack ships a Global Discovery Server implementation that is full OPC UA Part 12 compliance, including:
- Application registration and discovery.
- Pull and Push certificate-management models, including pushing to arbitrary certificate groups and custom certificate groups on the GDS itself.
- Sub-CA revocation without auto-creating an empty CRL.
- Support for both RSA and ECC certificate types and CRLs.
- AuthorizationService (OPC 10000-12 §9) —
OAuth2-style
StartRequestToken/FinishRequestTokenissuance with a pluggableIAccessTokenProvider/ITokenIssuer. - KeyCredentialService (OPC 10000-12 §8) —
Credential issuance for non-OPC UA services such as MQTT brokers and
REST APIs, backed by
IKeyCredentialRequestStore/ISecretStore.
See the GDS Developer Guide for the full feature breakdown and
hosting integration. The Local Discovery Server is a separate library
(Opc.Ua.Lds.Server) and reference application (ConsoleLdsServer) that
advertises the
Local Discovery Server 2017
facet.
Message Encoding
The stack supports the following message encoding formats:
- UA Binary — OPC UA binary encoding (primary for UA-TCP and HTTPS).
- UA XML — OPC UA XML encoding (for configuration import / export and PubSub Dataset XML).
- UA JSON — OPC UA JSON encoding for PubSub MQTT.
- UADP — UA Data Protocol for PubSub.
The 2.0 release ships a new JSON decoder / encoder, array / matrix
abstractions, and a first-class ByteString type. See the
2.0 migration guide — Encoders and Complex Types
for the encoder/decoder migration details and
Complex Types for client-side decode of
server-defined types.
Specification Compliance
- OPC UA Specification: Version 1.05.07.
- Certification: The reference server has been certified for compliance through an OPC Foundation Certification Test Lab.
- Testing: All releases are verified for compliance using the latest Compliance Test Tool (CTT).
- Redundancy (Part 4 §6.6): Server and client redundancy are implemented
(opt-in) —
RedundancySupport,Server.ServiceLevel, non-transparent (ServerUriArray/RedundantServerArray) and transparent (CurrentServerId) modes,RequestServerStateChange, and client-side transparent failover viaManagedSession.WithServerRedundancy(); see High Availability.
Configuration
Server profile configuration
Server profiles are configured in the server configuration file using the
ServerProfileArray element. The reference server's default array is:
<ServerConfiguration>
<!-- see https://profiles.opcfoundation.org/ for the canonical list of profile and facet URIs -->
<ServerProfileArray>
<ua:String>http://opcfoundation.org/UA-Profile/Server/StandardUA2017</ua:String>
<ua:String>http://opcfoundation.org/UA-Profile/Server/DataAccess</ua:String>
<ua:String>http://opcfoundation.org/UA-Profile/Server/Methods</ua:String>
<ua:String>http://opcfoundation.org/UA-Profile/Server/ReverseConnect</ua:String>
<ua:String>http://opcfoundation.org/UA-Profile/Server/ClientRedundancy</ua:String>
</ServerProfileArray>
</ServerConfiguration>
To advertise additional facets (Historical Access, Aggregates, Alarms &
Conditions, File Access, Auditing, NodeManagement, State Machine, etc.)
look up the canonical URI for the facet on
https://profiles.opcfoundation.org/ and add it to ServerProfileArray.
Only advertise a facet that the application genuinely implements — the
Compliance Test Tool will exercise every claimed facet. Bringing the
reference-server and CTT configs in line with the facets the stack
actually implements is tracked in
#3875.
Security policy configuration
Security policies are configured in the SecurityPolicies section:
<SecurityPolicies>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256</SecurityPolicyUri>
</ServerSecurityPolicy>
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep</SecurityPolicyUri>
</ServerSecurityPolicy>
<!-- ECC security policies -->
<ServerSecurityPolicy>
<SecurityMode>SignAndEncrypt_3</SecurityMode>
<SecurityPolicyUri>http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP256</SecurityPolicyUri>
</ServerSecurityPolicy>
</SecurityPolicies>
See the reference server configuration file
for a complete example, or the
CTT configuration file
for the variant selected by --ctt.
Related Documentation
- What's New in 2.0 — Narrative tour of the 1.5.378 → 2.0 changes, grouped by theme and layer.
- Migration Guide — Prescriptive, per-API migration reference.
- Subscriptions and Monitored Items —
V2
ISubscriptionManager, declarative + imperativeSetTriggering(N:M, replay on recreate / reconnect), andIStreamingSubscription. - Async Server Support — TAP-based
AsyncCustomNodeManagerand theIAsyncNodeManagerfamily. - Dependency Injection —
services.AddOpcUa()and theIOpcUaBuilderhosting surface. - Native AOT — AOT publishing, AOT-clean source generators, and the AOT test matrix.
Core and companion spec related documentation
- Alarms and Conditions (Part 9)
- Historical Access (Part 11)
- Aggregates (Part 13)
- State Machines (Part 16)
- Alias Names (Part 17)
- Role-Based User Management (Part 18)
- Identity Providers
- Authorization Service (Part 12 §9)
- Key Credential Service (Part 12 §8)
- GDS Developer Guide (Part 12 full compliance)
- File System Client (Part 20)
- Device Integration (Part 100)
- Relative Spatial Location and Global Positioning (Parts 210 and 211)
- Robotics (OPC 40010-1 over OPC 40001-1)
- Software Update
- Asset Administration Shell (OPC 30270 / AAS V2 and AAS V3 draft)
- WoT Connectivity (OPC 10100-1)
- Node Management (Part 4)
References
- OPC Foundation Profile Reporting — canonical profile and facet URI registry.
- OPC UA Specification — online reference for the OPC 10000 series.
- OPC UA Compliance Test Tool (CTT) — official conformance test tool.