i am new to mvc trying to call Api from Quickbooks to get company info (Sandbox), i followed the instructions in intuit.com about that : create app , generate client id , client secret and use them in the web.config . also i generate OAuth2 and i was able to see the 'connect to Quickbooks ' dialog in my project after sign in with user name and password , now i was trying to call the Api so firstly i create dobject of OAuth2RequestValidator class but an error says 'Object Reference Not Set to instance of an object' a i am using claims for authentication i think that claimsPrincipal is not able to read claims from ClaimsIdentity and i am stuck here , i am trying to use the sample code that is in intuit.com
this is the controller to get authentication and call the api
public class AppController : Controller
{
public static string clientid = ConfigurationManager.AppSettings["clientid"];
public static string clientsecret = ConfigurationManager.AppSettings["clientsecret"];
public static string redirectUrl = ConfigurationManager.AppSettings["redirectUrl"];
public static string environment = ConfigurationManager.AppSettings["appEnvironment"];
public static OAuth2Client auth2Client = new OAuth2Client(clientid, clientsecret, redirectUrl, environment);
/// <summary>
/// Use the Index page of App controller to get all endpoints from discovery url
/// </summary>
public ActionResult Index()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Session.Clear();
Session.Abandon();
Request.GetOwinContext().Authentication.SignOut("Cookies");
return View();
}
/// <summary>
/// Start Auth flow
/// </summary>
public ActionResult InitiateAuth(string submitButton)
{
switch (submitButton)
{
case "Connect to QuickBooks":
List<OidcScopes> scopes = new List<OidcScopes>();
scopes.Add(OidcScopes.Accounting);
string authorizeUrl = auth2Client.GetAuthorizationURL(scopes);
return Redirect(authorizeUrl);
default:
return (View());
}
}
/// <summary>
/// QBO API Request
/// </summary>
public ActionResult ApiCallService()
{
if (Session["realmId"] != null)
{
string realmId = Session["realmId"].ToString();
try
{
var principal = User as ClaimsPrincipal;
OAuth2RequestValidator oauthValidator = new OAuth2RequestValidator(principal.FindFirst("access_token").Value);
// Create a ServiceContext with Auth tokens and realmId
ServiceContext serviceContext = new ServiceContext(realmId, IntuitServicesType.QBO, oauthValidator);
serviceContext.IppConfiguration.MinorVersion.Qbo = "23";
// Create a QuickBooks QueryService using ServiceContext
QueryService<CompanyInfo> querySvc = new QueryService<CompanyInfo>(serviceContext);
CompanyInfo companyInfo = querySvc.ExecuteIdsQuery("SELECT * FROM CompanyInfo").FirstOrDefault();
string output = "Company Name: " + companyInfo.CompanyName + " Company Address: " + companyInfo.CompanyAddr.Line1 + ", " + companyInfo.CompanyAddr.City + ", " + companyInfo.CompanyAddr.Country + " " + companyInfo.CompanyAddr.PostalCode;
return View("ApiCallService", (object)("QBO API call Successful!! Response: " + output));
}
catch (Exception ex)
{
return View("ApiCallService", (object)("QBO API call Failed!" + " Error message: " + ex.Message));
}
}
else
return View("ApiCallService", (object)"QBO API call Failed!");
}
/// <summary>
/// Use the Index page of App controller to get all endpoints from discovery url
/// </summary>
public ActionResult Error()
{
return View("Error");
}
/// <summary>
/// Action that takes redirection from Callback URL
/// </summary>
public ActionResult Tokens()
{
return View("Tokens");
}
and this controller created Access Token and refresh token
public class CallbackController : Controller
{
/// <summary>
/// Code and realmid/company id recieved on Index page after redirect is complete from Authorization url
/// </summary>
public async Task<ActionResult> Index()
{
//Sync the state info and update if it is not the same
var state = Request.QueryString["state"];
if (state.Equals(AppController.auth2Client.CSRFToken, StringComparison.Ordinal))
{
ViewBag.State = state + " (valid)";
}
else
{
ViewBag.State = state + " (invalid)";
}
string code = Request.QueryString["code"] ?? "none";
string realmId = Request.QueryString["realmId"] ?? "none";
await GetAuthTokensAsync(code, realmId);
ViewBag.Error = Request.QueryString["error"] ?? "none";
return RedirectToAction("Tokens", "App");
}
/// <summary>
/// Exchange Auth code with Auth Access and Refresh tokens and add them to Claim list
/// </summary>
private async Task GetAuthTokensAsync(string code, string realmId)
{
if (realmId != null)
{
Session["realmId"] = realmId;
}
Request.GetOwinContext().Authentication.SignOut("TempState");
var tokenResponse = await AppController.auth2Client.GetBearerTokenAsync(code);
var claims = new List<Claim>();
if (Session["realmId"] != null)
{
claims.Add(new Claim("realmId", Session["realmId"].ToString()));
}
if (!string.IsNullOrWhiteSpace(tokenResponse.AccessToken))
{
claims.Add(new Claim("access_token", tokenResponse.AccessToken));
claims.Add(new Claim("access_token_expires_at", (DateTime.Now.AddSeconds(tokenResponse.AccessTokenExpiresIn)).ToString()));
}
if (!string.IsNullOrWhiteSpace(tokenResponse.RefreshToken))
{
claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
claims.Add(new Claim("refresh_token_expires_at", (DateTime.Now.AddSeconds(tokenResponse.RefreshTokenExpiresIn)).ToString()));
}
var id = new ClaimsIdentity(claims, "Cookies");
Request.GetOwinContext().Authentication.SignIn(id);
}
}
note : this is the controller where the user redirected after authentication completed .
and this is the error occured when i try to call api bject reference not set to an instance of an object. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 66: //{ Line 67: var principal = User as ClaimsPrincipal; Line 68:
OAuth2RequestValidator oauthValidator = new OAuth2RequestValidator(principal.FindFirst("access_token").Value); Line 69: Line 70: // Create a ServiceContext with Auth tokens and realmId