Client Authentication
Working with client sessions
After opening secure channel, the client needs to create a session. The client will receive a set of endpoints and a list of supported user identity token polices in response.
local session, err = client:createSession("test_session", 3600000)
if err ~= nil then
error("Creating session failed: "..err)
end
local tokenPolicy
for _, endpoint in ipairs(session.ServerEndpoints) do
for _, policy in ipairs(endpoint.UserIdentityTokens) do
if policy.TokenType == ua.Types.UserTokenType.UserName and
(policy.SecurityPolicyUri == nil or policy.SecurityPolicyUri == ua.Types.SecurityPolicy.None)
then
tokenPolicy = policy
goto found
end
end
end
::found::
if not tokenPolicy then
error("cannot find endpoint with username token.")
end
local userName = "admin"
local password = "12345"
local resp, err = client:activateSession(tokenPolicy.PolicyId, userName, password)
if err ~= nil then
error("Activating session failed: "..err)
end
Each token policy contains several fields. The following fields are common to all policy types:
- PolicyId
a string identifier assigned to the policy by the server. This identifier is used by the server to understand the parameters of the user token sent by the client.
- TokenType
The token type: Anonymous, UserName, Certificate, Issued Token.
- SecurityPolicyUri
The URI of the security policy used to secure the token.
Additional fields are specific to each token type and will be covered in the following sections.
Anonymous
An anonymous token basically means the absence of authentication, which means anyone can connect to and work with the server. This type of authentication is usually enabled for testing purposes only.
You can pass the identifier of the anonymous policy, which is taken from the response of CreateSession. No additional parameters are required for the anonymous token.
-- Create session with name "test_session" and with life time
-- 1 hour (3600000 ms)
local session, err = client:createSession("test_session", 3600000)
local tokenPolicy
for _, endpoint in ipairs(session.ServerEndpoints) do
for _, policy in ipairs(endpoint.UserIdentityTokens) do
if policy.TokenType == ua.Types.UserTokenType.Anonymous
then
tokenPolicy = policy
goto found
end
end
end
::found::
if not tokenPolicy then
error("cannot find endpoint with anonymous token.")
end
-- Passing id of anonymous token policy.
local resp, err = client:activateSession(tokenPolicy.PolicyId)
User Name
Depending on the server configuration, a password can be sent encrypted or unencrypted, which depends on the token policy configuration on the server.
The Username token policy has the following parameters:
PolicyId
Id of a policy on assigned by server
TokenType
Token type has value ua.Types.UserTokenPolicy.UserName
SecurityPolicyUri
URI of the security policy that defines what encryption should be applied for the password. If this field is absent or points to the security policy None, then no encryption is applied to the password. If the secure channel doesn’t apply encryption for all packets, then the password will be sent as is.
The following example demonstrates how to authenticate with a server using a username and password:
local session, err = client:createSession("test_session", 3600000)
if err ~= nil then
error("Creating session failed: "..err)
end
local tokenPolicy
for _, endpoint in ipairs(session.ServerEndpoints) do
for _, policy in ipairs(endpoint.UserIdentityTokens) do
if policy.TokenType == ua.Types.UserTokenType.UserName and
(policy.SecurityPolicyUri == nil or policy.SecurityPolicyUri == ua.Types.SecurityPolicy.None)
then
tokenPolicy = policy
goto found
end
end
end
::found::
if not tokenPolicy then
error("cannot find endpoint with username token.")
end
local userName = "admin"
local password = "12345"
local resp, err = client:activateSession(tokenPolicy.PolicyId, userName, password)
if err ~= nil then
error("Activating session failed: "..err)
end
x509 certificate
To authenticate with a certificate, you need to find the ID of the policy with the type ua.Types.UserTokenPolicy.Certificate.
This policy has the following parameters:
PolicyId
Id of a policy on assigned by server
TokenType
Token type has value ua.Types.UserTokenPolicy.Certificate
SecurityPolicyUri
URI of the security policy that defines if client will also send a signature. The signature is calculated with using corresponding private key of a user and proves owning of certificate by current client. If this field is absent or points to the security policy ‘None’, then the certificate is sent alone without a signature.
When activating a session with certificate-based authentication, the ActivateSession call should include the following parameters:
- TolicyId
ID of token policy Certificate
TokenType
Token type has value ua.Types.UserTokenPolicy.Certificate
Certificate
Certificate of the user. Is sent to cerver.
PrivateKey
Private key of corresponding user’s certificate. Used to calculate signature.
Activate session accepts certificate and provate key in pem, der format or can be passed path to files.
The following example show how to authenticate using a certificate:
error("Opening secure channel failed: "..err)
end
local session, err = client:createSession("test_session", 3600000)
local tokenPolicy
for _, endpoint in ipairs(session.ServerEndpoints) do
-- Select certificate token policy with security policy Basic128Rsa15
for _, policy in ipairs(endpoint.UserIdentityTokens) do
if policy.TokenType == ua.Types.UserTokenType.Certificate then
tokenPolicy = policy
goto found
end
end
end
::found::
if not tokenPolicy then
error("cannot find endpoint with certificate token policy.")
end
local certificate = mako.cfgdir.."/../certs/client.pem"
local privateKey = mako.cfgdir.."/../certs/client.key"
local resp, err = client:activateSession(
tokenPolicy.PolicyId, certificate, privateKey)
JWT, OAuth2, Azure
OPC UA allows authentication using third-party tokens, which are also known as Issued Tokens.
To authenticate with such tokens, you need to search for the policy that uses the token type ua.Types.UserTokenPolicy.IssuedToken. This type of token is commonly used for all third-party tokens. To distinguish between token formats, the policy includes an additional parameter called IssuedTokenType.
The IssuedToken policy has the following parameters:
- PolicyId
ID of token policy Certificate
- TokenType
Token type has value ua.Types.UserTokenPolicy.Certificate
- TssuedTokenType
This is a string that specifies the type of issued token and can have one of the following values:
- ua.Types.IssuedTokenType.JWT - ua.Types.IssuedTokenType.OAuth2 - ua.Types.IssuedTokenType.Azure
- IssuerEndpointUrl
Url of the server that issued the token
- SecurityPolicyUri
URI of the security policy that defines what encryption should be applied for token. If this field is absent of points to security policy None tnen no encryption for password is applied. if secure channel doesn’t apply encryption for all packets then password will be sent as is.
The following example shows how to authenticate with issued token:
error("Opening secure channel failed: "..err)
end
local session, err = client:createSession("test_session", 3600000)
local tokenPolicy
for _, endpoint in ipairs(session.ServerEndpoints) do
for _, policy in ipairs(endpoint.UserIdentityTokens) do
-- Select JWT token policy. There also Azure, OAuth2 and OPCUA.
if policy.TokenType == ua.Types.UserTokenType.IssuedToken and
policy.IssuedTokenType == ua.Types.IssuedTokenType.JWT
then
tokenPolicy = policy
goto found
end
end
end
::found::
if not tokenPolicy then
error("cannot find endpoint with certificate token policy.")
end
local jwtHeader = { alg="HS256", typ = "JWT"}
local jwtPayload = {
sub = "1234567890",
name = "John Doe",
iat = 1516239022
}
local token = require"jwt".scomp("my-secret", jwtPayload, jwtHeader)
local resp, err = client:activateSession(tokenPolicy.PolicyId, token)