Completed first iteration of access-refresh auth. Upgraded mooncore. Refactored mooncore related stuff
This commit is contained in:
@@ -38,6 +38,9 @@ public class AppConfiguration
|
|||||||
public string AccessSecret { get; set; } = Formatter.GenerateString(32);
|
public string AccessSecret { get; set; } = Formatter.GenerateString(32);
|
||||||
public string RefreshSecret { get; set; } = Formatter.GenerateString(32);
|
public string RefreshSecret { get; set; } = Formatter.GenerateString(32);
|
||||||
public string CodeSecret { get; set; } = Formatter.GenerateString(32);
|
public string CodeSecret { get; set; } = Formatter.GenerateString(32);
|
||||||
|
|
||||||
|
public int AccessTokenDuration { get; set; } = 60;
|
||||||
|
public int RefreshTokenDuration { get; set; } = 3600;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OAuth2Data
|
public class OAuth2Data
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using MoonCore.Exceptions;
|
using MoonCore.Exceptions;
|
||||||
using MoonCore.Extended.Abstractions;
|
using MoonCore.Extended.Abstractions;
|
||||||
using MoonCore.Extended.Helpers;
|
using MoonCore.Extended.Helpers;
|
||||||
@@ -12,7 +13,6 @@ using Moonlight.ApiServer.Database.Entities;
|
|||||||
using Moonlight.ApiServer.Helpers.Authentication;
|
using Moonlight.ApiServer.Helpers.Authentication;
|
||||||
using Moonlight.ApiServer.Interfaces.Auth;
|
using Moonlight.ApiServer.Interfaces.Auth;
|
||||||
using Moonlight.ApiServer.Interfaces.OAuth2;
|
using Moonlight.ApiServer.Interfaces.OAuth2;
|
||||||
using Moonlight.ApiServer.Services;
|
|
||||||
using Moonlight.Shared.Http.Requests.Auth;
|
using Moonlight.Shared.Http.Requests.Auth;
|
||||||
using Moonlight.Shared.Http.Responses.Auth;
|
using Moonlight.Shared.Http.Responses.Auth;
|
||||||
|
|
||||||
@@ -27,20 +27,22 @@ public class AuthController : Controller
|
|||||||
private readonly ConfigService<AppConfiguration> ConfigService;
|
private readonly ConfigService<AppConfiguration> ConfigService;
|
||||||
private readonly DatabaseRepository<User> UserRepository;
|
private readonly DatabaseRepository<User> UserRepository;
|
||||||
private readonly ImplementationService ImplementationService;
|
private readonly ImplementationService ImplementationService;
|
||||||
|
private readonly ILogger<AuthController> Logger;
|
||||||
|
|
||||||
public AuthController(
|
public AuthController(
|
||||||
OAuth2Service oAuth2Service,
|
OAuth2Service oAuth2Service,
|
||||||
TokenHelper tokenHelper,
|
TokenHelper tokenHelper,
|
||||||
DatabaseRepository<User> userRepository,
|
DatabaseRepository<User> userRepository,
|
||||||
ConfigService<AppConfiguration> configService,
|
ConfigService<AppConfiguration> configService,
|
||||||
ImplementationService implementationService
|
ImplementationService implementationService,
|
||||||
)
|
ILogger<AuthController> logger)
|
||||||
{
|
{
|
||||||
OAuth2Service = oAuth2Service;
|
OAuth2Service = oAuth2Service;
|
||||||
TokenHelper = tokenHelper;
|
TokenHelper = tokenHelper;
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
ConfigService = configService;
|
ConfigService = configService;
|
||||||
ImplementationService = implementationService;
|
ImplementationService = implementationService;
|
||||||
|
Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@@ -54,7 +56,7 @@ public class AuthController : Controller
|
|||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<OAuth2HandleResponse> Handle([FromBody] OAuth2HandleRequest request)
|
public async Task<OAuth2HandleResponse> Handle([FromBody] OAuth2HandleRequest request)
|
||||||
{
|
{
|
||||||
var accessData = await OAuth2Service.RequestAccess(request.Code);
|
var accessData = await OAuth2Service.RequestAccess(request.Code);;
|
||||||
|
|
||||||
// Find oauth2 provider
|
// Find oauth2 provider
|
||||||
var provider = ImplementationService.Get<IOAuth2Provider>().FirstOrDefault();
|
var provider = ImplementationService.Get<IOAuth2Provider>().FirstOrDefault();
|
||||||
@@ -93,10 +95,10 @@ public class AuthController : Controller
|
|||||||
|
|
||||||
var authConfig = ConfigService.Get().Authentication;
|
var authConfig = ConfigService.Get().Authentication;
|
||||||
|
|
||||||
var tokenPair = await TokenHelper.GeneratePair(
|
var tokenPair = TokenHelper.GeneratePair(
|
||||||
authConfig.AccessSecret,
|
authConfig.AccessSecret,
|
||||||
authConfig.AccessSecret,
|
authConfig.RefreshSecret,
|
||||||
data => { data.Add("userId", user.Id.ToString()); },
|
data => { data.Add("userId", user.Id); },
|
||||||
authConfig.AccessDuration,
|
authConfig.AccessDuration,
|
||||||
authConfig.RefreshDuration
|
authConfig.RefreshDuration
|
||||||
);
|
);
|
||||||
@@ -116,7 +118,7 @@ public class AuthController : Controller
|
|||||||
{
|
{
|
||||||
var authConfig = ConfigService.Get().Authentication;
|
var authConfig = ConfigService.Get().Authentication;
|
||||||
|
|
||||||
var tokenPair = await TokenHelper.RefreshPair(
|
var tokenPair = TokenHelper.RefreshPair(
|
||||||
request.RefreshToken,
|
request.RefreshToken,
|
||||||
authConfig.AccessSecret,
|
authConfig.AccessSecret,
|
||||||
authConfig.RefreshSecret,
|
authConfig.RefreshSecret,
|
||||||
@@ -139,7 +141,7 @@ public class AuthController : Controller
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ProcessRefreshData(Dictionary<string, string> refreshTokenData, Dictionary<string, string> newData, IServiceProvider serviceProvider)
|
private bool ProcessRefreshData(Dictionary<string, JsonElement> refreshTokenData, Dictionary<string, object> newData, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
// Find oauth2 provider
|
// Find oauth2 provider
|
||||||
var provider = ImplementationService.Get<IOAuth2Provider>().FirstOrDefault();
|
var provider = ImplementationService.Get<IOAuth2Provider>().FirstOrDefault();
|
||||||
@@ -148,7 +150,7 @@ public class AuthController : Controller
|
|||||||
throw new HttpApiException("No oauth2 provider has been registered", 500);
|
throw new HttpApiException("No oauth2 provider has been registered", 500);
|
||||||
|
|
||||||
// Check if the userId is present in the refresh token
|
// Check if the userId is present in the refresh token
|
||||||
if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId))
|
if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Load user from database if existent
|
// Load user from database if existent
|
||||||
@@ -166,34 +168,43 @@ public class AuthController : Controller
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if it's time to resync with the oauth2 provider
|
// Check if it's time to resync with the oauth2 provider
|
||||||
if (false && DateTime.UtcNow >= user.RefreshTimestamp)
|
if (DateTime.UtcNow >= user.RefreshTimestamp)
|
||||||
{
|
{
|
||||||
// It's time to refresh the access to the external oauth2 provider
|
try
|
||||||
var refreshData = OAuth2Service.RefreshAccess(user.RefreshToken).Result;
|
{
|
||||||
|
// It's time to refresh the access to the external oauth2 provider
|
||||||
|
var refreshData = OAuth2Service.RefreshAccess(user.RefreshToken).Result;
|
||||||
|
|
||||||
// Sync user with oauth2 provider
|
// Sync user with oauth2 provider
|
||||||
var syncedUser = provider.Sync(serviceProvider, refreshData.AccessToken).Result;
|
var syncedUser = provider.Sync(serviceProvider, refreshData.AccessToken).Result;
|
||||||
|
|
||||||
if (syncedUser == null) // User sync has failed. No refresh allowed
|
if (syncedUser == null) // User sync has failed. No refresh allowed
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Save oauth2 refresh and access tokens for later use (re-authentication etc.).
|
||||||
|
// Fetch user model in current db context, just in case the oauth2 provider
|
||||||
|
// uses a different db context or smth
|
||||||
|
|
||||||
|
var userModel = UserRepository
|
||||||
|
.Get()
|
||||||
|
.First(x => x.Id == syncedUser.Id);
|
||||||
|
|
||||||
|
userModel.AccessToken = refreshData.AccessToken;
|
||||||
|
userModel.RefreshToken = refreshData.RefreshToken;
|
||||||
|
userModel.RefreshTimestamp = DateTime.UtcNow.AddSeconds(refreshData.ExpiresIn);
|
||||||
|
|
||||||
|
UserRepository.Update(userModel);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// We are handling this error more softly, because it will occur when a user hasn't logged in a long period of time
|
||||||
|
Logger.LogDebug("An error occured while refreshing external oauth2 access: {e}", e);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// Save oauth2 refresh and access tokens for later use (re-authentication etc.).
|
|
||||||
// Fetch user model in current db context, just in case the oauth2 provider
|
|
||||||
// uses a different db context or smth
|
|
||||||
|
|
||||||
var userModel = UserRepository
|
|
||||||
.Get()
|
|
||||||
.First(x => x.Id == syncedUser.Id);
|
|
||||||
|
|
||||||
userModel.AccessToken = refreshData.AccessToken;
|
|
||||||
userModel.RefreshToken = refreshData.RefreshToken;
|
|
||||||
userModel.RefreshTimestamp = DateTime.UtcNow.AddSeconds(refreshData.ExpiresIn);
|
|
||||||
|
|
||||||
UserRepository.Update(userModel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All checks have passed, allow refresh
|
// All checks have passed, allow refresh
|
||||||
newData.Add("userId", user.Id.ToString());
|
newData.Add("userId", user.Id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class OAuth2Controller : Controller
|
|||||||
|
|
||||||
var user = await AuthService.Login(email, password);
|
var user = await AuthService.Login(email, password);
|
||||||
|
|
||||||
var code = await OAuth2Service.GenerateCode(data => { data.Add("userId", user.Id.ToString()); });
|
var code = await OAuth2Service.GenerateCode(data => { data.Add("userId", user.Id); });
|
||||||
|
|
||||||
var redirectUrl = redirectUri +
|
var redirectUrl = redirectUri +
|
||||||
$"?code={code}";
|
$"?code={code}";
|
||||||
@@ -98,16 +98,13 @@ public class OAuth2Controller : Controller
|
|||||||
|
|
||||||
var access = await OAuth2Service.ValidateAccess(clientId, clientSecret, redirectUri, code, data =>
|
var access = await OAuth2Service.ValidateAccess(clientId, clientSecret, redirectUri, code, data =>
|
||||||
{
|
{
|
||||||
if (!data.TryGetValue("userId", out var userIdStr))
|
if (!data.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!int.TryParse(userIdStr, out var userId))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
user = UserRepository.Get().FirstOrDefault(x => x.Id == userId);
|
user = UserRepository.Get().FirstOrDefault(x => x.Id == userId);
|
||||||
|
|
||||||
return user != null;
|
return user != null;
|
||||||
}, data => { data.Add("userId", user!.Id.ToString()); });
|
}, data => { data.Add("userId", user!.Id); });
|
||||||
|
|
||||||
if (access == null)
|
if (access == null)
|
||||||
throw new HttpApiException("Unable to validate access", 400);
|
throw new HttpApiException("Unable to validate access", 400);
|
||||||
@@ -115,6 +112,39 @@ public class OAuth2Controller : Controller
|
|||||||
return access;
|
return access;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("refresh")]
|
||||||
|
public async Task<RefreshData> Refresh(
|
||||||
|
[FromForm(Name = "grant_type")] string grantType,
|
||||||
|
[FromForm(Name = "refresh_token")] string refreshToken
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (grantType != "refresh_token")
|
||||||
|
throw new HttpApiException("Invalid grant type", 400);
|
||||||
|
|
||||||
|
var refreshData = await OAuth2Service.RefreshAccess(refreshToken, (refreshTokenData, newTokenData) =>
|
||||||
|
{
|
||||||
|
// Check if the userId is present in the refresh token
|
||||||
|
if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Load user from database if existent
|
||||||
|
var user = UserRepository
|
||||||
|
.Get()
|
||||||
|
.FirstOrDefault(x => x.Id == userId);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newTokenData.Add("userId", user.Id);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(refreshData == null)
|
||||||
|
throw new HttpApiException("Unable to validate refresh", 400);
|
||||||
|
|
||||||
|
return refreshData;
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("info")]
|
[HttpGet("info")]
|
||||||
public async Task<InfoResponse> Info()
|
public async Task<InfoResponse> Info()
|
||||||
{
|
{
|
||||||
@@ -133,7 +163,7 @@ public class OAuth2Controller : Controller
|
|||||||
data =>
|
data =>
|
||||||
{
|
{
|
||||||
// Check if the userId is present in the access token
|
// Check if the userId is present in the access token
|
||||||
if (!data.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId))
|
if (!data.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
currentUser = UserRepository
|
currentUser = UserRepository
|
||||||
@@ -150,7 +180,7 @@ public class OAuth2Controller : Controller
|
|||||||
if (!isValid)
|
if (!isValid)
|
||||||
throw new HttpApiException("Invalid access token", 401);
|
throw new HttpApiException("Invalid access token", 401);
|
||||||
|
|
||||||
if(currentUser == null)
|
if (currentUser == null)
|
||||||
throw new HttpApiException("Invalid access token", 401);
|
throw new HttpApiException("Invalid access token", 401);
|
||||||
|
|
||||||
return new InfoResponse()
|
return new InfoResponse()
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="MoonCore" Version="1.6.2" />
|
<PackageReference Include="MoonCore" Version="1.6.4" />
|
||||||
<PackageReference Include="MoonCore.Extended" Version="1.1.0" />
|
<PackageReference Include="MoonCore.Extended" Version="1.1.2" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ builder.Services.AddSwaggerGen();
|
|||||||
|
|
||||||
builder.Services.AddSingleton(configService);
|
builder.Services.AddSingleton(configService);
|
||||||
|
|
||||||
builder.Services.AddSingleton<JwtHelper>();
|
|
||||||
builder.Services.AutoAddServices<Program>();
|
builder.Services.AutoAddServices<Program>();
|
||||||
|
|
||||||
// OAuth2
|
// OAuth2
|
||||||
@@ -141,7 +140,7 @@ builder.Services.AddTokenAuthentication(configuration =>
|
|||||||
configuration.AccessSecret = config.Authentication.AccessSecret;
|
configuration.AccessSecret = config.Authentication.AccessSecret;
|
||||||
configuration.DataLoader = async (data, provider, context) =>
|
configuration.DataLoader = async (data, provider, context) =>
|
||||||
{
|
{
|
||||||
if (!data.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId))
|
if (!data.TryGetValue("userId", out var userIdStr) || !userIdStr.TryGetInt32(out var userId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var userRepo = provider.GetRequiredService<DatabaseRepository<User>>();
|
var userRepo = provider.GetRequiredService<DatabaseRepository<User>>();
|
||||||
@@ -211,7 +210,7 @@ app.UseRouting();
|
|||||||
|
|
||||||
app.UseMiddleware<ApiErrorMiddleware>();
|
app.UseMiddleware<ApiErrorMiddleware>();
|
||||||
|
|
||||||
app.UseTokenAuthentication(_ => {});
|
app.UseTokenAuthentication();
|
||||||
|
|
||||||
app.UseMiddleware<AuthorizationMiddleware>();
|
app.UseMiddleware<AuthorizationMiddleware>();
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"dotnetRunMessages": true,
|
"dotnetRunMessages": true,
|
||||||
"launchBrowser": false,
|
"launchBrowser": false,
|
||||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
|
|
||||||
"applicationUrl": "http://localhost:5165",
|
"applicationUrl": "http://localhost:5165",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
}
|
},
|
||||||
|
"hotReloadEnabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,16 +13,13 @@ public class AuthService
|
|||||||
{
|
{
|
||||||
private readonly DatabaseRepository<User> UserRepository;
|
private readonly DatabaseRepository<User> UserRepository;
|
||||||
private readonly ConfigService<AppConfiguration> ConfigService;
|
private readonly ConfigService<AppConfiguration> ConfigService;
|
||||||
private readonly JwtHelper JwtHelper;
|
|
||||||
|
|
||||||
public AuthService(
|
public AuthService(
|
||||||
DatabaseRepository<User> userRepository,
|
DatabaseRepository<User> userRepository,
|
||||||
ConfigService<AppConfiguration> configService,
|
ConfigService<AppConfiguration> configService)
|
||||||
JwtHelper jwtHelper)
|
|
||||||
{
|
{
|
||||||
UserRepository = userRepository;
|
UserRepository = userRepository;
|
||||||
ConfigService = configService;
|
ConfigService = configService;
|
||||||
JwtHelper = jwtHelper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<User> Register(string username, string email, string password)
|
public Task<User> Register(string username, string email, string password)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6"/>
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.6"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all"/>
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.6" PrivateAssets="all"/>
|
||||||
<PackageReference Include="MoonCore" Version="1.6.2" />
|
<PackageReference Include="MoonCore" Version="1.6.4" />
|
||||||
<PackageReference Include="MoonCore.Blazor" Version="1.2.1" />
|
<PackageReference Include="MoonCore.Blazor" Version="1.2.1" />
|
||||||
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
|
<PackageReference Include="MoonCore.PluginFramework" Version="1.0.0" />
|
||||||
<PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.0.6" />
|
<PackageReference Include="MoonCore.Blazor.Tailwind" Version="1.0.6" />
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ using Moonlight.Client.Interfaces;
|
|||||||
using Moonlight.Client.Services;
|
using Moonlight.Client.Services;
|
||||||
using Moonlight.Client.UI;
|
using Moonlight.Client.UI;
|
||||||
using Moonlight.Shared.Http.Requests.Auth;
|
using Moonlight.Shared.Http.Requests.Auth;
|
||||||
|
using Moonlight.Shared.Http.Responses.Auth;
|
||||||
|
|
||||||
// Build pre run logger
|
// Build pre run logger
|
||||||
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
|
var providers = LoggerBuildHelper.BuildFromConfiguration(configuration =>
|
||||||
@@ -70,13 +71,19 @@ builder.Services.AddScoped(sp =>
|
|||||||
DateTimeOffset.FromUnixTimeSeconds(long.Parse(await cookieService.GetValue("kms-timestamp", "0"))).UtcDateTime,
|
DateTimeOffset.FromUnixTimeSeconds(long.Parse(await cookieService.GetValue("kms-timestamp", "0"))).UtcDateTime,
|
||||||
async refreshToken =>
|
async refreshToken =>
|
||||||
{
|
{
|
||||||
await httpClient.PostAsync("api/auth/refresh", new StringContent(
|
var response = await httpClient.PostAsync("api/auth/refresh", new StringContent(
|
||||||
JsonSerializer.Serialize(new RefreshRequest()
|
JsonSerializer.Serialize(new RefreshRequest()
|
||||||
{
|
{
|
||||||
RefreshToken = refreshToken
|
RefreshToken = refreshToken
|
||||||
}), new MediaTypeHeaderValue("application/json")
|
}), new MediaTypeHeaderValue("application/json")
|
||||||
));
|
));
|
||||||
|
|
||||||
|
var refreshRes = await response.ParseAsJson<RefreshResponse>();
|
||||||
|
|
||||||
|
await cookieService.SetValue("kms-access", refreshRes.AccessToken, 10);
|
||||||
|
await cookieService.SetValue("kms-refresh", refreshRes.RefreshToken, 10);
|
||||||
|
await cookieService.SetValue("kms-timestamp", DateTimeOffset.UtcNow.AddSeconds(60).ToUnixTimeSeconds().ToString(), 10);
|
||||||
|
|
||||||
return new TokenPair()
|
return new TokenPair()
|
||||||
{
|
{
|
||||||
AccessToken = await cookieService.GetValue("kms-access", "x"),
|
AccessToken = await cookieService.GetValue("kms-access", "x"),
|
||||||
|
|||||||
Reference in New Issue
Block a user