This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -24,6 +25,8 @@ namespace qbridge.Controllers
|
|||||||
|
|
||||||
public const string DISCOVERY_DOCUMENT_URL = "https://developer.api.intuit.com/.well-known/openid_sandbox_configuration";
|
public const string DISCOVERY_DOCUMENT_URL = "https://developer.api.intuit.com/.well-known/openid_sandbox_configuration";
|
||||||
|
|
||||||
|
public static Dictionary<string, QBToken> TOKEN_STORE = null;
|
||||||
|
|
||||||
//current 2019 fall disco doc urls
|
//current 2019 fall disco doc urls
|
||||||
//Sandbox: https://developer.api.intuit.com/.well-known/openid_sandbox_configuration
|
//Sandbox: https://developer.api.intuit.com/.well-known/openid_sandbox_configuration
|
||||||
//Production: https://developer.api.intuit.com/.well-known/openid_configuration
|
//Production: https://developer.api.intuit.com/.well-known/openid_configuration
|
||||||
@@ -66,20 +69,25 @@ namespace qbridge.Controllers
|
|||||||
public OAuthRedirectController(IHttpClientFactory clientFactory)
|
public OAuthRedirectController(IHttpClientFactory clientFactory)
|
||||||
{
|
{
|
||||||
_clientFactory = clientFactory;
|
_clientFactory = clientFactory;
|
||||||
|
TOKEN_STORE = new Dictionary<string, QBToken>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("start/{qboid}")]
|
[HttpGet("start/{state}")]
|
||||||
public async Task<IActionResult> GetAsync([FromRoute]string qboid)
|
public async Task<IActionResult> GetAsync([FromRoute]string state)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(qboid))
|
if (string.IsNullOrWhiteSpace(state))
|
||||||
{
|
{
|
||||||
return BadRequest("QBOID value is required");
|
return BadRequest("state value is required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Job one is to clean out the old entries in the token store if necessary
|
||||||
|
//rather than bothering with some kind of recurring task just do it on every fetch for now
|
||||||
|
SweepTokenStore();
|
||||||
|
|
||||||
//GET THE DISCOVERY DOCUMENT
|
//GET THE DISCOVERY DOCUMENT
|
||||||
//Discovery document contains the actual current endpoints to use for various ops
|
//Discovery document contains the actual current endpoints to use for various ops
|
||||||
await GetQBDiscoveryDocument();
|
await GetQBDiscoveryDocument();
|
||||||
@@ -106,7 +114,7 @@ namespace qbridge.Controllers
|
|||||||
{"scope", "com.intuit.quickbooks.accounting" },
|
{"scope", "com.intuit.quickbooks.accounting" },
|
||||||
{"redirect_uri",REDIRECT_URI },
|
{"redirect_uri",REDIRECT_URI },
|
||||||
{"response_type","code"},
|
{"response_type","code"},
|
||||||
{"state",qboid}
|
{"state",state}
|
||||||
};
|
};
|
||||||
|
|
||||||
url = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(AuthorizationEndpoint, queryParams);
|
url = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(AuthorizationEndpoint, queryParams);
|
||||||
@@ -122,7 +130,7 @@ namespace qbridge.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Redirect endpoint
|
// Redirect endpoint, this is used by the Intuit auth server to redirect back to with the good stuff
|
||||||
//Step 4 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect
|
//Step 4 here: https://developer.intuit.com/app/developer/qbo/docs/develop/authentication-and-authorization/openid-connect
|
||||||
[HttpGet("redirect")]
|
[HttpGet("redirect")]
|
||||||
public async Task<IActionResult> GetAsync([FromQuery] string state, [FromQuery]string code, [FromQuery]string realmId)
|
public async Task<IActionResult> GetAsync([FromQuery] string state, [FromQuery]string code, [FromQuery]string realmId)
|
||||||
@@ -184,6 +192,13 @@ namespace qbridge.Controllers
|
|||||||
var x_refresh_token_expires_in = AccessTokenObject["x_refresh_token_expires_in"].Value<long>();
|
var x_refresh_token_expires_in = AccessTokenObject["x_refresh_token_expires_in"].Value<long>();
|
||||||
var access_token_expires_in = AccessTokenObject["expires_in"].Value<long>();
|
var access_token_expires_in = AccessTokenObject["expires_in"].Value<long>();
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Instead of returning the token here, store it in memory so QBOI can fetch it via the session id token in the "state" variable here
|
||||||
|
//return instead that user is successfully logged in and QBOI is ready to access
|
||||||
|
|
||||||
|
//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
|
return Ok(new
|
||||||
{
|
{
|
||||||
access_token = access_token,
|
access_token = access_token,
|
||||||
@@ -210,6 +225,54 @@ namespace qbridge.Controllers
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//examine stored tokens, if matching one found then return it and erase from the list?
|
||||||
|
[HttpGet("fetch/{state}")]
|
||||||
|
public IActionResult FetchTokenAsync([FromRoute]string state)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(state))
|
||||||
|
{
|
||||||
|
return BadRequest("state value is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class QBToken
|
||||||
|
{
|
||||||
|
public string realmId { get; set; }
|
||||||
|
public string access_token { get; set; }
|
||||||
|
public string refresh_token { get; set; }
|
||||||
|
public DateTime TokenBirthday { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove stale tokens
|
||||||
|
public static void SweepTokenStore()
|
||||||
|
{
|
||||||
|
//ditch tokens older than 7 days
|
||||||
|
//this works because our system in place is intended to be re-authed every session
|
||||||
|
DateTime dtExpireAfter=DateTime.Now.AddDays(-7);
|
||||||
|
//if the token birthday is newer than 7 days ago then select it to remain
|
||||||
|
TOKEN_STORE = TOKEN_STORE.Where(pair => pair.Value.TokenBirthday < dtExpireAfter)
|
||||||
|
.ToDictionary(pair => pair.Key,
|
||||||
|
pair => pair.Value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static string Base64Encode(string plainText)
|
public static string Base64Encode(string plainText)
|
||||||
{
|
{
|
||||||
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
|
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
|
||||||
|
|||||||
Reference in New Issue
Block a user