1
0
mirror of https://github.com/bitwarden/mobile synced 2026-01-05 18:13:36 +00:00

HandleTokenStateAsync before each API call for refresh and auth bearer migration

This commit is contained in:
Kyle Spearrin
2017-02-04 23:31:37 -05:00
parent 8ae95c4e30
commit 74239521cd
11 changed files with 216 additions and 30 deletions

View File

@@ -6,42 +6,153 @@ using Bit.App.Models.Api;
using Newtonsoft.Json;
using Plugin.Connectivity.Abstractions;
using Bit.App.Abstractions;
using System.Net;
using XLabs.Ioc;
namespace Bit.App.Repositories
{
public abstract class BaseApiRepository
{
public BaseApiRepository(IConnectivity connectivity, IHttpService httpService)
public BaseApiRepository(
IConnectivity connectivity,
IHttpService httpService,
ITokenService tokenService)
{
Connectivity = connectivity;
HttpService = httpService;
TokenService = tokenService;
}
protected IConnectivity Connectivity { get; private set; }
protected IHttpService HttpService { get; private set; }
protected ITokenService TokenService { get; private set; }
protected abstract string ApiRoute { get; }
protected async Task<ApiResult> HandleTokenStateAsync()
{
return await HandleTokenStateAsync(
() => ApiResult.Success(HttpStatusCode.OK),
() => HandledWebException(),
(r) => HandleErrorAsync(r));
}
protected async Task<ApiResult<T>> HandleTokenStateAsync<T>()
{
return await HandleTokenStateAsync(
() => ApiResult<T>.Success(default(T), HttpStatusCode.OK),
() => HandledWebException<T>(),
(r) => HandleErrorAsync<T>(r));
}
private async Task<T> HandleTokenStateAsync<T>(Func<T> success, Func<T> webException,
Func<HttpResponseMessage, Task<T>> error)
{
if(!string.IsNullOrWhiteSpace(TokenService.AuthBearer) && string.IsNullOrWhiteSpace(TokenService.Token))
{
// Migrate from old auth bearer to new access token
var deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
var appIdService = Resolver.Resolve<IAppIdService>();
using(var client = HttpService.Client)
{
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(client.BaseAddress, string.Concat(ApiRoute, "/token")),
Content = new FormUrlEncodedContent(new TokenRequest
{
Email = "abcdefgh",
MasterPasswordHash = "abcdefgh",
OldAuthBearer = TokenService.AuthBearer,
Device = new DeviceRequest(appIdService, deviceInfoService)
}.ToIdentityTokenRequest())
};
try
{
var response = await client.SendAsync(requestMessage).ConfigureAwait(false);
if(!response.IsSuccessStatusCode)
{
return await error.Invoke(response).ConfigureAwait(false);
}
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
TokenService.Token = tokenResponse.AccessToken;
TokenService.RefreshToken = tokenResponse.RefreshToken;
TokenService.AuthBearer = null;
}
catch(WebException)
{
return webException.Invoke();
}
}
}
else if(TokenService.TokenNeedsRefresh && !string.IsNullOrWhiteSpace(TokenService.RefreshToken))
{
using(var client = HttpService.Client)
{
var requestMessage = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(client.BaseAddress, string.Concat(ApiRoute, "/token")),
Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "grant_type", "refresh_token" },
{ "client_id", "mobile" },
{ "refresh_token", TokenService.RefreshToken }
})
};
try
{
var response = await client.SendAsync(requestMessage).ConfigureAwait(false);
if(!response.IsSuccessStatusCode)
{
return await error.Invoke(response).ConfigureAwait(false);
}
var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
TokenService.Token = tokenResponse.AccessToken;
TokenService.RefreshToken = tokenResponse.RefreshToken;
}
catch(WebException)
{
return webException.Invoke();
}
}
}
else if(!string.IsNullOrWhiteSpace(TokenService.AuthBearer))
{
TokenService.AuthBearer = null;
}
return success.Invoke();
}
protected ApiResult HandledNotConnected()
{
return ApiResult.Failed(System.Net.HttpStatusCode.RequestTimeout,
return ApiResult.Failed(HttpStatusCode.RequestTimeout,
new ApiError { Message = "Not connected to the internet." });
}
protected ApiResult<T> HandledNotConnected<T>()
{
return ApiResult<T>.Failed(System.Net.HttpStatusCode.RequestTimeout,
return ApiResult<T>.Failed(HttpStatusCode.RequestTimeout,
new ApiError { Message = "Not connected to the internet." });
}
protected ApiResult HandledWebException()
{
return ApiResult.Failed(System.Net.HttpStatusCode.BadGateway,
return ApiResult.Failed(HttpStatusCode.BadGateway,
new ApiError { Message = "There is a problem connecting to the server." });
}
protected ApiResult<T> HandledWebException<T>()
{
return ApiResult<T>.Failed(System.Net.HttpStatusCode.BadGateway,
return ApiResult<T>.Failed(HttpStatusCode.BadGateway,
new ApiError { Message = "There is a problem connecting to the server." });
}