Python · recipe

Set up OPC UA certificates in Python

Generate a certificate whose SAN contains both the DNS name you will dial and your ApplicationUri as a URI entry, then point the client at the key pair and the security policy. The ApplicationUri in the certificate and in the client configuration must match exactly.

Stackasyncua (FreeOpcUa/opcua-asyncio)
Version2.0.1

The code

# 1. Generate a key pair with the SAN entries OPC UA actually checks.
#    The URI: entry must equal your ApplicationUri, character for character.
#
# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.der -outform DER \
#   -days 730 -nodes -subj "/CN=my-opcua-client/O=Example" \
#   -addext "subjectAltName=DNS:my-host.example.com,URI:urn:example:my-opcua-client" \
#   -addext "keyUsage=digitalSignature,keyEncipherment,dataEncipherment,nonRepudiation" \
#   -addext "extendedKeyUsage=serverAuth,clientAuth"

import asyncio
from asyncua import Client

async def main():
    client = Client(url="opc.tcp://milo.digitalpetri.com:62541/milo")
    client.application_uri = "urn:example:my-opcua-client"   # must match the SAN URI
    await client.set_security_string(
        "Basic256Sha256,SignAndEncrypt,cert.der,key.pem"
    )
    async with client:
        print("secure session established")
        print(await client.get_node("i=2258").read_value())

asyncio.run(main())

What it prints

secure session established
2026-09-08 03:45:12.880000

Notes

  • The SAN is the part everyone gets wrong. It needs a DNS entry matching the host you dial and a URI entry matching your ApplicationUri exactly.
  • Connecting by IP against a certificate whose SAN lists only a DNS name fails. Put every name and address clients will actually use in the SAN.
  • The first secure connection will be refused: your certificate lands in the server's rejected store and an administrator has to move it to trusted. That is the designed workflow, not a bug.
  • Trust must be mutual. The server trusting you is only half of it.
  • Set the certificate validity to a period you will actually renew within, and diary the renewal: an expired client certificate takes a line down.

What breaks first

The secure connection is refused on the first attempt BadCertificateUntrusted
Move your certificate from the server's rejected store into its trusted store, and add the server's certificate to your own trust list.

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