C# / .NET · recipe

Set up OPC UA certificates in C#

The application configuration owns your PKI. Point the four stores at persistent directories, keep AutoAcceptUntrustedCertificates false, and make sure the ApplicationUri matches the URI entry in your certificate's SAN.

StackOPCFoundation/UA-.NETStandard
Version1.5.378.156 stable, 2.0.0-preview.2

The code

var application = new ApplicationInstance
{
    ApplicationName = "MyOpcUaClient",
    ApplicationType = ApplicationType.Client,
    ApplicationConfiguration = await BuildConfigAsync(),
};

// create a self-signed application instance certificate if none exists
bool hasCert = await application.CheckApplicationInstanceCertificates(
    silent: true, lifeTimeInMonths: 24);
if (!hasCert) throw new Exception("no application certificate and none could be created");

var config = application.ApplicationConfiguration;

// surface rejections instead of swallowing them
config.CertificateValidator.CertificateValidation += (sender, e) =>
{
    Console.WriteLine($"peer certificate rejected: {e.Error.StatusCode}");
    Console.WriteLine($"  subject: {e.Certificate.Subject}");
    e.Accept = false;   // never blanket-accept in production
};

var endpoint = CoreClientUtils.SelectEndpoint(config, "opc.tcp://milo.digitalpetri.com:62541/milo", useSecurity: true);
Console.WriteLine($"policy: {endpoint.SecurityPolicyUri}");
Console.WriteLine($"mode  : {endpoint.SecurityMode}");

var configured = new ConfiguredEndpoint(null, endpoint, EndpointConfiguration.Create(config));
using var session = await Session.Create(config, configured, false, "MyOpcUaClient", 60000,
    new UserIdentity(new AnonymousIdentityToken()), null);
Console.WriteLine($"secure session: {session.Connected}");

What it prints

policy: http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
mode  : SignAndEncrypt
secure session: True

Notes

  • CheckApplicationInstanceCertificates generates a self-signed certificate on first run, with the SAN entries derived from your ApplicationUri and hostname. Verify them afterwards rather than assuming.
  • The CertificateValidation handler is how you find out why a peer was rejected. Log the status code and the subject; do not set e.Accept = true to make the problem disappear.
  • In a container, ./pki must be a persistent volume. Otherwise the certificate is regenerated on every restart and every peer's trust list goes stale.
  • The four stores are own, trusted, issuer and rejected. Intermediates go in issuer, not trusted.
  • Set a certificate lifetime you will renew within, and diary it. An expired client certificate stops a line.

What breaks first

A CA-issued certificate is rejected even though the CA is trusted BadCertificateChainIncomplete
Put the intermediate certificates in the issuer store. Also check the CA certificate carries keyCertSign and cRLSign: corporate CAs often do not.

Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.

Free download
OPC UA Troubleshooting & Integration Checklist
The field-tested checklist engineers use to diagnose certificates, ports and namespace problems fast, plus a Python (asyncua) client template.
Get the free checklist →
Free, no course, no login