private UserIdentityToken ValidateUserIdentityToken(
ExtensionObject identityToken,
SignatureData userTokenSignature,
out UserTokenPolicy policy )
{
policy = null;
// check for empty token.
if (identityToken == null || identityToken.Body == null)
{
// not changing the token if already activated.
if (m_activated)
{
return null;
}
// check if an anonymous login is permitted.
if (m_endpoint.UserIdentityTokens != null && m_endpoint.UserIdentityTokens.Count > 0)
{
bool found = false;
for (int ii = 0; ii < m_endpoint.UserIdentityTokens.Count; ii++)
{
if (m_endpoint.UserIdentityTokens[ii].TokenType == UserTokenType.Anonymous)
{
found = true;
policy = m_endpoint.UserIdentityTokens[ii];
break;
}
}
if (!found)
{
throw ServiceResultException.Create(StatusCodes.BadUserAccessDenied, "Anonymous user token policy not supported.");
}
}
// create an anonymous token to use for subsequent validation.
AnonymousIdentityToken anonymousToken = new AnonymousIdentityToken();
anonymousToken.PolicyId = policy.PolicyId;
return anonymousToken;
}
UserIdentityToken token = null;
// check for unrecognized token.
if (!typeof( UserIdentityToken ).IsInstanceOfType( identityToken.Body ))
{
//handle the use case when the UserIdentityToken is binary encoded over xml message encoding
if (identityToken.Encoding == ExtensionObjectEncoding.Binary && typeof( byte[] ).IsInstanceOfType( identityToken.Body ))
{
UserIdentityToken newToken = BaseVariableState.DecodeExtensionObject( null, typeof( UserIdentityToken ), identityToken, false ) as UserIdentityToken;
if (newToken == null)
{
throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
}
policy = m_endpoint.FindUserTokenPolicy( newToken.PolicyId );
if (policy == null)
{
throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "User token policy not supported.", "Opc.Ua.Server.Session.ValidateUserIdentityToken" );
}
switch (policy.TokenType)
{
case UserTokenType.Anonymous:
token = BaseVariableState.DecodeExtensionObject( null, typeof( AnonymousIdentityToken ), identityToken, true ) as AnonymousIdentityToken;
break;
case UserTokenType.UserName:
token = BaseVariableState.DecodeExtensionObject( null, typeof( UserNameIdentityToken ), identityToken, true ) as UserNameIdentityToken;
break;
case UserTokenType.Certificate:
token = BaseVariableState.DecodeExtensionObject( null, typeof( X509IdentityToken ), identityToken, true ) as X509IdentityToken;
break;
case UserTokenType.IssuedToken:
token = BaseVariableState.DecodeExtensionObject( null, typeof( IssuedIdentityToken ), identityToken, true ) as IssuedIdentityToken;
break;
default:
throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
}
}
else
{
throw ServiceResultException.Create( StatusCodes.BadUserAccessDenied, "Invalid user identity token provided." );
}
}
else
{
// get the token.
token = (UserIdentityToken) identityToken.Body;
}
// find the user token policy.
policy = m_endpoint.FindUserTokenPolicy( token.PolicyId );
if (policy == null)
{
throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, "User token policy not supported.");
}
// determine the security policy uri.
string securityPolicyUri = policy.SecurityPolicyUri;
if (String.IsNullOrEmpty( securityPolicyUri ))
{
securityPolicyUri = m_endpoint.SecurityPolicyUri;
}
if (ServerBase.RequireEncryption(m_endpoint))
{
// decrypt the token.
if (m_serverCertificate == null)
{
m_serverCertificate = CertificateFactory.Create(m_endpoint.ServerCertificate, true);
// check for valid certificate.
if (m_serverCertificate == null)
{
throw ServiceResultException.Create(StatusCodes.BadConfigurationError, "ApplicationCertificate cannot be found.");
}
}
try
{
token.Decrypt(m_serverCertificate, m_serverNonce, securityPolicyUri);
}
catch (Exception e)
{
if (e is ServiceResultException)
{
throw;
}
throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid, e, "Could not decrypt identity token.");
}
// verify the signature.
if (securityPolicyUri != SecurityPolicies.None)
{
byte[] dataToSign = Utils.Append(m_serverCertificate.RawData, m_serverNonce);
if (!token.Verify(dataToSign, userTokenSignature, securityPolicyUri))
{
throw new ServiceResultException(StatusCodes.BadUserSignatureInvalid, "Invalid user signature!");
}
}
}
// validate user identity token.
return token;
}