From 71dc81c4dcb226a7cd66c5e3007d23485367d4c0 Mon Sep 17 00:00:00 2001 From: Masu Baumgartner <68913099+Masu-Baumgartner@users.noreply.github.com> Date: Sat, 19 Oct 2024 19:27:22 +0200 Subject: [PATCH] Reorganized config. Re implemented auth controller to use token-pair authentication and oauth2 --- .../Configuration/AppConfiguration.cs | 39 ++-- .../Http/Controllers/Auth/AuthController.cs | 198 +++++++++++++----- .../Interfaces/Auth/IAuthInterceptor.cs | 9 + .../Interfaces/OAuth2/IOAuth2Provider.cs | 8 + .../Moonlight.ApiServer.csproj | 1 - Moonlight.ApiServer/Program.cs | 42 ++-- Moonlight.ApiServer/Services/AuthService.cs | 10 - .../UI/Screens/AuthenticationScreen.razor | 2 +- .../Http/Requests/Auth/LoginRequest.cs | 13 -- .../Http/Requests/Auth/OAuth2HandleRequest.cs | 9 + .../Http/Requests/Auth/RegisterRequest.cs | 19 -- .../Http/Responses/Auth/LoginResponse.cs | 6 - .../Responses/Auth/OAuth2HandleResponse.cs | 8 + ...tartResponse.cs => OAuth2StartResponse.cs} | 2 +- .../Http/Responses/Auth/RefreshResponse.cs | 8 + .../Http/Responses/Auth/RegisterResponse.cs | 6 - 16 files changed, 238 insertions(+), 142 deletions(-) create mode 100644 Moonlight.ApiServer/Interfaces/Auth/IAuthInterceptor.cs create mode 100644 Moonlight.ApiServer/Interfaces/OAuth2/IOAuth2Provider.cs delete mode 100644 Moonlight.Shared/Http/Requests/Auth/LoginRequest.cs create mode 100644 Moonlight.Shared/Http/Requests/Auth/OAuth2HandleRequest.cs delete mode 100644 Moonlight.Shared/Http/Requests/Auth/RegisterRequest.cs delete mode 100644 Moonlight.Shared/Http/Responses/Auth/LoginResponse.cs create mode 100644 Moonlight.Shared/Http/Responses/Auth/OAuth2HandleResponse.cs rename Moonlight.Shared/Http/Responses/Auth/{AuthStartResponse.cs => OAuth2StartResponse.cs} (84%) create mode 100644 Moonlight.Shared/Http/Responses/Auth/RefreshResponse.cs delete mode 100644 Moonlight.Shared/Http/Responses/Auth/RegisterResponse.cs diff --git a/Moonlight.ApiServer/Configuration/AppConfiguration.cs b/Moonlight.ApiServer/Configuration/AppConfiguration.cs index 8d5aded2..699737e7 100644 --- a/Moonlight.ApiServer/Configuration/AppConfiguration.cs +++ b/Moonlight.ApiServer/Configuration/AppConfiguration.cs @@ -23,25 +23,32 @@ public class AppConfiguration public class AuthenticationConfig { - public string MlAccessSecret { get; set; } = Formatter.GenerateString(32); - public string MlRefreshSecret { get; set; } = Formatter.GenerateString(32); - - public string Secret { get; set; } = Formatter.GenerateString(32); - - public int TokenDuration { get; set; } = 10; - - public bool UseLocalOAuth2Service { get; set; } = true; public string AccessSecret { get; set; } = Formatter.GenerateString(32); public string RefreshSecret { get; set; } = Formatter.GenerateString(32); - public string ClientId { get; set; } = Formatter.GenerateString(8); - public string ClientSecret { get; set; } = Formatter.GenerateString(32); - public string? AuthorizationUri { get; set; } - public string? AuthorizationRedirect { get; set; } - public string? AccessEndpoint { get; set; } - public string? RefreshEndpoint { get; set; } + public int AccessDuration { get; set; } = 60; + public int RefreshDuration { get; set; } = 3600; - // Local OAuth2 Service - public string CodeSecret { get; set; } = Formatter.GenerateString(32); + public OAuth2Data OAuth2 { get; set; } = new(); + public bool UseLocalOAuth2 { get; set; } = true; + + public LocalOAuth2Data LocalOAuth2 { get; set; } = new(); + + public class LocalOAuth2Data + { + public string AccessSecret { get; set; } = Formatter.GenerateString(32); + public string RefreshSecret { get; set; } = Formatter.GenerateString(32); + public string CodeSecret { get; set; } = Formatter.GenerateString(32); + } + + public class OAuth2Data + { + public string ClientId { get; set; } = Formatter.GenerateString(8); + public string ClientSecret { get; set; } = Formatter.GenerateString(32); + public string? AuthorizationUri { get; set; } + public string? AuthorizationRedirect { get; set; } + public string? AccessEndpoint { get; set; } + public string? RefreshEndpoint { get; set; } + } } public class DevelopmentConfig diff --git a/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs b/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs index fb7294e1..ceac3095 100644 --- a/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs +++ b/Moonlight.ApiServer/Http/Controllers/Auth/AuthController.cs @@ -4,11 +4,14 @@ using MoonCore.Extended.Abstractions; using MoonCore.Extended.Helpers; using MoonCore.Extended.OAuth2.ApiServer; using MoonCore.Helpers; +using MoonCore.PluginFramework.Services; using MoonCore.Services; using Moonlight.ApiServer.Attributes; using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Database.Entities; using Moonlight.ApiServer.Helpers.Authentication; +using Moonlight.ApiServer.Interfaces.Auth; +using Moonlight.ApiServer.Interfaces.OAuth2; using Moonlight.ApiServer.Services; using Moonlight.Shared.Http.Requests.Auth; using Moonlight.Shared.Http.Responses.Auth; @@ -23,100 +26,191 @@ public class AuthController : Controller private readonly TokenHelper TokenHelper; private readonly ConfigService ConfigService; private readonly DatabaseRepository UserRepository; + private readonly ImplementationService ImplementationService; - public AuthController(OAuth2Service oAuth2Service, TokenHelper tokenHelper, DatabaseRepository userRepository, ConfigService configService) + public AuthController( + OAuth2Service oAuth2Service, + TokenHelper tokenHelper, + DatabaseRepository userRepository, + ConfigService configService, + ImplementationService implementationService + ) { OAuth2Service = oAuth2Service; TokenHelper = tokenHelper; UserRepository = userRepository; ConfigService = configService; + ImplementationService = implementationService; } - [HttpGet("start")] - public async Task Start() + [HttpGet] + public async Task Start() { var data = await OAuth2Service.StartAuthorizing(); - return Mapper.Map(data); + return Mapper.Map(data); + } + + [HttpPost] + public async Task Handle([FromBody] OAuth2HandleRequest request) + { + var accessData = await OAuth2Service.RequestAccess(request.Code); + + // Find oauth2 provider + var provider = ImplementationService.Get().FirstOrDefault(); + + if (provider == null) + throw new HttpApiException("No oauth2 provider has been registered", 500); + + // Sync user from oauth2 provider + var user = await provider.Sync(HttpContext.RequestServices, accessData.AccessToken, accessData.RefreshToken); + + if (user == null) + throw new HttpApiException("The oauth2 provider was unable to authenticate you", 401); + + // Allow plugins to intercept access calls + var interceptors = ImplementationService.Get(); + + if (interceptors.Any(interceptor => !interceptor.AllowAccess(user, HttpContext.RequestServices))) + throw new HttpApiException("Unable to get access token", 401); + + // 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 == user.Id); + + userModel.AccessToken = accessData.AccessToken; + userModel.RefreshToken = accessData.RefreshToken; + userModel.RefreshTimestamp = DateTime.UtcNow.AddSeconds(accessData.ExpiresIn); + + UserRepository.Update(userModel); + + // Generate local token-pair for the authentication + // between client and the api server + + var authConfig = ConfigService.Get().Authentication; + + var tokenPair = await TokenHelper.GeneratePair( + authConfig.AccessSecret, + authConfig.AccessSecret, + data => { data.Add("userId", user.Id.ToString()); }, + authConfig.AccessDuration, + authConfig.RefreshDuration + ); + + // Authentication finished. Return data to client + + return new OAuth2HandleResponse() + { + AccessToken = tokenPair.AccessToken, + RefreshToken = tokenPair.RefreshToken, + ExpiresAt = DateTime.UtcNow.AddSeconds(authConfig.AccessDuration) + }; } [HttpPost("refresh")] - public async Task Refresh([FromBody] RefreshRequest request) + public async Task Refresh([FromBody] RefreshRequest request) { var authConfig = ConfigService.Get().Authentication; - + var tokenPair = await TokenHelper.RefreshPair( request.RefreshToken, - authConfig.MlAccessSecret, - authConfig.MlRefreshSecret, - (refreshTokenData, newTokenData) => - { - if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId)) - return false; - - var user = UserRepository.Get().FirstOrDefault(x => x.Id == userId); - - if (user == null) - return false; - - //TODO: External check - - newTokenData.Add("userId", user.Id.ToString()); - return true; - } + authConfig.AccessSecret, + authConfig.RefreshSecret, + (refreshData, newData) + => ProcessRefreshData(refreshData, newData, HttpContext.RequestServices), + authConfig.AccessDuration, + authConfig.RefreshDuration ); + // Handle refresh error if (!tokenPair.HasValue) throw new HttpApiException("Unable to refresh token", 401); - - Response.Cookies.Append("ml-access", tokenPair.Value.AccessToken); - Response.Cookies.Append("ml-refresh", tokenPair.Value.RefreshToken); - Response.Cookies.Append("ml-timestamp", DateTimeOffset.UtcNow.AddSeconds(3600).ToUnixTimeSeconds().ToString()); + + // Return data + return new RefreshResponse() + { + AccessToken = tokenPair.Value.AccessToken, + RefreshToken = tokenPair.Value.RefreshToken, + ExpiresAt = DateTime.UtcNow.AddSeconds(authConfig.AccessDuration) + }; } - [HttpGet("handle")] - public async Task Handle([FromQuery(Name = "code")] string code) + private bool ProcessRefreshData(Dictionary refreshTokenData, Dictionary newData, IServiceProvider serviceProvider) { - //TODO: Validate jwt syntax - - var accessData = await OAuth2Service.RequestAccess(code); - - //TODO: Add modular oauth2 consumer system - var userId = 1; + // Find oauth2 provider + var provider = ImplementationService.Get().FirstOrDefault(); - var user = UserRepository.Get().First(x => x.Id == userId); - - user.AccessToken = accessData.AccessToken; - user.RefreshToken = accessData.RefreshToken; - user.RefreshTimestamp = DateTime.UtcNow.AddSeconds(accessData.ExpiresIn); + if (provider == null) + throw new HttpApiException("No oauth2 provider has been registered", 500); - UserRepository.Update(user); + // Check if the userId is present in the refresh token + if (!refreshTokenData.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId)) + return false; - var authConfig = ConfigService.Get().Authentication; - var tokenPair = await TokenHelper.GeneratePair(authConfig.MlAccessSecret, authConfig.MlAccessSecret, data => + // Load user from database if existent + var user = UserRepository + .Get() + .FirstOrDefault(x => x.Id == userId); + + if (user == null) + return false; + + // Allow plugins to intercept the refresh call + var interceptors = ImplementationService.Get(); + + if (interceptors.Any(interceptor => !interceptor.AllowRefresh(user, serviceProvider))) + return false; + + // Check if it's time to resync with the oauth2 provider + if (DateTime.UtcNow >= user.RefreshTimestamp) { - data.Add("userId", user.Id.ToString()); - }); + // It's time to refresh the access to the external oauth2 provider + var refreshData = OAuth2Service.RefreshAccess(user.RefreshToken).Result; + + // Sync user with oauth2 provider + var syncedUser = provider.Sync(serviceProvider, refreshData.AccessToken, refreshData.RefreshToken).Result; + + 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); + } - Response.Cookies.Append("ml-access", tokenPair.AccessToken); - Response.Cookies.Append("ml-refresh", tokenPair.RefreshToken); - Response.Cookies.Append("ml-timestamp", DateTimeOffset.UtcNow.AddSeconds(3600).ToUnixTimeSeconds().ToString()); - - Response.Redirect("/"); + // All checks have passed, allow refresh + newData.Add("userId", user.Id.ToString()); + return true; } [HttpGet("check")] [RequirePermission("meta.authenticated")] - public async Task Check() + public Task Check() { var perm = HttpContext.User as PermClaimsPrinciple; var user = perm!.CurrentModel; - return new CheckResponse() + var response = new CheckResponse() { Email = user.Email, Username = user.Username, Permissions = perm.Permissions }; + + return Task.FromResult(response); } } \ No newline at end of file diff --git a/Moonlight.ApiServer/Interfaces/Auth/IAuthInterceptor.cs b/Moonlight.ApiServer/Interfaces/Auth/IAuthInterceptor.cs new file mode 100644 index 00000000..e2ace94f --- /dev/null +++ b/Moonlight.ApiServer/Interfaces/Auth/IAuthInterceptor.cs @@ -0,0 +1,9 @@ +using Moonlight.ApiServer.Database.Entities; + +namespace Moonlight.ApiServer.Interfaces.Auth; + +public interface IAuthInterceptor +{ + public bool AllowAccess(User user, IServiceProvider serviceProvider); + public bool AllowRefresh(User user, IServiceProvider serviceProvider); +} \ No newline at end of file diff --git a/Moonlight.ApiServer/Interfaces/OAuth2/IOAuth2Provider.cs b/Moonlight.ApiServer/Interfaces/OAuth2/IOAuth2Provider.cs new file mode 100644 index 00000000..c0ad5acb --- /dev/null +++ b/Moonlight.ApiServer/Interfaces/OAuth2/IOAuth2Provider.cs @@ -0,0 +1,8 @@ +using Moonlight.ApiServer.Database.Entities; + +namespace Moonlight.ApiServer.Interfaces.OAuth2; + +public interface IOAuth2Provider +{ + public Task Sync(IServiceProvider provider, string accessToken, string refreshToken); +} \ No newline at end of file diff --git a/Moonlight.ApiServer/Moonlight.ApiServer.csproj b/Moonlight.ApiServer/Moonlight.ApiServer.csproj index cd64af09..a3fcac0c 100644 --- a/Moonlight.ApiServer/Moonlight.ApiServer.csproj +++ b/Moonlight.ApiServer/Moonlight.ApiServer.csproj @@ -29,7 +29,6 @@ - diff --git a/Moonlight.ApiServer/Program.cs b/Moonlight.ApiServer/Program.cs index 91d8b189..0f88d774 100644 --- a/Moonlight.ApiServer/Program.cs +++ b/Moonlight.ApiServer/Program.cs @@ -7,6 +7,7 @@ using MoonCore.Extended.OAuth2.ApiServer; using MoonCore.Extensions; using MoonCore.Helpers; using MoonCore.Models; +using MoonCore.PluginFramework.Services; using MoonCore.Services; using Moonlight.ApiServer.Configuration; using Moonlight.ApiServer.Database; @@ -93,41 +94,41 @@ builder.Services.AddSingleton(); builder.Services.AddHttpClient(); builder.Services.AddOAuth2Consumer(configuration => { - configuration.ClientId = config.Authentication.ClientId; - configuration.ClientSecret = config.Authentication.ClientSecret; + configuration.ClientId = config.Authentication.OAuth2.ClientId; + configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret; configuration.AuthorizationRedirect = - config.Authentication.AuthorizationRedirect ?? $"{config.PublicUrl}/api/auth/handle"; + config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/api/auth/handle"; - configuration.AccessEndpoint = config.Authentication.AccessEndpoint ?? $"{config.PublicUrl}/oauth2/access"; - configuration.RefreshEndpoint = config.Authentication.RefreshEndpoint ?? $"{config.PublicUrl}/oauth2/refresh"; + configuration.AccessEndpoint = config.Authentication.OAuth2.AccessEndpoint ?? $"{config.PublicUrl}/oauth2/access"; + configuration.RefreshEndpoint = config.Authentication.OAuth2.RefreshEndpoint ?? $"{config.PublicUrl}/oauth2/refresh"; - if (config.Authentication.UseLocalOAuth2Service) + if (config.Authentication.UseLocalOAuth2) { - configuration.AuthorizationEndpoint = config.Authentication.AuthorizationRedirect ?? $"{config.PublicUrl}/oauth2/authorize"; + configuration.AuthorizationEndpoint = config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/oauth2/authorize"; } else { - if(config.Authentication.AuthorizationUri == null) + if(config.Authentication.OAuth2.AuthorizationUri == null) logger.LogWarning("The 'AuthorizationUri' for the oauth2 client is not set. If you want to use an external oauth2 provider, you need to specify this url. If you want to use the local oauth2 service, set 'UseLocalOAuth2Service' to true"); - configuration.AuthorizationEndpoint = config.Authentication.AuthorizationUri!; + configuration.AuthorizationEndpoint = config.Authentication.OAuth2.AuthorizationUri!; } }); -if (config.Authentication.UseLocalOAuth2Service) +if (config.Authentication.UseLocalOAuth2) { logger.LogInformation("Using local oauth2 provider"); builder.Services.AddOAuth2Provider(configuration => { - configuration.AccessSecret = config.Authentication.AccessSecret; - configuration.RefreshSecret = config.Authentication.RefreshSecret; + configuration.AccessSecret = config.Authentication.LocalOAuth2.AccessSecret; + configuration.RefreshSecret = config.Authentication.LocalOAuth2.RefreshSecret; - configuration.ClientId = config.Authentication.ClientId; - configuration.ClientSecret = config.Authentication.ClientSecret; - configuration.CodeSecret = config.Authentication.CodeSecret; + configuration.ClientId = config.Authentication.OAuth2.ClientId; + configuration.ClientSecret = config.Authentication.OAuth2.ClientSecret; + configuration.CodeSecret = config.Authentication.LocalOAuth2.CodeSecret; configuration.AuthorizationRedirect = - config.Authentication.AuthorizationRedirect ?? $"{config.PublicUrl}/api/auth/handle"; + config.Authentication.OAuth2.AuthorizationRedirect ?? $"{config.PublicUrl}/api/auth/handle"; configuration.AccessTokenDuration = 60; configuration.RefreshTokenDuration = 3600; }); @@ -135,7 +136,7 @@ if (config.Authentication.UseLocalOAuth2Service) builder.Services.AddTokenAuthentication(configuration => { - configuration.AccessSecret = config.Authentication.MlAccessSecret; + configuration.AccessSecret = config.Authentication.AccessSecret; configuration.DataLoader = async (data, provider, context) => { if (!data.TryGetValue("userId", out var userIdStr) || !int.TryParse(userIdStr, out var userId)) @@ -210,6 +211,13 @@ if (configService.Get().Development.EnableApiDocs) })); } +// Implementation service +var implementationService = new ImplementationService(); + + + +builder.Services.AddSingleton(implementationService); + var app = builder.Build(); using (var scope = app.Services.CreateScope()) diff --git a/Moonlight.ApiServer/Services/AuthService.cs b/Moonlight.ApiServer/Services/AuthService.cs index a803296e..5397727d 100644 --- a/Moonlight.ApiServer/Services/AuthService.cs +++ b/Moonlight.ApiServer/Services/AuthService.cs @@ -70,14 +70,4 @@ public class AuthService return Task.FromResult(user); } - - public async Task GenerateToken(User user) - { - var authConfig = ConfigService.Get().Authentication; - - return await JwtHelper.Create(authConfig.Secret, data => - { - data.Add("userId", user.Id.ToString()); - }, "login", TimeSpan.FromDays(authConfig.TokenDuration)); - } } \ No newline at end of file diff --git a/Moonlight.Client/UI/Screens/AuthenticationScreen.razor b/Moonlight.Client/UI/Screens/AuthenticationScreen.razor index 2626df4b..4f86a28f 100644 --- a/Moonlight.Client/UI/Screens/AuthenticationScreen.razor +++ b/Moonlight.Client/UI/Screens/AuthenticationScreen.razor @@ -12,7 +12,7 @@ { private async Task StartAuth(WButton _) { - var authStartData = await HttpApiClient.GetJson("api/auth/start"); + var authStartData = await HttpApiClient.GetJson("api/auth/start"); var uri = authStartData.Endpoint + $"?client_id={authStartData.ClientId}" + diff --git a/Moonlight.Shared/Http/Requests/Auth/LoginRequest.cs b/Moonlight.Shared/Http/Requests/Auth/LoginRequest.cs deleted file mode 100644 index 923e909b..00000000 --- a/Moonlight.Shared/Http/Requests/Auth/LoginRequest.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Moonlight.Shared.Http.Requests.Auth; - -public class LoginRequest -{ - [Required(ErrorMessage = "You need to provide an email address")] - [EmailAddress(ErrorMessage = "You need to provide a valid email address")] - public string Email { get; set; } - - [Required(ErrorMessage = "You need to provide a password")] - public string Password { get; set; } -} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Requests/Auth/OAuth2HandleRequest.cs b/Moonlight.Shared/Http/Requests/Auth/OAuth2HandleRequest.cs new file mode 100644 index 00000000..579e1a9c --- /dev/null +++ b/Moonlight.Shared/Http/Requests/Auth/OAuth2HandleRequest.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.Shared.Http.Requests.Auth; + +public class OAuth2HandleRequest +{ + [Required(ErrorMessage = "You need to provide the oauth2 code")] + public string Code { get; set; } +} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Requests/Auth/RegisterRequest.cs b/Moonlight.Shared/Http/Requests/Auth/RegisterRequest.cs deleted file mode 100644 index d84c1bea..00000000 --- a/Moonlight.Shared/Http/Requests/Auth/RegisterRequest.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Moonlight.Shared.Http.Requests.Auth; - -public class RegisterRequest -{ - [Required(ErrorMessage = "You need to provide an email address")] - [EmailAddress(ErrorMessage = "You need to provide a valid email address")] - public string Email { get; set; } - - [Required(ErrorMessage = "You need to provide a username")] - [RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers and should not start with a number")] - public string Username { get; set; } - - [Required(ErrorMessage = "You need to provide a password")] - [MinLength(8, ErrorMessage = "Your password needs to be at least 8 characters long")] - [MaxLength(256, ErrorMessage = "Your password should not exceed the length of 256 characters")] - public string Password { get; set; } -} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Responses/Auth/LoginResponse.cs b/Moonlight.Shared/Http/Responses/Auth/LoginResponse.cs deleted file mode 100644 index 1bf4a6f8..00000000 --- a/Moonlight.Shared/Http/Responses/Auth/LoginResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Moonlight.Shared.Http.Responses.Auth; - -public class LoginResponse -{ - public string Token { get; set; } -} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Responses/Auth/OAuth2HandleResponse.cs b/Moonlight.Shared/Http/Responses/Auth/OAuth2HandleResponse.cs new file mode 100644 index 00000000..67d86cdf --- /dev/null +++ b/Moonlight.Shared/Http/Responses/Auth/OAuth2HandleResponse.cs @@ -0,0 +1,8 @@ +namespace Moonlight.Shared.Http.Responses.Auth; + +public class OAuth2HandleResponse +{ + public string AccessToken { get; set; } + public string RefreshToken { get; set; } + public DateTime ExpiresAt { get; set; } +} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Responses/Auth/AuthStartResponse.cs b/Moonlight.Shared/Http/Responses/Auth/OAuth2StartResponse.cs similarity index 84% rename from Moonlight.Shared/Http/Responses/Auth/AuthStartResponse.cs rename to Moonlight.Shared/Http/Responses/Auth/OAuth2StartResponse.cs index a7be320b..7184d252 100644 --- a/Moonlight.Shared/Http/Responses/Auth/AuthStartResponse.cs +++ b/Moonlight.Shared/Http/Responses/Auth/OAuth2StartResponse.cs @@ -1,6 +1,6 @@ namespace Moonlight.Shared.Http.Responses.Auth; -public class AuthStartResponse +public class OAuth2StartResponse { public string Endpoint { get; set; } public string ClientId { get; set; } diff --git a/Moonlight.Shared/Http/Responses/Auth/RefreshResponse.cs b/Moonlight.Shared/Http/Responses/Auth/RefreshResponse.cs new file mode 100644 index 00000000..28125006 --- /dev/null +++ b/Moonlight.Shared/Http/Responses/Auth/RefreshResponse.cs @@ -0,0 +1,8 @@ +namespace Moonlight.Shared.Http.Responses.Auth; + +public class RefreshResponse +{ + public string AccessToken { get; set; } + public string RefreshToken { get; set; } + public DateTime ExpiresAt { get; set; } +} \ No newline at end of file diff --git a/Moonlight.Shared/Http/Responses/Auth/RegisterResponse.cs b/Moonlight.Shared/Http/Responses/Auth/RegisterResponse.cs deleted file mode 100644 index 5776b73f..00000000 --- a/Moonlight.Shared/Http/Responses/Auth/RegisterResponse.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Moonlight.Shared.Http.Responses.Auth; - -public class RegisterResponse -{ - public string Token { get; set; } -} \ No newline at end of file