Alexey
Alexey

Reputation: 31

How can I pass a Soap Header to a SOAP WCF Service in Visual Studio?

I'm trying to consume a third-party web service (discription on russian language) https://92.46.122.150:8443/esf-web/ws/SessionService?wsdl

I am trying to connect to a website using method "createSession", get Id session and close session in a website. Do this I using Visual Studio 2013, C#, .NET 4.5, WSE 3.0 (Microsoft.Web.Services3.dll).

I have already created project in Visual Studio 2013 "Windows Forms Application". In this form user can enter user name, login and to choose his a digital signature certificate. Also I added web service as a "web service reference" but I'm not sure how to pass the credentials for the header.

I'm trying to do this:

string strPasswordCertificate = "123456";
string strCertificate = "C:/Test/AUTH_RSA_db79bb07b4722c042e025979b3b11995fc46765b.p12";
X509Certificate x509_CertAUTH = new X509Certificate(strCertificateFilePathAUTH, strPasswordCertificate);
string strCertAUTH = x509_CertAUTH.ToString();

CreateSessionRequest CreateReq = new CreateSessionRequest();

CreateReq.x509Certificate = strCertAUTH;
string strIIN = "753159846249";

CreateReq.tin = strIIN;
WS.createSession(CreateReq);

But when run a programm Visual studio show an error on a line with "WS.createSession(CreateReq)" like below:

SoapHeaderException was unhandled. An unhandled exception of type "System.Web.Service.Protocols.SoapHeaderExeption" occurred in System.Web.Services.dll Additional information: An error was discovered processing the "wsse:Security" header.

This exception is thrown when an XML Web service method is called over SOAP and an exception occurs during processing of the SOAP header. After that I made changes in my code like below:

string strPasswordCertificate = "123456";
string strCertificate = "C:/Test/AUTH_RSA_db79bb07b4722c042e025979b3b11995fc46765b.p12";
X509Certificate x509_CertAUTH = new X509Certificate(strCertificateFilePathAUTH, strPasswordCertificate);
string strCertAUTH = x509_CertAUTH.ToString();

CreateSessionRequest CreateReq = new CreateSessionRequest();

CreateReq.x509Certificate = strCertAUTH;
string strIIN = "753159846249";

CreateReq.tin = strIIN;
WS.createSession(CreateReq);

string _userName = "123456789011";
string _UserPassword = "TestPass123";

UsernameToken userToken;

userToken = new UsernameToken(_userName, _UserPassword, PasswordOption.SendPlainText);

SessionService WS = new SessionService();
SoapContext requestContext = WS.RequestSoapContext;
requestContext.Security.Tokens.Add(userToken);

WS.createSession(CreateReq);

But when run a programm Visual studio show error on a line with "WS.createSession(CreateReq)" like below:

SoapHeaderException was unhandled. An unhandled exception of type 'System.Web.Service.Protocols.SoapHeaderExeption' occurred in System.Web.Services.dll Additional information: An invalid security token was provided.

What I need more to do or change in my code that web reverence start to work? Any idea?

Upvotes: 0

Views: 1186

Answers (1)

Alexey
Alexey

Reputation: 31

First, need add web service "https://92.46.122.150:8443/esf-web/ws/SessionService?wsdl" like Service Reference.

Second, your certificate should be like trusted. If not, then you can do this using code below:

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Third, add in your solution new item like C# class for your SOAP header. In this class shoud be code like below:

namespace WindowsFormsApplication1
{
    public class MySoapSecurityHeader : MessageHeader
    {
        private readonly UsernameToken _usernameToken;

        public MySoapSecurityHeader(string username, string password)
        {
            _usernameToken = new UsernameToken(string.Empty, username, password);
        }

        public MySoapSecurityHeader(string id, string username, string password)
        {
            _usernameToken = new UsernameToken(id, username, password);
        }

        public override string Name
        {
            get { return "Security"; }
        }

        public override string Namespace
        {
            get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
        }

        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(UsernameToken));
            serializer.Serialize(writer, _usernameToken);
        }
    }


    [XmlRoot(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
    public class UsernameToken
    {
        public UsernameToken()
        {
        }

        public UsernameToken(string id, string username, string password)
        {
            Id = id;
            Username = username;
            Password = new Password() { Value = password };
        }

        [XmlAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")]
        public string Id { get; set; }

        [XmlElement]
        public string Username { get; set; }

        [XmlElement]
        public Password Password { get; set; }
    }

    public class Password
    {
        public Password()
        {
            Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
        }

        [XmlAttribute]
        public string Type { get; set; }

        [XmlText]
        public string Value { get; set; }
    }
}

After that you need add code in a file "Form1.cs":

//The path to the certificate.
string certPath = "C:/AUTH_RSA256_e9f5afab50193175883774ec07bac05cb8c9e2d7.p12";

//Password to signing a certificate
string certPassword = "123456";

//IIN or BIN persom who signing ESF on esf_gov site
var tin = "123456789021";

//Load the certificate into an X509Certificate object.
X509Certificate x509Cert = new X509Certificate(certPath, certPassword);

//Transfer sertificate to string value of base64
var certPEM = ExportToPEM(x509Cert);


using (SessionServiceClient client = new SessionServiceClient())
            {
                using (new OperationContextScope(client.InnerChannel))
                {
                    OperationContext.Current.OutgoingMessageHeaders.Add(
                        new MySoapSecurityHeader("123456789011", "TestPass123"));

                    //Create session for a work with site ESF
                    CreateSessionRequest createSessionRequest = new CreateSessionRequest
                    {
                        tin = tin,
                        x509Certificate = certPEM
                    };

                    var response = client.createSession(createSessionRequest);
                    MessageBox.Show("Session ID is: " + response.sessionId, "Information message",
                                    MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);

                    //Close session for a work with site ESF
                    CloseSessionRequest closeSessionRequest = new CloseSessionRequest
                    {
                        sessionId = response.sessionId,
                        tin = tin,
                        x509Certificate = certPEM
                    };

                    var closeResponse = client.closeSession(closeSessionRequest);
                }
            }

        }
        public static string ExportToPEM(X509Certificate cert)
        {
            //Export certificate, get baty array, convert in base64 string
            return Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks);
        }

Then run a programm and this will be work.

Upvotes: 2

Related Questions