From 751e1a107195f0c9c98c866e8267a5a760545982 Mon Sep 17 00:00:00 2001 From: vnugent Date: Thu, 12 Jan 2023 17:47:41 -0500 Subject: Large project reorder and consolidation --- .../Endpoints/AccessTokenEndpoint.cs | 194 --------------------- .../Endpoints/RevocationEndpoint.cs | 55 ------ 2 files changed, 249 deletions(-) delete mode 100644 Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs delete mode 100644 Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs (limited to 'Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints') diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs deleted file mode 100644 index d968398..0000000 --- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/AccessTokenEndpoint.cs +++ /dev/null @@ -1,194 +0,0 @@ -/* -* Copyright (c) 2022 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Plugins.Essentials.Sessions.OAuth -* File: AccessTokenEndpoint.cs -* -* AccessTokenEndpoint.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Plugins.Essentials.Sessions.OAuth is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* VNLib.Plugins.Essentials.Sessions.OAuth is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - -using System; -using System.Net; -using System.Text.Json; - -using VNLib.Utils.Memory; -using VNLib.Hashing.IdentityUtility; -using VNLib.Plugins.Essentials.Oauth; -using VNLib.Plugins.Essentials.Endpoints; -using VNLib.Plugins.Essentials.Oauth.Tokens; -using VNLib.Plugins.Essentials.Oauth.Applications; -using VNLib.Plugins.Essentials.Extensions; -using VNLib.Plugins.Extensions.Loading; -using VNLib.Plugins.Extensions.Loading.Sql; -using VNLib.Plugins.Extensions.Validation; - -namespace VNLib.Plugins.Essentials.Sessions.OAuth.Endpoints -{ - delegate Task CreateTokenImpl(HttpEntity ev, UserApplication application, CancellationToken cancellation = default); - - /// - /// Grants authorization to OAuth2 clients to protected resources - /// with access tokens - /// - internal sealed class AccessTokenEndpoint : ResourceEndpointBase - { - - private readonly CreateTokenImpl CreateToken; - private readonly ApplicationStore Applications; - - private readonly Task JWTVerificationKey; - - //override protection settings to allow most connections to authenticate - protected override ProtectionSettings EndpointProtectionSettings { get; } = new() - { - DisableBrowsersOnly = true, - DisableSessionsRequired = true, - DisableVerifySessionCors = true - }; - - public AccessTokenEndpoint(string path, PluginBase pbase, CreateTokenImpl tokenStore, Task verificationKey) - { - InitPathAndLog(path, pbase.Log); - CreateToken = tokenStore; - Applications = new(pbase.GetContextOptions(), pbase.GetPasswords()); - JWTVerificationKey = verificationKey; - } - - - protected override async ValueTask PostAsync(HttpEntity entity) - { - //Check for refresh token - if (entity.RequestArgs.IsArgumentSet("grant_type", "refresh_token")) - { - //process a refresh token - } - - //See if we have an application authorized with JWT - else if (entity.RequestArgs.IsArgumentSet("grant_type", "application")) - { - if(entity.RequestArgs.TryGetNonEmptyValue("token", out string? appJwt)) - { - //Try to get and verify the app - UserApplication? app = GetApplicationFromJwt(appJwt); - - //generate token - return await GenerateTokenAsync(entity, app); - } - } - - //Check for grant_type parameter from the request body - else if (entity.RequestArgs.IsArgumentSet("grant_type", "client_credentials")) - { - //Get client id and secret (and make sure theyre not empty - if (entity.RequestArgs.TryGetNonEmptyValue("client_id", out string? clientId) && - entity.RequestArgs.TryGetNonEmptyValue("client_secret", out string? secret)) - { - - if (!ValidatorExtensions.OnlyAlphaNumRegx.IsMatch(clientId)) - { - //respond with error message - entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidRequest, "Invalid client_id"); - return VfReturnType.VirtualSkip; - } - if (!ValidatorExtensions.OnlyAlphaNumRegx.IsMatch(secret)) - { - //respond with error message - entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidRequest, "Invalid client_secret"); - return VfReturnType.VirtualSkip; - } - - //Convert the clientid and secret to lowercase - clientId = clientId.ToLower(); - secret = secret.ToLower(); - - //Convert secret to private string that is unreferrenced - using PrivateString secretPv = new(secret, false); - - //Get the application from apps store - UserApplication? app = await Applications.VerifyAppAsync(clientId, secretPv); - - return await GenerateTokenAsync(entity, app); - } - } - - entity.CloseResponseError(HttpStatusCode.BadRequest, ErrorType.InvalidClient, "Invalid grant type"); - //Default to bad request - return VfReturnType.VirtualSkip; - } - - private UserApplication? GetApplicationFromJwt(string jwtData) - { - //Not enabled - if (JWTVerificationKey?.Result == null) - { - return null; - } - - //Parse application token - using JsonWebToken jwt = JsonWebToken.Parse(jwtData); - - //verify the application jwt - if (!jwt.VerifyFromJwk(JWTVerificationKey.Result.RootElement)) - { - return null; - } - - using JsonDocument doc = jwt.GetPayload(); - - //Get expiration time - DateTimeOffset exp = doc.RootElement.GetProperty("exp").GetDateTimeOffset(); - - //Check if token is expired - return exp < DateTimeOffset.UtcNow ? null : UserApplication.FromJwtDoc(doc.RootElement); - } - - - private async Task GenerateTokenAsync(HttpEntity entity, UserApplication? app) - { - if (app == null) - { - //App was not found or the credentials do not match - entity.CloseResponseError(HttpStatusCode.UnprocessableEntity, ErrorType.InvalidClient, "The credentials are invalid or do not exist"); - return VfReturnType.VirtualSkip; - } - - IOAuth2TokenResult? result = await CreateToken(entity, app, entity.EventCancellation); - - if (result == null) - { - entity.CloseResponseError(HttpStatusCode.TooManyRequests, ErrorType.TemporarilyUnabavailable, "You have reached the maximum number of valid tokens for this application"); - return VfReturnType.VirtualSkip; - } - - //Create the new response message - OauthTokenResponseMessage tokenMessage = new() - { - AccessToken = result.AccessToken, - IdToken = result.IdentityToken, - //set expired as seconds in int form - Expires = result.ExpiresSeconds, - RefreshToken = result.RefreshToken, - TokenType = result.TokenType - }; - - //Respond with the token message - entity.CloseResponseJson(HttpStatusCode.OK, tokenMessage); - return VfReturnType.VirtualSkip; - } - } -} \ No newline at end of file diff --git a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs b/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs deleted file mode 100644 index d981f69..0000000 --- a/Libs/VNLib.Plugins.Essentials.Sessions.OAuth/Endpoints/RevocationEndpoint.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Copyright (c) 2022 Vaughn Nugent -* -* Library: VNLib -* Package: VNLib.Plugins.Essentials.Sessions.OAuth -* File: RevocationEndpoint.cs -* -* RevocationEndpoint.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger -* VNLib collection of libraries and utilities. -* -* VNLib.Plugins.Essentials.Sessions.OAuth is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* VNLib.Plugins.Essentials.Sessions.OAuth is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - -using System; -using System.Text.Json; - -using VNLib.Plugins.Essentials.Oauth; -using VNLib.Plugins.Extensions.Loading; - -namespace VNLib.Plugins.Essentials.Sessions.OAuth.Endpoints -{ - /// - /// An OAuth2 authorized endpoint for revoking the access token - /// held by the current connection - /// - [ConfigurationName("o2_revocation_endpoint")] - internal class RevocationEndpoint : O2EndpointBase - { - - public RevocationEndpoint(PluginBase pbase, IReadOnlyDictionary config) - { - string? path = config["path"].GetString(); - InitPathAndLog(path, pbase.Log); - } - - protected override VfReturnType Post(HttpEntity entity) - { - //Revoke the access token, by invalidating it - entity.Session.Invalidate(); - entity.CloseResponse(System.Net.HttpStatusCode.OK); - return VfReturnType.VirtualSkip; - } - } -} -- cgit