oauth-2.0http-headersiwebbrowser2

HTTP response header from IWebBrowser2


Very similar to this question, I am trying to get a specific value in the response header. It references a pass-through solution using Asynchronous Pluggable Protocol (APP) handlers, however the links are dead since the solution is quite dated.

Perhaps I am approaching this incorrectly.

Overview: I am extending an OAuth2 library that I have written in C++ (desktop app), which works well for the Google APIs, to now allow negotiation with Microsoft. As referenced on this site (under 'Redirect request after successful sign in'), the auth code is returned in the Location field of the response header. Using an HTTP debugger, I can see the value that was sent (see below).

When attempting to get IHTMLLocation interface from IHTMLDocument2, none of the properties contain the value that I can see using the HTTP debugger, and these calls succeed with various values even when the 'Location' field does not exist in the response headers (this is clearly not what is needed).

This is the only hang-up. All subsequent calls and requests, I use the WinHTTP APIs, and response headers are easily accessed. However this stage is still where the user can properly authenticate and authorize the app in a browser. I appreciate your time and help.

Update: The response looks similar to the following:

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Location: urn:ietf:wg:oauth:2.0:oob?code=[VALUE]

Solution

  • In this case, getting the response header is not necessary. The auth code is also passed as a query parameter to the redirect url.

    Implement DWebBrowserEvents2, and get the url in the Invoke function:

    HRESULT __stdcall DWebBrowserEvents2::Invoke(_In_ DISPID dispIdMember,
                                                 _In_ REFIID riid,
                                                 _In_ LCID lcid,
                                                 _In_ WORD flags,
                                                 _In_ DISPPARAMS *pDispParams,
                                                 _Out_opt_ VARIANT *pVarResult,
                                                 _Out_opt_ EXCEPINFO *pExcepInfo,
                                                 _Out_opt_ UINT *puArgErr);
    

    Detect when

    // new document goes ReadyState_Complete
    dispIdMember == DISPID_DOCUMENTCOMPLETE  [ 259 ]
    

    The url is a variant located here:

    VARIANT *vurl = pDispParams->rgvarg[0].pvarVal; // <-- not bstrVal
    

    Convert to BSTR, then string:

    BSTR url = (vurl->vt & VT_BYREF) ? *vurl->pbstrVal : vurl->bstrVal;
    std::wstring ws(url, SysStringLen(url));
    
    // url will look similar to the following:
    // http://localhost/?code=[...]&session_state=[...]