diff --git a/Controllers/AuthController.cs b/Controllers/AuthController.cs
index 1ab766f..31b4a3e 100644
--- a/Controllers/AuthController.cs
+++ b/Controllers/AuthController.cs
@@ -93,16 +93,15 @@ namespace qbridge.Controllers
await GetQBDiscoveryDocument();
if (DiscoveryDoc == null)
{
- return Content($"
Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed");
-
+ return ContentPage($"Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed");
}
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");
+ return ContentPage($"Error - Unable to find AuthorizationEndpoint value in Discovery document from QuickBooks Online
Cannot proceed");
}
-
+
//GET AUTHORIZATION CODE AND REDIRECT
@@ -140,7 +139,7 @@ namespace qbridge.Controllers
if (DiscoveryDoc == null)
{
- return Content($"Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed with Revoke");
+ return ContentPage($"Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed with Revoke");
}
@@ -148,7 +147,7 @@ namespace qbridge.Controllers
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");
+ return ContentPage($"Error - Unable to find TokenEndpoint value in Discovery document from QuickBooks Online
Cannot proceed");
}
//Step 5: Exchange authorization code for refresh and access tokens
@@ -179,34 +178,21 @@ namespace qbridge.Controllers
{
string data = await response.Content.ReadAsStringAsync();
AccessTokenObject = JObject.Parse(data);
+ var refresh_token = AccessTokenObject["refresh_token"].Value();
+ var access_token = AccessTokenObject["access_token"].Value();
+ var x_refresh_token_expires_in = AccessTokenObject["x_refresh_token_expires_in"].Value();
+ var access_token_expires_in = AccessTokenObject["expires_in"].Value();
+
+ //Store the token!!
+ TOKEN_STORE.Add(state, new QBToken() { realmId = realmId, access_token = access_token, refresh_token = refresh_token, TokenBirthday = DateTime.Now });
+ return Redirect("/success");
}
else
{
- AccessTokenObject = null;
+ return ContentPage($"Error - Failed to authenticate with QuickBooks Online
Error returned by QuickBooks online is: {response.ReasonPhrase}");
}
- var refresh_token = AccessTokenObject["refresh_token"].Value();
- var access_token = AccessTokenObject["access_token"].Value();
- var x_refresh_token_expires_in = AccessTokenObject["x_refresh_token_expires_in"].Value();
- var access_token_expires_in = AccessTokenObject["expires_in"].Value();
-
-
- //Store the token!!
- TOKEN_STORE.Add(state, new QBToken() { realmId = realmId, access_token = access_token, refresh_token = refresh_token, TokenBirthday = DateTime.Now });
-
- return Ok(new
- {
- access_token = access_token,
- access_token_expires_in = access_token_expires_in,
- refresh_token = refresh_token,
- x_refresh_token_expires_in = x_refresh_token_expires_in,
- realmId = realmId,
- code = code,
- state = state
- });
- //return Content($"ACCESS TOKEN: {access_token}, REFRESH TOKEN: {refresh_token}, REALM:{realmId}, STATE:{state}, CODE:{code}");
-
/*
Actual response example:
@@ -222,11 +208,19 @@ namespace qbridge.Controllers
}
+ //return a success page to the user
+ //this is done as a redirect to scrub the url bar clean of the codes and state etc
+ [HttpGet("success")]
+ public IActionResult SuccessPage()
+ {
+ return ContentPage("Success!
Token received from QuickBooks online and available for QBOI to automatically retrieve. You can close this browser window now.");
+
+ }
//examine stored tokens, if matching one found then return it and erase from the list?
[HttpGet("fetch/{state}")]
- public IActionResult FetchTokenAsync([FromRoute]string state)
+ public IActionResult FetchToken([FromRoute]string state)
{
//clear out any tokens older than 1 hour
SweepTokenStore();
@@ -279,8 +273,6 @@ namespace qbridge.Controllers
-
-
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
@@ -343,14 +335,14 @@ namespace qbridge.Controllers
await GetQBDiscoveryDocument();
if (DiscoveryDoc == null)
{
- return Content($"Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed with Revoke");
+ return ContentPage($"Error - Unable to fetch Discovery document from QuickBooks Online
Cannot proceed with Revoke");
}
var revocation_endpoint = DiscoveryDoc["revocation_endpoint"].Value();
if (string.IsNullOrWhiteSpace(revocation_endpoint))
{
- return Content($"Error - Unable to find revocation_endpoint value in Discovery document from QuickBooks Online
Cannot proceed");
+ return ContentPage($"Error - Unable to find revocation_endpoint value in Discovery document from QuickBooks Online
Cannot proceed");
}
@@ -379,11 +371,11 @@ namespace qbridge.Controllers
if (response.IsSuccessStatusCode)
{
- return Content("Token revoked");
+ return ContentPage("Token revoked");
}
else
{
- return Content("Token revocation FAILED!");
+ return ContentPage("Token revocation FAILED!");
}
@@ -391,53 +383,21 @@ namespace qbridge.Controllers
}
-
-
-
- /*
- Plan:
- Make a web APP and api that runs on our server and handles getting tokens from the QB Online oAuth2 endpoints
-
- Docs for normal development are here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization
-
- Tentative process:
-
- Borrowing from the technique and concepts outlined here: http://relasoft.net/KB10004.html
- and here: https://github.com/IntuitDeveloper/C2QB-library-for-Windows-CUI-and-GUI/issues/1#issuecomment-511172847
-
-
- User runs QBOI plugin, if it needs a new access token then it shells out to browser (with random temp session ID number to uniquely identify this user) to go to *our* qBridge auth page.
- User enters their creds to login to QBOnline instance.
- QBridge passes creds (along with random session id as the extra parameter they allow) on to the QBOI auth page which when successful redirects browser to the QBridge page we've specified as the
- "redirect url" with the tokens in the url and also our unique session ID which then shows the end user that it's success and stores the tokens somewhere (gonna need a db I guess) for fetching by QBOI.
-
- Meanwhile, in the background, QBOI is polling a route on qbridge with the unique ID number looking for a return of the tokens it needs to proceed.
- Once it fetches the "Access token" and "Refresh token" it needs successfully then it continues on to normal usage
-
- If it gets a response that the token needs to be refreshed, it either hands this operation off to qBridge or does it itself (not sure at this point which way it's supposed to happen)
- If the access token expires after 100 days or so then they repeat this process (automatically by QBOI)
-
-
- */
- // POST: api/Todo
- // [HttpPost]
- // public async Task> Post(QCreds creds)
- // {
-
- // var q = new QItem();
- // q.Token1 = "Test token 1";
- // q.Token2 = System.DateTime.Now.ToString();
- // q.Token3 = creds.Login;
- // return Ok(q);
- // //return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
- // }
-
- // public class QCreds
- // {
- // public string Login { get; set; }
- // public string Password { get; set; }
- // }
-
+ ///
+ /// Prepare a content result that includes the specified html
+ /// This is the .net core 2.x approved way of returning content from a web api route
+ ///
+ ///
+ ///
+ private ContentResult ContentPage(string bodyHtml)
+ {
+ return new ContentResult
+ {
+ ContentType = "text/html",
+ StatusCode = (int)Microsoft.AspNetCore.Http.StatusCodes.Status200OK,
+ Content = $"{bodyHtml}"
+ };
+ }
// *************************************************************************************************************