DotNetOpenAuth OAuth2 Access to additional data
I am using the DotNetOpenAuth OAuth2 library to handle authorization with another third party system. This all works fine, except that the third party system returns UserId = "testname" in the Response with the AccessToken.
I need this UserId because this third party API requires it as part of their API calls (eg: users / {userId} / account).
Using DotNetOpenAuth I don't have access to the AccessToken response, so I can't get the UserId.
I'm calling: (_client is a WebServerClient) var state = _client.ProcessUserAuthorization (request);
the state has my AccessToken, but no additional data sent down. Based on DotNetOpenAuth source code, UserId is in the library and I don't have access.
Is there a way to get this UserId using DotNetOpenAuth? Or do I have to give up DotNetOpenAuth and try something else?
source to share
You can access the request and response data by executing IDirectWebRequestHandler
and assigning it Channel
. But with the current DNOA implementation, the only way to make it work is to apply a proxy pattern to the existing class UntrustedWebRequestHandler
, because this particular handler is passed CachedDirectWebResponse
that has a stream of responses that can be read multiple times - once by your code to get additional data, and then reverse the code to ProcessUserAuthorization()
.
This is the code for custom IDirectWebRequestHandler
:
public class RequestHandlerWithLastResponse : IDirectWebRequestHandler
{
private readonly UntrustedWebRequestHandler _webRequestHandler;
public string LastResponseContent { get; private set; }
public RequestHandlerWithLastResponse(UntrustedWebRequestHandler webRequestHandler)
{
if (webRequestHandler == null) throw new ArgumentNullException( "webRequestHandler" );
_webRequestHandler = webRequestHandler;
}
public bool CanSupport( DirectWebRequestOptions options )
{
return _webRequestHandler.CanSupport( options );
}
public Stream GetRequestStream( HttpWebRequest request )
{
return _webRequestHandler.GetRequestStream( request, DirectWebRequestOptions.None );
}
public Stream GetRequestStream( HttpWebRequest request, DirectWebRequestOptions options )
{
return _webRequestHandler.GetRequestStream( request, options );
}
public IncomingWebResponse GetResponse( HttpWebRequest request )
{
var response = _webRequestHandler.GetResponse( request, DirectWebRequestOptions.None );
//here we actually getting the response content
this.LastResponseContent = GetResponseContent( response );
return response;
}
public IncomingWebResponse GetResponse( HttpWebRequest request, DirectWebRequestOptions options )
{
return _webRequestHandler.GetResponse( request, options );
}
private string GetResponseContent(IncomingWebResponse response)
{
MemoryStream stream = new MemoryStream();
response.ResponseStream.CopyTo(stream);
stream.Position = 0;
response.ResponseStream.Position = 0;
using (var sr = new StreamReader(stream))
{
return sr.ReadToEnd();
}
}
}
And this is how we apply it and get the response data:
var h = new RequestHandlerWithLastResponse(new UntrustedWebRequestHandler()); ;
_client.Channel.WebRequestHandler = h;
var auth = _client.ProcessUserAuthorization( request );
//convert response json to POCO
var extraData = JsonConvert.DeserializeObject<MyExtraData>( h.LastResponseContent );
source to share
Just read the id directly from the query string after the string ProcessUserAuthorization
, depending on how it is passed (body, query string). I see no reason to stop using DNOA.
var auth = client.ProcessUserAuthorization();
if ( auth != null )
{
// this is where you could still access the identity provider request
...
Note that passing additional parameters along with an access token is rather unusual and can lead to potential security issues. This is because the response from the identity provider is first sent to the user's browser and then sent to your server. The user can change the response of the identity provider by retaining the access token but replacing the user ID with any other valid user ID.
source to share