From 62a271ec662957ea6807880fa5abeeb3d2f6184f Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Wed, 25 Sep 2019 18:27:15 +0000 Subject: [PATCH] --- Controllers/AuthController.cs | 94 +++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 15 deletions(-) diff --git a/Controllers/AuthController.cs b/Controllers/AuthController.cs index f41a8c0..227dfc8 100644 --- a/Controllers/AuthController.cs +++ b/Controllers/AuthController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using System.Net.Http; using Newtonsoft.Json.Linq; +using Newtonsoft.Json; namespace qbridge.Controllers { @@ -13,6 +14,10 @@ namespace qbridge.Controllers [Produces("application/json")] public class OAuthRedirectController : ControllerBase { + public const string CLIENT_ID = "ABj70Wv5gDauFd9KgKFwuvpQjfzTwEgodEG8tnBbS8mSQhNrZJ"; + public const string CLIENT_SECRET = "XUmJyvEcEuwQuyhARUAm0a8G3gzbEAeMiATCLyFZ"; + public const string REDIRECT_URI = "https://localhost:5001/OAuthRedirect"; + //used for discovery document //https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.0 private readonly IHttpClientFactory _clientFactory; @@ -54,53 +59,112 @@ namespace qbridge.Controllers _clientFactory = clientFactory; } - // Redirect endpoint - //Step 4 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect - [HttpGet] - public IActionResult Get([FromQuery]string state, [FromQuery]string code) - { - //https://localhost:5001/oauthredirect?state=bar&code=foo - return Content($"State: {state}, Code: {code}"); - } + [HttpGet("Start")] public async Task GetAsync() { + + //GET THE DISCOVERY DOCUMENT + //Discovery document contains the actual current endpoints to use for various ops await GetQBDiscoveryDocument(); if (DiscoveryDoc == null) { return Content($"

Error - Unable to fetch Discovery document from QuickBooks Online

Cannot proceed"); } - var authorizationEndpoint = DiscoveryDoc["authorization_endpoint"].Value(); - if (string.IsNullOrWhiteSpace(authorizationEndpoint)) + + var AuthorizationEndpoint = DiscoveryDoc["authorization_endpoint"].Value(); + if (string.IsNullOrWhiteSpace(AuthorizationEndpoint)) { return Content($"

Error - Unable to find AuthorizationEndpoint value in Discovery document from QuickBooks Online

Cannot proceed"); } + //GET AUTHORIZATION CODE AND REDIRECT + string url = string.Empty; var queryParams = new Dictionary() { - {"client_id", "ABj70Wv5gDauFd9KgKFwuvpQjfzTwEgodEG8tnBbS8mSQhNrZJ" }, + {"client_id", CLIENT_ID }, {"scope", "openid" }, - {"redirect_uri","https://localhost:5001/OAuthRedirect" }, + {"redirect_uri",REDIRECT_URI }, {"response_type","code"}, {"state","MyUniqueStateID"} }; - url = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(authorizationEndpoint, queryParams); + url = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(AuthorizationEndpoint, queryParams); return Redirect(url); - //will ask for login creds and permission then will redirect back to the Get method above with: + //will ask for login creds and permission then will redirect back to the Get method below with: //State: MyUniqueStateID, Code: AB11569366500tshFDRPEuR28l4vTjpXWuwFldE44rMng98Gn9 + //This Code value is the "Authorization code" that is then used to get the access token //which in turn is *then* used to actually get the access token - //which is step 5 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect#step-5-exchange-authorization-code-to-obtain-id-token-and-access-token + + } + // Redirect endpoint + //Step 4 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect + [HttpGet] + public async Task GetAsync([FromQuery]string state, [FromQuery]string code) + { + //We arrive here after the user has logged in and now we should have the authorization code that can now be used to fetch the actual tokens we need + var TokenEndpoint = DiscoveryDoc["token_endpoint"].Value(); + if (string.IsNullOrWhiteSpace(TokenEndpoint)) + { + return Content($"

Error - Unable to find TokenEndpoint value in Discovery document from QuickBooks Online

Cannot proceed"); + } + + //Step 5: Exchange authorization code for refresh and access tokens + //Get access token + //which is step 5 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect#step-5-exchange-authorization-code-to-obtain-id-token-and-access-token + + + + var request = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint); + request.Headers.Add("Accept", "application/json"); + request.Headers.Add("User-Agent", "AyaNova-QBridge"); + request.Headers.Add("Authorization", "Basic " + Base64Encode(CLIENT_ID + ":" + CLIENT_SECRET)); + + var bodyParams = new Dictionary() + { + {"code", code }, + {"redirect_uri", REDIRECT_URI }, + {"grant_type","authorization_code"} + }; + request.Content = new StringContent(JsonConvert.SerializeObject(bodyParams), System.Text.Encoding.UTF8, "application/json"); + var client = _clientFactory.CreateClient(); + var response = await client.SendAsync(request); + + JObject AccessTokenObject = null; + + if (response.IsSuccessStatusCode) + { + string data = await response.Content.ReadAsStringAsync(); + AccessTokenObject = JObject.Parse(data); + } + else + { + AccessTokenObject = null; + } + + return Content($"TOKEN: {AccessTokenObject.ToString()}"); + + + + //https://localhost:5001/oauthredirect?state=bar&code=foo + // return Content($"State: {state}, Code: {code}"); + } + + public static string Base64Encode(string plainText) + { + var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); + return System.Convert.ToBase64String(plainTextBytes); + } public async Task GetQBDiscoveryDocument() {