Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URI's user info not used? #3

Closed
eburkitt opened this issue Oct 9, 2015 · 5 comments
Closed

URI's user info not used? #3

eburkitt opened this issue Oct 9, 2015 · 5 comments

Comments

@eburkitt
Copy link
Contributor

eburkitt commented Oct 9, 2015

I am attempting to communicate with a Web service that expects a user name and password in the URL (e.g., HTTP://username:password@domain.top). I'm supplying user info in the base URL, but it's not being sent that I can see. Further, I see no code in the Casablanca project that would send it. No code other than uri_builder and uri class manipulation calls uri_builder::user_info().

Does Casablanca, in fact, make no use of these data? If so, what can I do to work around this omission?

-evan

@ras0219-msft
Copy link
Contributor

It should be passed into the URI as part of the join() function.

https://github.com/Microsoft/cpprestsdk/blob/e83d8b92e9f4d2ffa7fbb00e4ba05d41a3a9400d/Release/src/uri/uri.cpp#L70

If you're connecting to the server over HTTP, can you capture the stream using fiddler or wireshark? That should give you more info on what exactly is getting sent over the wire.

@eburkitt
Copy link
Contributor Author

ras0219-msft:

Yes, I see that now, and the result of the call to Join() is apparently what's passed to WinHttpOpenRequest() at line ~500 in http_client_winhttp.cpp. However, after much experimentation and largely unproductive Web searching I've not managed to make Casablanca actually send the credentials. Experimenting with wget I've determined that it always sends its first request without credentials (which is the behavior I get from Casablanca). The server's 401 response to that request contains a header, Www-Authenticate: Basic realm="Application", the the presence of which causes wget retry the request, this time including the user name and password in the request, like this:

POST /sms HTTP/1.1
User-Agent: Wget/1.16.1 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: domain.top
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 77
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

It appears that the Www-Authenticate header returned by the server tells the client (wget) what kind of authentication it will accept. I see nothing in Casablanca's API that looks like a "use Basic authentication" flag so I don't see how to make use of the server's request. That Casablanca (really MS's WinHttp) ignores the credentials I give it the first place was such unlikely behavior that it took me a long time to accept that's what's happening.

I'm stumped at the moment.

-evan

@ras0219-msft
Copy link
Contributor

Since you know the website is expecting basic auth, you can manually add the authorization header:

std::vector<unsigned char> vec_basic_auth_buf;
// fill vec_basic_auth_buf with the text: "username:password"
request.headers().add(header_names::authorization, U("Basic ")
    + utility::conversions::to_base64(vec_basic_auth_buf);

@eburkitt
Copy link
Contributor Author

I took a more thorough look at Casablanca's sending of requests and found that it does have code to retry connections that fail due to authentication challenges. At least it does in Windows (http/client/http_client_winhttp.cpp). Knowing this I started setting up an environment where I could watch it work and see where it failed. Before I did so, I tried again, just be sure I still had a problem. Of course, it worked that time.

While I "know" that I was seeing only one attempt by Casablanca and two by wget, I didn't save those Wireshark captures, so I have no proof. Between the failures and eventual success, the vendor whose site I was accessing fixed my account so I could actually authenticate, which may have some bearing, but wget tried twice and failed twice before the credentials were valid; now it tries twice and succeeds on the second try, so if the credential fix made the difference, is not obvious how.

ras0219-msft, thanks for your help. I will try your hand-made headers idea, as the eventual production implementation will be making thousands of connections a day, and providing credentials on the first connection will save half of them.

-evan

@garethsb
Copy link
Contributor

I confirm @eburkitt's original finding that uri::user_info is not used by either http_client_asio or http_client_winhttp, Basic Auth is actually only possible via the client config credentials object or manual creation of an Authorization header. Very confusing.

GerHobbelt pushed a commit to GerHobbelt/cpprestsdk that referenced this issue Mar 20, 2024
* Add headers to lua for better VS experience

* Hold linked callbacks separately, deregister them on destruction

* Replace _JoinAllTokens_Add with cancellation_token_source::create_linked_source, pare down helper structs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants