title: OWIN/OAuth2 3rd party login: Authentication from Client App, Authorization from Web API
body: <p>I am trying to create a Web API that allows the API's clients (native mobile apps) to login using a 3rd party cloud storage provider. I'm using the following general flow from Microsoft:</p>
  
  <p><img src="https://i.stack.imgur.com/PBlvj.png" alt=""></p>
  
  <p>Here is what I am trying to achieve:</p>
  
  <p><img src="https://i.stack.imgur.com/GcwXJ.jpg" alt=""></p>
  
  <p>I am using the default ASP.NET Web API Visual Studio template with external authentication, along with the <a href="https://github.com/owin-middleware/OwinOAuthProviders/tree/master/Owin.Security.Providers" rel="nofollow noreferrer">OWin.Security.Providers</a> Nuget package for Dropbox login functionality, and the existing built-in login functionality for Google (Drive) and Microsoft (OneDrive).</p>
  
  <p>The issue I'm having is that the built-in functionality all seems to do the authentication and authorization as part of one flow. For example, if I set up the following in Startup.Auth.cs:</p>
  
  <pre><code>DropboxAuthenticationOptions dropboxAuthOptions = new DropboxAuthenticationOptions
                                                      {
                                                          AppKey = _dropboxAppKey,
                                                          AppSecret = _dropboxAppSecret
                                                      };
  app.UseDropboxAuthentication(dropboxAuthOptions);
  </code></pre>
  
  <p>... and navigate to this url from my web browser:</p>
  
  <pre><code>http://&lt;api_base_url&gt;/api/Account/ExternalLogin?provider=Dropbox&amp;response_type=token&amp;client_id=self&amp;redirect_uri=&lt;api_base_url&gt;
  </code></pre>
  
  <p>I am successfully redirected to Dropbox to login:</p>
  
  <pre><code>https://www.dropbox.com/1/oauth2/authorize?response_type=code&amp;client_id=&lt;id&gt;&amp;redirect_uri=&lt;redirect_uri&gt;
  </code></pre>
  
  <p>... and then after I grant access, am redirected back to:</p>
  
  <pre><code>http://&lt;api_base_url&gt;/Help#access_token=&lt;access_token&gt;&amp;token_type=bearer&amp;expires_in=1209600
  </code></pre>
  
  <p>... as you can see the token is part of that, so could be extracted. The problem is that the client needs to be the one navigating to Dropbox and returning the authorization code back up to the Web API, and the Web API would send the authorization code back to the third party to get the token which would then be returned to the client... as shown in the diagram above. I need the ExternalLogin action in the AccountController to somehow retrieve the Dropbox url and return that to the client (it would just be a json response), but I don't see a way to retrieve that (it just returns a ChallengeResult, and the actual Dropbox url is buried somewhere). Also, I think I need a way to separately request the token from the third party based on the authorization code.</p>
  
  <p>This post seems a little similar to what I am trying to do:</p>
  
  <p><a href="https://stackoverflow.com/questions/21167648/registering-web-api-2-external-logins-from-multiple-api-clients-with-owin-identi">Registering Web API 2 external logins from multiple API clients with OWIN Identity</a></p>
  
  <p>... but the solution there seems to require the client to be an MVC application, which is not necessarily the case for me. I want to keep this as simple as possible on the client side, follow the flow from my diagram above, but also not reinvent the wheel (reuse as much as possible of what already exists in the OWIN/OAuth2 implementation). Ideally I don't want the client to have to reference any of the OWIN/OAuth libraries since all I really need the client to do is access an external url provided by the API (Dropbox in my example), have the user input their credentials and give permission, and send the resulting authorization code back up to the api.</p>
  
  <p>Conceptually this doesn't sound that hard but I have no idea how to implement it and still use as much of the existing OAuth code as possible. Please help!</p>