mirror of
https://github.com/bitwarden/android.git
synced 2024-12-30 04:48:30 +03:00
HandleTokenStateAsync before each API call for refresh and auth bearer migration
This commit is contained in:
parent
8ae95c4e30
commit
74239521cd
11 changed files with 216 additions and 30 deletions
src/App
Abstractions/Services
Models/Api/Request
Repositories
AccountsApiRepository.csApiRepository.csBaseApiRepository.csCipherApiRepository.csConnectApiRepository.csDeviceApiRepository.csFolderApiRepository.csLoginApiRepository.cs
Services
|
@ -11,7 +11,7 @@ namespace Bit.App.Abstractions
|
||||||
DateTime TokenExpiration { get; }
|
DateTime TokenExpiration { get; }
|
||||||
bool TokenExpired { get; }
|
bool TokenExpired { get; }
|
||||||
TimeSpan TokenTimeRemaining { get; }
|
TimeSpan TokenTimeRemaining { get; }
|
||||||
bool TokenNeedseRefresh { get; }
|
bool TokenNeedsRefresh { get; }
|
||||||
string TokenUserId { get; }
|
string TokenUserId { get; }
|
||||||
string TokenEmail { get; }
|
string TokenEmail { get; }
|
||||||
string TokenName { get; }
|
string TokenName { get; }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Bit.App.Models.Api
|
namespace Bit.App.Models.Api
|
||||||
{
|
{
|
||||||
|
@ -8,6 +9,8 @@ namespace Bit.App.Models.Api
|
||||||
public string MasterPasswordHash { get; set; }
|
public string MasterPasswordHash { get; set; }
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
public int? Provider { get; set; }
|
public int? Provider { get; set; }
|
||||||
|
[Obsolete]
|
||||||
|
public string OldAuthBearer { get; set; }
|
||||||
public DeviceRequest Device { get; set; }
|
public DeviceRequest Device { get; set; }
|
||||||
|
|
||||||
public IDictionary<string, string> ToIdentityTokenRequest()
|
public IDictionary<string, string> ToIdentityTokenRequest()
|
||||||
|
@ -21,6 +24,11 @@ namespace Bit.App.Models.Api
|
||||||
{ "client_id", "mobile" }
|
{ "client_id", "mobile" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if(OldAuthBearer != null)
|
||||||
|
{
|
||||||
|
dict.Add("OldAuthBearer", OldAuthBearer);
|
||||||
|
}
|
||||||
|
|
||||||
if(Device != null)
|
if(Device != null)
|
||||||
{
|
{
|
||||||
dict.Add("DeviceType", Device.Type.ToString());
|
dict.Add("DeviceType", Device.Type.ToString());
|
||||||
|
|
|
@ -12,8 +12,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public AccountsApiRepository(
|
public AccountsApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "accounts";
|
protected override string ApiRoute => "accounts";
|
||||||
|
|
|
@ -17,8 +17,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public ApiRepository(
|
public ApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
public virtual async Task<ApiResult<TResponse>> GetByIdAsync(TId id)
|
public virtual async Task<ApiResult<TResponse>> GetByIdAsync(TId id)
|
||||||
|
@ -28,6 +29,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<TResponse>();
|
return HandledNotConnected<TResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<TResponse>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
@ -62,6 +69,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<ListResponse<TResponse>>();
|
return HandledNotConnected<ListResponse<TResponse>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<ListResponse<TResponse>>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
@ -96,6 +109,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<TResponse>();
|
return HandledNotConnected<TResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<TResponse>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage(requestObj)
|
var requestMessage = new TokenHttpRequestMessage(requestObj)
|
||||||
|
@ -130,6 +149,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<TResponse>();
|
return HandledNotConnected<TResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<TResponse>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage(requestObj)
|
var requestMessage = new TokenHttpRequestMessage(requestObj)
|
||||||
|
@ -164,6 +189,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected();
|
return HandledNotConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
|
|
@ -6,42 +6,153 @@ using Bit.App.Models.Api;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Plugin.Connectivity.Abstractions;
|
using Plugin.Connectivity.Abstractions;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
|
using System.Net;
|
||||||
|
using XLabs.Ioc;
|
||||||
|
|
||||||
namespace Bit.App.Repositories
|
namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public abstract class BaseApiRepository
|
public abstract class BaseApiRepository
|
||||||
{
|
{
|
||||||
public BaseApiRepository(IConnectivity connectivity, IHttpService httpService)
|
public BaseApiRepository(
|
||||||
|
IConnectivity connectivity,
|
||||||
|
IHttpService httpService,
|
||||||
|
ITokenService tokenService)
|
||||||
{
|
{
|
||||||
Connectivity = connectivity;
|
Connectivity = connectivity;
|
||||||
HttpService = httpService;
|
HttpService = httpService;
|
||||||
|
TokenService = tokenService;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IConnectivity Connectivity { get; private set; }
|
protected IConnectivity Connectivity { get; private set; }
|
||||||
protected IHttpService HttpService { get; private set; }
|
protected IHttpService HttpService { get; private set; }
|
||||||
|
protected ITokenService TokenService { get; private set; }
|
||||||
protected abstract string ApiRoute { get; }
|
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()
|
protected ApiResult HandledNotConnected()
|
||||||
{
|
{
|
||||||
return ApiResult.Failed(System.Net.HttpStatusCode.RequestTimeout,
|
return ApiResult.Failed(HttpStatusCode.RequestTimeout,
|
||||||
new ApiError { Message = "Not connected to the internet." });
|
new ApiError { Message = "Not connected to the internet." });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ApiResult<T> HandledNotConnected<T>()
|
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." });
|
new ApiError { Message = "Not connected to the internet." });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ApiResult HandledWebException()
|
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." });
|
new ApiError { Message = "There is a problem connecting to the server." });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ApiResult<T> HandledWebException<T>()
|
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." });
|
new ApiError { Message = "There is a problem connecting to the server." });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public CipherApiRepository(
|
public CipherApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "ciphers";
|
protected override string ApiRoute => "ciphers";
|
||||||
|
@ -27,6 +28,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<CipherResponse>();
|
return HandledNotConnected<CipherResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<CipherResponse>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
@ -61,6 +68,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<ListResponse<CipherResponse>>();
|
return HandledNotConnected<ListResponse<CipherResponse>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<ListResponse<CipherResponse>>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
@ -95,6 +108,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<CipherHistoryResponse>();
|
return HandledNotConnected<CipherHistoryResponse>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<CipherHistoryResponse>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public ConnectApiRepository(
|
public ConnectApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "connect";
|
protected override string ApiRoute => "connect";
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public DeviceApiRepository(
|
public DeviceApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "devices";
|
protected override string ApiRoute => "devices";
|
||||||
|
@ -26,6 +27,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected();
|
return HandledNotConnected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage(request)
|
var requestMessage = new TokenHttpRequestMessage(request)
|
||||||
|
|
|
@ -14,8 +14,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public FolderApiRepository(
|
public FolderApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "folders";
|
protected override string ApiRoute => "folders";
|
||||||
|
@ -27,6 +28,12 @@ namespace Bit.App.Repositories
|
||||||
return HandledNotConnected<ListResponse<FolderResponse>>();
|
return HandledNotConnected<ListResponse<FolderResponse>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tokenStateResponse = await HandleTokenStateAsync<ListResponse<FolderResponse>>();
|
||||||
|
if(!tokenStateResponse.Succeeded)
|
||||||
|
{
|
||||||
|
return tokenStateResponse;
|
||||||
|
}
|
||||||
|
|
||||||
using(var client = HttpService.Client)
|
using(var client = HttpService.Client)
|
||||||
{
|
{
|
||||||
var requestMessage = new TokenHttpRequestMessage()
|
var requestMessage = new TokenHttpRequestMessage()
|
||||||
|
|
|
@ -13,8 +13,9 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
public LoginApiRepository(
|
public LoginApiRepository(
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IHttpService httpService)
|
IHttpService httpService,
|
||||||
: base(connectivity, httpService)
|
ITokenService tokenService)
|
||||||
|
: base(connectivity, httpService, tokenService)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
protected override string ApiRoute => "sites";
|
protected override string ApiRoute => "sites";
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Bit.App.Services
|
namespace Bit.App.Services
|
||||||
{
|
{
|
||||||
|
@ -67,22 +68,21 @@ namespace Bit.App.Services
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var decoded = DecodeToken();
|
var decoded = DecodeToken();
|
||||||
long exp = 0;
|
if(decoded?["exp"] == null)
|
||||||
if(decoded?.exp != null || !long.TryParse(decoded.exp, out exp))
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("No exp in token.");
|
throw new InvalidOperationException("No exp in token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return _epoc.AddSeconds(Convert.ToDouble(exp));
|
return _epoc.AddSeconds(Convert.ToDouble(decoded["exp"].Value<long>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TokenExpired => DateTime.UtcNow < TokenExpiration;
|
public bool TokenExpired => DateTime.UtcNow < TokenExpiration;
|
||||||
public TimeSpan TokenTimeRemaining => TokenExpiration - DateTime.UtcNow;
|
public TimeSpan TokenTimeRemaining => TokenExpiration - DateTime.UtcNow;
|
||||||
public bool TokenNeedseRefresh => TokenTimeRemaining.TotalMinutes < 5;
|
public bool TokenNeedsRefresh => TokenTimeRemaining.TotalMinutes < 5;
|
||||||
public string TokenUserId => DecodeToken()?.sub;
|
public string TokenUserId => DecodeToken()?["sub"].Value<string>();
|
||||||
public string TokenEmail => DecodeToken()?.email;
|
public string TokenEmail => DecodeToken()?["email"].Value<string>();
|
||||||
public string TokenName => DecodeToken()?.name;
|
public string TokenName => DecodeToken()?["name"].Value<string>();
|
||||||
|
|
||||||
public string RefreshToken
|
public string RefreshToken
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,7 @@ namespace Bit.App.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public dynamic DecodeToken()
|
public JObject DecodeToken()
|
||||||
{
|
{
|
||||||
if(_decodedToken != null)
|
if(_decodedToken != null)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +176,7 @@ namespace Bit.App.Services
|
||||||
throw new InvalidOperationException($"{nameof(Token)} must have 3 parts");
|
throw new InvalidOperationException($"{nameof(Token)} must have 3 parts");
|
||||||
}
|
}
|
||||||
|
|
||||||
_decodedToken = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(decodedBytes, 0, decodedBytes.Length));
|
_decodedToken = JObject.Parse(Encoding.UTF8.GetString(decodedBytes, 0, decodedBytes.Length));
|
||||||
return _decodedToken;
|
return _decodedToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue