Additional build steps required:
HTTP Basic Authentication is the default authentication supported by gSOAP. The credentials for client-side use age set with:
soap.userid = "<userid>"; soap.passed = "<passwd>"; if (soap_call_ns__method(&soap, ...)) ... // error
HTTP Basic Authentication should never be used over plain HTTP, because the user ID and password are sent in the clear. It is safe(r) to use over HTTPS, because the HTTP headers and body are encrypted.
The better alternative is to use HTTP Digest Authentication, which uses the digest (hash value) of the credentials and avoids a plain-text password exchange.
To use HTTP Digest Authentication with gSOAP, register the http_da plugin:
To make a client-side service call:
struct http_da_info info; if (soap_call_ns__method(&soap, ...)) { if (soap.error == 401) { http_da_save(&soap, &info, "<authrealm>", "<userid>", "<passwd>"); if (soap_call_ns__method(&soap, ...)) // try again ... // error http_da_release(&soap, &info); } else ... // other error }
The "<authrealm>" is a string that is associated with the server's realm. It can be obtained after an unsuccessful non-authenticated call:
if (soap_call_ns__method(&soap, ...)) { if (soap.error == 401) // HTTP authentication is required { const char *realm = soap.authrealm; ... } else ... // error }
Before a second call is made to the same endpoint that requires authentication, you must restore the authentication state and then finally release it:
struct http_da_info info; bool auth = false; if (soap_call_ns__method(&soap, ...)) { if (soap.error == 401) { http_da_save(&soap, &info, "<authrealm>", "<userid>", "<passwd>"); auth = true; } else ... // other error } if (soap_call_ns__method(&soap, ...)) ... // error if (auth) http_da_restore(&soap, &info); if (soap_call_ns__method(&soap, ...)) ... // error soap_destroy(&soap); // okay to dealloc data soap_end(&soap); // okay to dealloc data if (auth) http_da_restore(&soap, &info); if (soap_call_ns__method(&soap, ...)) ... // error if (auth) http_da_release(&soap, &info); soap_destroy(&soap); soap_end(&soap); soap_done(&soap);
For HTTP proxies requiring HTTP Digest Authenticaiton, use the 'proxy' functions:
struct http_da_info info; ... if (soap_call_ns__method(&soap, ...)) { if (soap.error == 407) { http_da_proxy_save(&soap, &info, "<authrealm>", "<userid>", "<passwd>"); auth = true; } else ... // error } if (auth) http_da_proxy_restore(&soap, &info); if (soap_call_ns__method(&soap, ...)) ... // error http_da_proxy_release(&soap, &info); soap_destroy(&soap); soap_end(&soap); soap_done(&soap);
A client authenticating against a server:
soap_register_plugin(&soap, http_da); // try calling without authenticating if (soap_call_ns__method(&soap, ...)) { if (soap.error == 401) // HTTP authentication is required { if (!strcmp(soap.authrealm, authrealm)) // check authentication realm { struct http_da_info info; // to store userid and passwd http_da_save(&soap, &info, authrealm, userid, passwd); // call again, now with credentials if (soap_call_ns__method(&soap, ...) == SOAP_OK) { ... // process response data soap_end(&soap); ... // userid and passwd were deallocated (!) http_da_restore(&soap, &info); // get userid and passwd after soap_end() if (!soap_call_ns__method(&soap, ...) == SOAP_OK) ... // error http_da_release(&soap, &info); // free data and remove userid and passwd
A client authenticating against a proxy:
soap_register_plugin(&soap, http_da); // try calling without authenticating if (soap_call_ns__method(&soap, ...)) { if (soap.error == 407) // HTTP authentication is required { if (!strcmp(soap.authrealm, authrealm)) // check authentication realm { struct http_da_info info; // to store userid and passwd http_da_proxy_save(&soap, &info, authrealm, userid, passwd); // call again, now with credentials if (soap_call_ns__method(&soap, ...) == SOAP_OK) { ... // process response data soap_end(&soap); ... // userid and passwd were deallocated (!) http_da_proxy_restore(&soap, &info); // get userid and passwd after soap_end() if (!soap_call_ns__method(&soap, ...) == SOAP_OK) ... // error http_da_proxy_release(&soap, &info); // free data and remove userid and passwd
Server-side HTTP Basic Authentication can be enforced by simply checking the soap.userid and soap.passwd values in a service method that requires client authentication:
soap_register_plugin(&soap, http_da); ... soap_serve(&soap); ... int ns__method(struct soap *soap, ...) { if (!soap->userid || !soap->passwd || strcmp(soap->userid, "<userid>") || strcmp(soap->passwd, "<passwd>")) return 401; // HTTP authentication required ... }
HTTP Digest Authentication is verified differently:
soap_register_plugin(&soap, http_da); ... soap_serve(&soap); ... int ns__method(struct soap *soap, ...) { if (soap->authrealm && soap->userid) { passwd = ... // database lookup on userid and authrealm to find passwd if (!strcmp(soap->authrealm, authrealm) && !strcmp(soap->userid, userid)) { if (!http_da_verify_post(soap, passwd)) // HTTP POST DA verification { ... // process request and produce response return SOAP_OK; } } } soap->authrealm = authrealm; // realm to send to client return 401; // Not authorized, challenge with digest authentication
The http_da_verify_post() function checks the HTTP POST credentials. To verify an HTTP GET operation, use http_da_verify_get().
soap_register_plugin(&soap, http_da); ... soap_serve(&soap); ... int ns__method(struct soap *soap, ...) { if (soap->userid && soap->passwd) // Basic authentication { if (!strcmp(soap->userid, userid) && !strcmp(soap->passwd, passwd)) { ... // can also check soap->authrealm ... // process request and produce response return SOAP_OK; } } else if (soap->authrealm && soap->userid) // Digest authentication { passwd = ... // database lookup on userid and authrealm to find passwd if (!strcmp(soap->authrealm, authrealm) && !strcmp(soap->userid, userid)) { if (!http_da_verify_post(soap, passwd)) // HTTP POST DA verification { ... // process request and produce response return SOAP_OK; } } } soap->authrealm = authrealm; // realm to send to client return 401; // Not authorized, challenge with digest authentication }
HTTP Digest Authentication cannot be used with streaming MTOM/MIME/DIME attachments. Streaming is turned off by the plugin and attachment data is buffered rather than streamed. Non-streaming MTOM/MIME/DIME attachments are handled just fine.