Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions Xero.NetStandard.OAuth2Client/src/Client/IXeroClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xero.NetStandard.OAuth2.Config;
using Xero.NetStandard.OAuth2.Models;
Expand All @@ -15,13 +16,13 @@ public interface IXeroClient
string BuildLoginUriPkce(string codeVerifier);
string BuildLoginUriPkce(string codeVerifier, string state);
string BuildLoginUriPkce(string codeVerifier, string state, string scope);
Task<IXeroToken> RequestAccessTokenAsync(string code);
Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string codeVerifier);
Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken);
Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenants=true);
Task<IXeroToken> GetCurrentValidTokenAsync(IXeroToken xeroToken);
Task<List<Tenant>> GetConnectionsAsync(IXeroToken xeroToken);
Task DeleteConnectionAsync(IXeroToken xeroToken, Tenant xeroTenant);
Task RevokeAccessTokenAsync(IXeroToken xeroToken);
Task<IXeroToken> RequestAccessTokenAsync(string code, CancellationToken cancellationToken = default);
Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string codeVerifier, CancellationToken cancellationToken = default);
Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default);
Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenants = true, CancellationToken cancellationToken = default);
Task<IXeroToken> GetCurrentValidTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default);
Task<List<Tenant>> GetConnectionsAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default);
Task DeleteConnectionAsync(IXeroToken xeroToken, Tenant xeroTenant, CancellationToken cancellationToken = default);
Task RevokeAccessTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default);
}
}
47 changes: 28 additions & 19 deletions Xero.NetStandard.OAuth2Client/src/Client/XeroClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
Expand Down Expand Up @@ -133,8 +134,9 @@ public string BuildLoginUriPkce(string codeVerifier, string state, string scope)
/// Refreshes your current token
/// </summary>
/// <param name="xeroToken"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken)
public async Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default)
{
if (xeroToken == null)
{
Expand All @@ -147,7 +149,7 @@ public async Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken)
ClientId = xeroConfiguration.ClientId,
ClientSecret = xeroConfiguration.ClientSecret,
RefreshToken = xeroToken.RefreshToken
});
}, cancellationToken);

if (response.IsError)
{
Expand All @@ -165,8 +167,10 @@ public async Task<IXeroToken> RefreshAccessTokenAsync(IXeroToken xeroToken)
/// <summary>
/// Requests a fully formed IXeroToken with list of tenants filled
/// </summary>
/// <param name="fetchTenants"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenants=true)
public async Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenants = true, CancellationToken cancellationToken = default)
{

var response = await _httpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
Expand All @@ -175,7 +179,7 @@ public async Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenan
ClientId = xeroConfiguration.ClientId,
ClientSecret = xeroConfiguration.ClientSecret,
Scope = xeroConfiguration.Scope
});
}, cancellationToken);

if (response.IsError)
{
Expand All @@ -188,7 +192,7 @@ public async Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenan
ExpiresAtUtc = DateTime.UtcNow.AddSeconds(response.ExpiresIn)
};
if(fetchTenants){
xeroToken.Tenants = await GetConnectionsAsync(xeroToken);
xeroToken.Tenants = await GetConnectionsAsync(xeroToken, cancellationToken);
}
return xeroToken;

Expand All @@ -198,8 +202,9 @@ public async Task<IXeroToken> RequestClientCredentialsTokenAsync(bool fetchTenan
/// Requests a fully formed IXeroToken with list of tenants filled
/// </summary>
/// <param name="code">Code returned from callback</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IXeroToken> RequestAccessTokenAsync(string code)
public async Task<IXeroToken> RequestAccessTokenAsync(string code, CancellationToken cancellationToken = default)
{
var response = await _httpClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
{
Expand All @@ -213,7 +218,7 @@ public async Task<IXeroToken> RequestAccessTokenAsync(string code)
{
{ "scope", xeroConfiguration.Scope}
}
});
}, cancellationToken);

if (response.IsError)
{
Expand All @@ -227,7 +232,7 @@ public async Task<IXeroToken> RequestAccessTokenAsync(string code)
ExpiresAtUtc = DateTime.UtcNow.AddSeconds(response.ExpiresIn),
IdToken = response.IdentityToken,
};
xeroToken.Tenants = await GetConnectionsAsync(xeroToken);
xeroToken.Tenants = await GetConnectionsAsync(xeroToken, cancellationToken);
return xeroToken;

}
Expand All @@ -238,9 +243,9 @@ public async Task<IXeroToken> RequestAccessTokenAsync(string code)
/// </summary>
/// <param name="code">code from callback</param>
/// <param name="codeVerifier">codeVerifier used for initial request</param>
/// <param name="xeroToken"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string codeVerifier)
public async Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string codeVerifier, CancellationToken cancellationToken = default)
{

var response = await _httpClient.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
Expand All @@ -256,7 +261,7 @@ public async Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string co
{ "scope", xeroConfiguration.Scope}
},
CodeVerifier = codeVerifier
});
}, cancellationToken);

if (response.IsError)
{
Expand All @@ -277,12 +282,13 @@ public async Task<IXeroToken> RequestAccessTokenPkceAsync(string code, string co
/// Convenience method to refresh token for you if it is expired
/// </summary>
/// <param name="xeroToken">your current XeroToken</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<IXeroToken> GetCurrentValidTokenAsync(IXeroToken xeroToken)
public async Task<IXeroToken> GetCurrentValidTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default)
{
if (DateTime.UtcNow > xeroToken.ExpiresAtUtc)
{
return await RefreshAccessTokenAsync(xeroToken);
return await RefreshAccessTokenAsync(xeroToken, cancellationToken);
}

return xeroToken;
Expand All @@ -291,14 +297,15 @@ public async Task<IXeroToken> GetCurrentValidTokenAsync(IXeroToken xeroToken)
/// Get's a list of Tokens given the accesstoken
/// </summary>
/// <param name="xeroToken"></param>
/// <param name="cancellationToken"></param>
/// <returns>List of Tenants attached to accesstoken</returns>
public async Task<List<Tenant>> GetConnectionsAsync(IXeroToken xeroToken)
public async Task<List<Tenant>> GetConnectionsAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default)
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"{xeroConfiguration.XeroApiBaseUri}/connections"))
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", xeroToken.AccessToken);

var result = await _httpClient.SendAsync(requestMessage);
var result = await _httpClient.SendAsync(requestMessage, cancellationToken);
var json = await result.Content.ReadAsStringAsync();
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
Expand All @@ -315,14 +322,15 @@ public async Task<List<Tenant>> GetConnectionsAsync(IXeroToken xeroToken)
/// </summary>
/// <param name="xeroToken"></param>
/// <param name="xeroTenant"></param>
/// <param name="cancellationToken"></param>
/// <returns>List of Tenants attached to accesstoken</returns>
public async Task DeleteConnectionAsync(IXeroToken xeroToken, Tenant xeroTenant)
public async Task DeleteConnectionAsync(IXeroToken xeroToken, Tenant xeroTenant, CancellationToken cancellationToken = default)
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Delete, $"{xeroConfiguration.XeroApiBaseUri}/connections" + "/" + xeroTenant.id))
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", xeroToken.AccessToken);

var result = await _httpClient.SendAsync(requestMessage);
var result = await _httpClient.SendAsync(requestMessage, cancellationToken);
if (result.StatusCode == System.Net.HttpStatusCode.NoContent)
{
return;
Expand All @@ -336,8 +344,9 @@ public async Task DeleteConnectionAsync(IXeroToken xeroToken, Tenant xeroTenant)
/// Revokes the current token - immediate disconnect all orgs and stops the user authorisation
/// </summary>
/// <param name="xeroToken"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task RevokeAccessTokenAsync(IXeroToken xeroToken)
public async Task RevokeAccessTokenAsync(IXeroToken xeroToken, CancellationToken cancellationToken = default)
{
if (xeroToken == null)
{
Expand All @@ -349,7 +358,7 @@ public async Task RevokeAccessTokenAsync(IXeroToken xeroToken)
ClientId = xeroConfiguration.ClientId,
ClientSecret = xeroConfiguration.ClientSecret,
Token = xeroToken.RefreshToken
});
}, cancellationToken);

if (response.IsError)
{
Expand Down