Resolving WinCC TIA V14 OPC UA Client Certificate Trust Failures

David Krause13 min read
OPC / OPC UASiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Resolving WinCC TIA V14 OPC UA Client Certificate Trust Failures

When a WinCC Professional (TIA Portal V14) OPC UA client refuses to connect to a Node.js node-opcua server running on a Raspberry Pi 3 — even though a third-party client (ProSys, UaExpert) connects successfully from the same engineering workstation — the failure almost always traces back to OPC UA application instance certificate trust, SecurityPolicy negotiation, or endpoint URL/ApplicationUri mismatch. This reference walks through a deterministic diagnostic path and field-proven remediation steps for shop-floor deployments.

1. Problem Statement

Engineering workstation symptoms commonly reported:

  • ProSys OPC UA Client (or UaExpert) reads nodes successfully from opc.tcp://<raspi-ip>:4840.
  • WinCC Runtime Professional on the engineering PC starts the OPC UA channel, attempts the CreateSession call, and the channel stays in Connecting or transitions to Faulted.
  • The Windows Rejected certificate folder for the WinCC OPC UA client remains empty — no .der file appears for the Raspberry Pi server's certificate.
  • No certificate is created in the WinCC Runtime's own Own Certificates store, blocking the server-side trust step.

The TIA Portal V14 OPC UA Client channel (WinCC Professional only — Comfort Panels require the OPC UA Client license from V14 SP1 onward) implements the full OPC UA Binary protocol stack, but it stores and validates instance certificates in a WinCC-specific directory tree that diverges from the OPC Foundation reference stack. Engineers who follow the generic "copy the cert to the Rejected folder" instructions from a node-opcua manual end up with an empty reject folder and zero progress.

2. Root Cause Analysis

Four root-cause families cover roughly 95% of WinCC ↔ node-opcua certificate failures:

# Root cause Symptom Detection
A WinCC Runtime account lacks write permission to the Rejected/Trusted certificate folders No .der file appears in Rejected; channel remains Faulted Procmon trace shows ACCESS_DENIED on WinCCRTPro\Certificates\opcua\rejected\
B Server endpoint URL or ApplicationUri does not match the certificate's subjectAltName URI Server returns Bad_CertificateUriInvalid; channel aborted Open server cert with OpenSSL; compare URI: field to configured endpoint
C SecurityPolicy/MessageSecurityMode mismatch between WinCC channel and node-opcua Channel never opens; no cert exchange; Bad_SecurityPolicyRejected Compare WinCC channel SecurityPolicy (None/Basic128Rsa15/Basic256/Basic256Sha256) with server.options.securityPolicies
D Server certificate was issued by a private CA that is not in WinCC's Trusted root store, or has expired WinCC logs Bad_CertificateUntrusted or Bad_CertificateTimeInvalid Inspect cert validity dates and issuer chain
Note: A WinCC Runtime Professional channel does not use the Windows certificate store (certmgr.msc) for OPC UA trust. It uses its own directory under C:\Program Files\Siemens\Automation\WinCC RT Pro\ by default. A certificate that is "Trusted" in Windows is still untrusted to WinCC OPC UA.

3. WinCC OPC UA Certificate Store Architecture

WinCC Runtime Professional V14 stores OPC UA instance certificates in a fixed directory tree. The exact paths are documented in the WinCC Professional system manual (Siemens FAQ 63481236) and the TIA Portal V14 WinCC Professional documentation set.

Folder Default path (WinCC RT Pro, default install) Purpose
Own Certificates %ProgramFiles%\Siemens\Automation\WinCC RT Pro\Certificates\opcua\own\ WinCC client instance certificate (self-signed or CA-issued)
Trusted %ProgramFiles%\Siemens\Automation\WinCC RT Pro\Certificates\opcua\trusted\ Trusted server certificates; once placed here, WinCC accepts the server without prompt
Rejected %ProgramFiles%\Siemens\Automation\WinCC RT Pro\Certificates\opcua\rejected\ Temporary holding area; WinCC writes any untrusted server cert here during first connect
Issuer %ProgramFiles%\Siemens\Automation\WinCC RT Pro\Certificates\opcua\issuer\ Trusted CA / intermediate certificates used to validate the chain

Under TIA Portal V14 (no SP) the runtime uses X.509 v1 self-signed certificates generated at first runtime start. From TIA V14 SP1 onward, X.509 v3 with subjectAltName URI is supported, but the folder layout is unchanged.

Permission trap: On Windows 7/10/11, C:\Program Files is write-protected by default. The WinCC Runtime is started by the SCADAConnect service, which typically runs as LOCAL SYSTEM — that account does have write access. However, when an engineer is debugging by launching WinCCRTPro.exe interactively, the user's ACL may be the bottleneck. The Rejected folder appearing empty is the canonical symptom of this ACL failure.

4. node-opcua Default Server Configuration

The default node-opcua server (as of v0.3.x — the version contemporary with TIA V14, late 2016) generates a self-signed certificate the first time the server starts and stores it next to the running script:

// Typical node-opcua minimal server (V14 era)
const opcua = require("node-opcua");

const server = new opcua.OPCUAServer({
    port: 4840,
    resourcePath: "/UA/Server",          // endpoint = opc.tcp://<host>:4840/UA/Server
    serverInfo: {
        applicationUri: "urn:<host>:NodeOpcUaServer",
        productUri:      "urn:node-opcua:server",
        applicationName: { text: "NodeOpcUaServer" },
        // V14 era defaults — note: Basic128Rsa15 deprecated in 2020
        serverCertificate: null,           // auto-generated on first start
        securityPolicies: [
            opcua.SecurityPolicy.None,
            opcua.SecurityPolicy.Basic128Rsa15,
            opcua.SecurityPolicy.Basic256
        ],
        securityModes: [
            opcua.MessageSecurityMode.None,
            opcua.MessageSecurityMode.Sign,
            opcua.MessageSecurityMode.SignAndEncrypt
        ]
    }
});

server.initialize(() => { server.start(() => console.log("Server ready")); });

The auto-generated certificate is saved as server_cert.pem (PEM, base64 X.509) in the working directory. The matching private key is server_key.pem. Both are 2048-bit RSA, 1-year validity, with subjectAltName URI = urn:<hostname>:NodeOpcUaServer.

When ProSys connects successfully and WinCC fails, the cause is not in the server's cert validity — both clients see the same cert. The cause is on the WinCC side: WinCC is either dropping the cert to the Rejected folder (and the engineer is looking in the wrong directory) or refusing the cert silently because of an ApplicationUri mismatch.

5. Step-by-Step Diagnostic Procedure

  1. Confirm the endpoint URL is reachable. From the engineering PC, open a command prompt and run telnet <raspi-ip> 4840. A black screen means TCP is open; connection failed means firewall on the Pi blocks inbound 4840/TCP.
  2. Verify DNS / hostname resolution. The ApplicationUri in the server cert is bound to a hostname (or IP). The WinCC endpoint must use the same host identifier or the server returns Bad_CertificateUriInvalid. Use the IP literally if hostname resolution is broken.
  3. Open the server cert with OpenSSL on the Pi and capture the subjectAltName URI:
    openssl x509 -in server_cert.pem -noout -text | grep -A1 "Subject Alternative Name"
    # Expected line: URI:urn:raspi3:NodeOpcUaServer
  4. Check the WinCC Runtime service identity. In services.msc locate SIMATIC WinCC RT Pro (and SCADAConnect if present). Confirm the Log On tab account. The LOCAL SYSTEM account is the safest default for OPC UA file access.
  5. Grant the service account write access to all four certificate folders:
    icacls "C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\rejected" /grant "SYSTEM":(OI)(CI)F /T
    icacls "C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\trusted"  /grant "SYSTEM":(OI)(CI)F /T
    icacls "C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\own"     /grant "SYSTEM":(OI)(CI)F /T
    icacls "C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\issuer"  /grant "SYSTEM":(OI)(CI)F /T
  6. Stop and restart the WinCC Runtime (not just the project) so the OPC UA channel re-initialises.
  7. Trigger the OPC UA channel in Runtime. Within ~5 seconds, the Rejected folder should contain a .der file whose filename is the SHA-1 thumbprint of the server certificate. If still empty, the channel never even reached the GetEndpoints call — the failure is at the transport or SecurityPolicy layer, not trust.

6. Solution: Manual Certificate Exchange (Field-Proven)

The most reliable remediation on TIA V14 — where the runtime's automatic trust prompt is not exposed in the HMI — is a deterministic two-side manual exchange.

6.1 Server side: export node-opcua cert to DER

# On the Raspberry Pi
openssl x509 -in server_cert.pem -outform der -out server_cert.der
# Copy the DER to the engineering PC (WinSCP, scp, USB stick)

6.2 Client side: import to WinCC Trusted folder

  1. Stop the WinCC Runtime.
  2. Copy server_cert.der to C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\trusted\.
  3. Append the SHA-1 thumbprint to the Rejected list file (WinCC uses rejected.txt as a denylist; remove the thumbprint from there to be safe).
    openssl x509 -in server_cert.der -inform der -fingerprint -sha1 -noout
    # Example: SHA1 Fingerprint=AB:CD:EF:...
    # Make sure this line is NOT present in:
    #   C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\rejected\rejected.txt
  4. Start the WinCC Runtime and re-arm the OPC UA channel.

6.3 Client side: export WinCC own cert to server

node-opcua, by default, trusts any client certificate placed under trusted/ in its PKI directory (set via server.options.serverCertificateManager). Export the WinCC client cert from the Own Certificates folder and add it to the Pi's trusted store:

# On the engineering PC (PowerShell as admin)
Get-ChildItem "C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\own\" -Filter *.der
# Copy the .der to the Pi and rename to <thumbprint>.der in the node-opcua pki/trusted folder
Symmetric trust: Both sides must trust the other's cert. Skipping the WinCC → Pi step causes the server to reject the client's ActivateSession with Bad_CertificateUntrusted, and the WinCC channel will show as Faulted with no cert in the Rejected folder because the failure happens after WinCC has already accepted the server cert.

7. SecurityPolicy and MessageSecurityMode Alignment

TIA Portal V14 ships with the following OPC UA client-side defaults in the WinCC Professional OPC UA channel:

WinCC setting (TIA V14) Allowed values Default node-opcua counterpart
SecurityPolicy None, Basic128Rsa15, Basic256, Basic256Sha256 (V14 SP1+) None SecurityPolicy.None
MessageSecurityMode None, Sign, SignAndEncrypt None MessageSecurityMode.None
Authentication Anonymous, Username/Password, Certificate Anonymous resourcePolicies / userManager
Endpoint URL opc.tcp://host:port/resourcePath — Must match the URL exposed by GetEndpoints

The fastest path to a green channel in a brownfield factory is to set WinCC to SecurityPolicy = None and MessageSecurityMode = None, confirm the link, then progressively tighten:

  1. None / None → confirms transport and ApplicationUri.
  2. None / Sign → confirms cert exchange path (no payload encryption needed).
  3. Basic256Sha256 / SignAndEncrypt → production target; requires both sides to have SHA-256-capable certs and matching trust.
Basic128Rsa15 is deprecated by the OPC Foundation as of 2019. For new deployments on a Raspberry Pi 3, prefer Basic256Sha256 with a 2048-bit RSA cert and SHA-256 signature. TIA V14 SP1 and later are required for Basic256Sha256 on the WinCC side.

8. Network, Firewall and Timeout Tuning

OPC UA over TCP uses port 4840 by default. On the Raspberry Pi, ensure the OS firewall permits inbound 4840:

# Raspberry Pi OS (iptables legacy)
sudo iptables -A INPUT -p tcp --dport 4840 -j ACCEPT
# or with ufw
sudo ufw allow 4840/tcp

On the Windows engineering PC, allow outbound 4840 through Windows Defender Firewall (usually permitted by default for any local subnet, but corporate GPOs may block).

Session timeout tuning — WinCC's OPC UA Channel Diagnostics view will surface timeouts as the channel cycling between Connecting and Faulted every N seconds. The TIA V14 WinCC OPC UA channel exposes the following parameters in the channel configuration:

Parameter Default Recommended for slow / wireless links
Session timeout (ms) 60000 120000
Publish interval (ms) 500 1000
Keep-alive count 10 20
Connection attempt timeout (ms) 5000 15000

Common OPC Foundation status codes you will encounter in WinCC's channel log:

Hex status Symbolic Meaning Remediation
0x80050000 Bad_CommunicationError TCP / TLS handshake failed Check port, firewall, DNS
0x801F0000 Bad_SecurityPolicyRejected No common SecurityPolicy Lower WinCC policy to None, then escalate
0x80220000 Bad_CertificateUntrusted Issuer not in WinCC Trusted list Import issuer cert to issuer\ or server cert to trusted\
0x80220001 Bad_CertificateTimeInvalid Cert expired or not yet valid Regenerate server cert with node-opcua v0.5+ and a 5-year validity
0x8022000F Bad_CertificateUriInvalid Endpoint URL ≠ cert subjectAltName URI Align URL with the URI field in the cert
0x80060000 Bad_Timeout No response within configured timeout Increase session timeout, check network latency

9. Alternate Configurations and Edge Cases

9.1 Running node-opcua as a systemd service

On a Raspberry Pi 3 with Raspbian Jessie/Stretch, when started via systemd the server's working directory matters: server_cert.pem is generated next to the executable's CWD, not the script. Use WorkingDirectory=/opt/opcua in the unit file and ReadWritePaths=/opt/opcua.

9.2 Raspberry Pi 3 clock / time skew

The Pi has no RTC by default. If the system time drifts more than a few minutes from real time, the server cert (issued "now") will appear either not-yet-valid (Bad_CertificateTimeInvalid) or already expired on the WinCC side. Always enable systemd-timesyncd or install ntp before commissioning.

9.3 ApplicationUri with IP address

If WinCC connects by IP (opc.tcp://192.168.1.50:4840) and the server cert has urn:raspi3:NodeOpcUaServer in subjectAltName, set the node-opcua alternateName option to add a URI entry containing the IP, or change WinCC's endpoint URL to use the hostname. node-opcua v0.5.x+ accepts an altNames array:

const server = new opcua.OPCUAServer({
    // ...
    serverInfo: {
        applicationUri: "urn:raspi3:NodeOpcUaServer",
        // ...
    },
    serverCertificateManager: new opcua.CertificateManager({
        automaticallyAcceptUnknownCertificate: false,
        // ensure the cert's URI field includes the IP variant
    })
});

9.4 Cross-subnet deployment

When the engineering PC and the Pi are on different VLANs, multicast DNS (used by some node-opcua discovery) does not cross L3 boundaries. Use the literal IP in the WinCC endpoint URL and disable discovery on the server side to avoid delays during the FindServers call.

9.5 TIA V14 vs V14 SP1 vs V15

The certificate folder layout is identical, but the supported SecurityPolicy set expands at SP1:

Feature V14 (no SP) V14 SP1 V15 / V15.1
SecurityPolicy Basic128Rsa15 Yes Yes Yes
SecurityPolicy Basic256 Yes Yes Yes
SecurityPolicy Basic256Sha256 No Yes Yes
X.509 v3 with subjectAltName URI No Yes Yes
UA-TCP binary chunking > 64 KB Limited Yes Yes

10. Verification Checklist

After applying the fix, run through the following to confirm a stable channel:

  1. WinCC Runtime channel status reads Connected (green), not Faulted (red).
  2. No new .der file appears in the Rejected folder after a Runtime restart.
  3. ProSys OPC UA Client on a third PC can browse and read the same tags that WinCC is reading.
  4. A node tag in WinCC (e.g. Channel1\Connection1\Tag1) updates at the configured publish interval (default 500 ms).
  5. Stopping the node-opcua process on the Pi causes the WinCC channel to enter Faulted within one publish interval × keep-alive count, and re-establishes within the session timeout when the server returns.
  6. The WinCC OPC UA Channel Diagnostics view shows zero Bad_* service faults over a 10-minute observation window.

11. Troubleshooting Matrix

Symptom Most likely cause First action
Channel stays Connecting, no Rejected cert Firewall blocks 4840 or wrong host telnet <pi> 4840
Rejected cert appears, but channel still Faulted WinCC cert not in node-opcua trusted Export own cert, copy to Pi
Channel connects on None, fails on Basic256 Cert signed with SHA-1, not SHA-256 Regenerate node-opcua cert with v0.5+
Channel connects once, drops every 60 s Session timeout < server's keep-alive interval Set session timeout 120000 ms in TIA
Bad_CertificateTimeInvalid Pi clock skew Enable systemd-timesyncd
Bad_CertificateUriInvalid Endpoint URL ≠ cert URI Match URL or add altNames on server
Channel Faulted after WinCC reboot only Service account ACL lost Re-apply icacls grants

12. Field-Proven Configuration Reference

A minimal working configuration for a TIA V14 SP1 engineering PC talking to a Raspberry Pi 3 node-opcua v0.5.x server on a 192.168.1.0/24 production network:

Setting WinCC (TIA V14 SP1) node-opcua server
Endpoint opc.tcp://192.168.1.50:4840/UA/Server Same, derived from port + resourcePath
SecurityPolicy Basic256Sha256 SecurityPolicy.Basic256Sha256
MessageSecurityMode SignAndEncrypt MessageSecurityMode.SignAndEncrypt
Authentication Anonymous Default resourcePolicies
ApplicationUri (client) urn:<pc-host>:Siemens.WinCC.Pro —
ApplicationUri (server) — urn:raspi3:NodeOpcUaServer
Session timeout 120000 ms Default 60000 ms (server clamps to min)
Publish interval 1000 ms —
Certificate store (client) %ProgramFiles%\Siemens\Automation\WinCC RT Pro\Certificates\opcua\ —
Certificate store (server) — ./pki/trusted/ + ./pki/rejected/ in CWD
Document anchor: For the canonical Siemens-side reference on OPC UA application certificates for HMI systems, see Siemens FAQ 63481236 — "Which settings are required for the OPC UA communication of SIMATIC HMI systems?" and the WinCC Professional V14 SP1 system manual on the Siemens support portal. The OPC UA security concepts chapter defines the directory layout and trust semantics implemented in this fix.

Why does the WinCC Runtime Rejected certificate folder stay empty even though my server cert exists?

The WinCC Runtime is most likely running under a Windows account that lacks write permission on C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\rejected. Verify with Process Monitor or grant SYSTEM full control on all four opcua subfolders and restart the runtime.

My ProSys client connects to node-opcua but WinCC does not — what is different?

ProSys uses the OPC Foundation reference stack and auto-trusts server certificates on first connect in its user-managed trust store. WinCC Runtime Professional uses a vendor-specific directory tree and a strict ApplicationUri check. Align the WinCC endpoint URL with the cert's subjectAltName URI field and import the server cert to the trusted folder manually.

Which OPC UA SecurityPolicy should I use on a Raspberry Pi 3 with TIA V14?

Use Basic256Sha256 for new deployments. It requires TIA V14 SP1 or later on the WinCC side and node-opcua v0.5.x or later on the Pi. For brownfield compatibility, None is acceptable on a closed factory network but is not recommended for any link that leaves the cell.

How do I export the WinCC client certificate to add to node-opcua's trust list?

Stop the runtime, navigate to C:\Program Files\Siemens\Automation\WinCC RT Pro\Certificates\opcua\own\, copy the .der file to the Pi and place it in the node-opcua pki/trusted/ directory with the SHA-1 thumbprint as the filename. Restart both services.

The WinCC channel shows Bad_CertificateTimeInvalid even though the date is correct on both PCs. Why?

The Raspberry Pi 3 has no hardware RTC. If the system time on the Pi drifts from real time, the server certificate may already be expired (or not yet valid) from the WinCC client's perspective. Enable NTP via systemd-timesyncd and force a clock sync before commissioning.

Back to blog