Endpoint Auto-Selection
OPC UA servers expose multiple endpoints, each with a different combination of security policy and security mode. Endpoint auto-selection discovers all available endpoints and picks the most secure one automatically, so you don’t need to know the server’s security configuration in advance.
How It Works
When auto-selection is enabled, the client performs these steps before connecting:
- Opens a temporary
SecureChannelwithSecurityPolicy#Noneto the server - Sends a
GetEndpointsrequest to retrieve all available endpoints - Scores each endpoint based on its security policy and mode
- Selects the highest-scoring endpoint that matches the URL scheme (
opc.tcp) - Closes the temporary channel and connects to the selected endpoint
This follows the OPC Foundation reference implementation pattern — discovery always uses an unsecured channel, then the real connection uses the discovered security settings.
Selection Algorithm
Each endpoint receives a security level score based on its security policy and mode. The endpoint with the highest score wins.
Policy Base Scores
| Security Policy | Base Score |
|---|---|
| None | 0 |
| Basic128Rsa15 | 2 |
| Basic256 | 4 |
| Basic256Sha256 | 6 |
| Aes128_Sha256_RsaOaep | 8 |
| Aes256_Sha256_RsaPss | 10 |
| ECC_brainpoolP256r1 | 11 |
| ECC_nistP256 | 12 |
| ECC_brainpoolP384r1 | 13 |
| ECC_nistP384 | 14 |
| ECC_curve25519 | 15 |
| ECC_curve448 | 16 |
Mode Modifier
| Security Mode | Modifier |
|---|---|
| Sign | +0 |
| SignAndEncrypt | +100 |
| None | Score is 0 regardless of policy |
For example, Aes256_Sha256_RsaPss + SignAndEncrypt scores 110 (10 + 100), while ECC_curve448 + Sign scores 16 (16 + 0). SignAndEncrypt is always preferred over Sign for the same policy.
The useSecurity Toggle
The selector accepts a useSecurity parameter:
true(default) — only considers endpoints withSignorSignAndEncryptmode and a recognized security policy. Falls back to the first URL-matching endpoint if no secure endpoint is available.false— only considers endpoints withSecurityMode.None. Useful for development servers or when connecting to servers that only support unsecured transport.
Client Library Usage
Enable auto-selection with the WithAutoSelectEndpoint() builder method:
// Auto-select the most secure endpoint
var client = new OpcSharpClientBuilder()
.WithEndpoint("opc.tcp://192.168.1.100:4840")
.WithAutoSelectEndpoint()
.WithAutoAcceptUntrustedCertificates(true)
.Build();
await client.ConnectAsync();The client will discover endpoints, pick the best one, generate a self-signed application certificate if needed, and connect — all within ConnectAsync().
For development servers that only support unsecured transport:
var client = new OpcSharpClientBuilder()
.WithEndpoint("opc.tcp://localhost:4840")
.WithAutoSelectEndpoint(useSecurity: false)
.Build();
await client.ConnectAsync();You can combine auto-selection with user credentials:
var client = new OpcSharpClientBuilder()
.WithEndpoint("opc.tcp://192.168.1.100:4840")
.WithAutoSelectEndpoint()
.WithUserIdentity(new UserNameIdentity("operator", "password"))
.WithAutoAcceptUntrustedCertificates(true)
.Build();
await client.ConnectAsync();The selector automatically matches the user identity type to a supported UserTokenPolicy on the chosen endpoint.
CLI Tool Usage
The CLI tool uses endpoint auto-selection as the default behavior for the browse, read, and check commands. You no longer need to specify --security-policy and --security-mode manually.
# Connects using the most secure endpoint automatically
opcsharp browse opc.tcp://192.168.1.100:4840
# Same for read
opcsharp read opc.tcp://192.168.1.100:4840 i=2258--no-security Flag
Use --no-security to force a connection without security (equivalent to useSecurity: false):
# Connect to a development server with no security
opcsharp browse opc.tcp://localhost:4840 --no-securityIf you provide --security-policy or --security-mode explicitly, auto-selection is bypassed and the specified values are used directly.
Enhanced discover Output
The discover command now shows the computed security level for each endpoint and marks the auto-selected endpoint with *:
Server: My OPC UA Server
URI: urn:myserver:opcua
┌─────────────────────────────┬──────────────────────┬──────────────────┬──────────────────┬───────┬───┐
│ Endpoint URL │ Security Policy │ Security Mode │ User Tokens │ Level │ │
├─────────────────────────────┼──────────────────────┼──────────────────┼──────────────────┼───────┼───┤
│ opc.tcp://localhost:4840 │ Aes256_Sha256_RsaPss │ SignAndEncrypt │ Anonymous, User │ 110 │ * │
│ opc.tcp://localhost:4840 │ Basic256Sha256 │ SignAndEncrypt │ Anonymous, User │ 106 │ │
│ opc.tcp://localhost:4840 │ Basic256Sha256 │ Sign │ Anonymous │ 6 │ │
│ opc.tcp://localhost:4840 │ None │ None │ Anonymous │ 0 │ │
└─────────────────────────────┴──────────────────────┴──────────────────┴──────────────────┴───────┴───┘Endpoints are sorted by security level in descending order. The * marker shows which endpoint the client would auto-select.
When to Use Explicit Security
Auto-selection is the right choice for most scenarios, but there are cases where you should specify the security policy and mode explicitly:
- Compliance requirements — your organization mandates a specific policy (e.g., only
Aes256_Sha256_RsaPssor ECC policies) - Pinning — you want to ensure the client always uses the exact same policy, even if the server adds new endpoints
- Debugging — you need to test a specific security configuration
- None-only servers — if you know the server only supports
Noneand want to skip the discovery round-trip, useWithSecurity(SecurityPolicyUris.None, MessageSecurityMode.None)directly
For explicit configuration, see the Security page.