aboutsummaryrefslogtreecommitdiff
path: root/libs/VNLib.Plugins.Sessions.OAuth/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/VNLib.Plugins.Sessions.OAuth/src')
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/AccessTokenEndpoint.cs6
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/RevocationEndpoint.cs3
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/O2AuthenticationPluginEntry.cs29
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/O2SessionProviderEntry.cs81
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionProvider.cs54
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionStore.cs27
-rw-r--r--libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2TokenFactory.cs2
7 files changed, 79 insertions, 123 deletions
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/AccessTokenEndpoint.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/AccessTokenEndpoint.cs
index 77cad38..dc0530f 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/AccessTokenEndpoint.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/AccessTokenEndpoint.cs
@@ -46,7 +46,6 @@ namespace VNLib.Plugins.Sessions.OAuth.Endpoints
/// Grants authorization to OAuth2 clients to protected resources
/// with access tokens
/// </summary>
- [ConfigurationName(O2SessionProviderEntry.OAUTH2_CONFIG_KEY)]
internal sealed class AccessTokenEndpoint : ResourceEndpointBase
{
private readonly IApplicationTokenFactory TokenFactory;
@@ -60,14 +59,13 @@ namespace VNLib.Plugins.Sessions.OAuth.Endpoints
DisableSessionsRequired = true
};
- public AccessTokenEndpoint(PluginBase pbase, IConfigScope config)
+ public AccessTokenEndpoint(PluginBase pbase, IConfigScope config, IApplicationTokenFactory tokenFactory)
{
string? path = config["token_path"].GetString();;
InitPathAndLog(path, pbase.Log);
- //Get the session provider, as its a token factory
- TokenFactory = pbase.GetOrCreateSingleton<OAuth2SessionProvider>();
+ TokenFactory = tokenFactory;
Applications = new(pbase.GetContextOptions(), pbase.GetOrCreateSingleton<ManagedPasswordHashing>());
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/RevocationEndpoint.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/RevocationEndpoint.cs
index 45a8391..bdb4e4e 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/RevocationEndpoint.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/Endpoints/RevocationEndpoint.cs
@@ -46,8 +46,7 @@ namespace VNLib.Plugins.Sessions.OAuth.Endpoints
{
//Revoke the access token, by invalidating it
entity.Session.Invalidate();
- entity.CloseResponse(System.Net.HttpStatusCode.OK);
- return VfReturnType.VirtualSkip;
+ return VirtualOk(entity);
}
}
}
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/O2AuthenticationPluginEntry.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/O2AuthenticationPluginEntry.cs
index 5cd6aaf..1d74b7e 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/O2AuthenticationPluginEntry.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/O2AuthenticationPluginEntry.cs
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2022 Vaughn Nugent
+* Copyright (c) 2023 Vaughn Nugent
*
* Library: VNLib
* Package: VNLib.Plugins.Essentials.Sessions.OAuth
@@ -23,9 +23,13 @@
*/
using System;
-using System.Collections.Generic;
+
+using System.ComponentModel.Design;
using VNLib.Utils.Logging;
+using VNLib.Plugins.Attributes;
+using VNLib.Plugins.Essentials.Sessions;
+using VNLib.Plugins.Extensions.Loading;
namespace VNLib.Plugins.Sessions.OAuth
{
@@ -33,19 +37,20 @@ namespace VNLib.Plugins.Sessions.OAuth
{
public override string PluginName => "Essentials.Oauth.Authentication";
- private readonly O2SessionProviderEntry SessionProvider = new();
+ private OAuth2SessionProvider? SessionProvider;
+
+
+ [ServiceConfigurator]
+ public void OnServicesLoading(IServiceContainer services)
+ {
+ //Expose the OAuth2 session provider as a service singleton
+ services.AddService<ISessionProvider>(SessionProvider!);
+ }
protected override void OnLoad()
{
- try
- {
- //Load the session provider, that will only load the endpoints
- SessionProvider.Load(this, Log);
- }
- catch(KeyNotFoundException kne)
- {
- Log.Error("Missing required configuration keys {err}", kne.Message);
- }
+ SessionProvider = this.GetOrCreateSingleton<OAuth2SessionProvider>();
+ Log.Information("Plugin loaded");
}
protected override void OnUnLoad()
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/O2SessionProviderEntry.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/O2SessionProviderEntry.cs
deleted file mode 100644
index 0437541..0000000
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/O2SessionProviderEntry.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-* Copyright (c) 2023 Vaughn Nugent
-*
-* Library: VNLib
-* Package: VNLib.Plugins.Essentials.Sessions.OAuth
-* File: O2SessionProviderEntry.cs
-*
-* O2SessionProviderEntry.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.Threading;
-using System.Threading.Tasks;
-
-using VNLib.Net.Http;
-using VNLib.Utils.Logging;
-using VNLib.Plugins.Sessions.OAuth.Endpoints;
-using VNLib.Plugins.Essentials.Sessions;
-using VNLib.Plugins.Extensions.Loading;
-using VNLib.Plugins.Extensions.Loading.Routing;
-
-namespace VNLib.Plugins.Sessions.OAuth
-{
-
- public sealed class O2SessionProviderEntry : ISessionProvider
- {
- public const string OAUTH2_CONFIG_KEY = "oauth2";
-
- private OAuth2SessionProvider? _sessions;
-
- public bool CanProcess(IHttpEvent entity)
- {
- //If authorization header is set try to process as oauth2 session
- return _sessions != null && _sessions.IsConnected && entity.Server.Headers.HeaderSet(System.Net.HttpRequestHeader.Authorization);
- }
-
- ValueTask<SessionHandle> ISessionProvider.GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
- {
- return _sessions!.GetSessionAsync(entity, cancellationToken);
- }
-
- public void Load(PluginBase plugin, ILogProvider localized)
- {
- IConfigScope o2Config = plugin.GetConfig(OAUTH2_CONFIG_KEY);
-
- //Access token endpoint is optional
- if (o2Config.ContainsKey("token_path"))
- {
- //Create token endpoint
- plugin.Route<AccessTokenEndpoint>();
- }
-
- //Optional revocation endpoint
- if (plugin.HasConfigForType<RevocationEndpoint>())
- {
- //Route revocation endpoint
- plugin.Route<RevocationEndpoint>();
- }
-
- //Init session provider
- _sessions = plugin.GetOrCreateSingleton<OAuth2SessionProvider>();
- _sessions.SetLog(localized);
-
- localized.Information("Session provider loaded");
- }
- }
-} \ No newline at end of file
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionProvider.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionProvider.cs
index b1b97b7..99bac29 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionProvider.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionProvider.cs
@@ -5,8 +5,8 @@
* Package: VNLib.Plugins.Essentials.Sessions.OAuth
* File: OAuth2SessionProvider.cs
*
-* OAuth2SessionProvider.cs is part of VNLib.Plugins.Essentials.Sessions.OAuth which is part of the larger
-* VNLib collection of libraries and utilities.
+* OAuth2SessionProvider.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
@@ -31,7 +31,6 @@ using System.Collections.Generic;
using VNLib.Net.Http;
using VNLib.Utils;
using VNLib.Utils.Logging;
-using VNLib.Data.Caching.Exceptions;
using VNLib.Plugins.Essentials;
using VNLib.Plugins.Essentials.Sessions;
using VNLib.Plugins.Essentials.Oauth.Tokens;
@@ -39,6 +38,8 @@ using VNLib.Plugins.Essentials.Oauth.Applications;
using VNLib.Plugins.Extensions.Loading;
using VNLib.Plugins.Extensions.Loading.Sql;
using VNLib.Plugins.Extensions.Loading.Events;
+using VNLib.Plugins.Extensions.Loading.Routing;
+using VNLib.Plugins.Sessions.OAuth.Endpoints;
using static VNLib.Plugins.Essentials.Oauth.OauthSessionExtensions;
namespace VNLib.Plugins.Sessions.OAuth
@@ -47,9 +48,12 @@ namespace VNLib.Plugins.Sessions.OAuth
/// <summary>
/// Provides OAuth2 session management
/// </summary>
- [ConfigurationName(O2SessionProviderEntry.OAUTH2_CONFIG_KEY)]
- internal sealed class OAuth2SessionProvider : ISessionProvider, ITokenManager, IApplicationTokenFactory, IIntervalScheduleable
- {
+ [ExternService]
+ [ConfigurationName(OAUTH2_CONFIG_KEY)]
+ public sealed class OAuth2SessionProvider : ISessionProvider, ITokenManager, IApplicationTokenFactory, IIntervalScheduleable
+ {
+ public const string OAUTH2_CONFIG_KEY = "oauth2";
+
private static readonly SessionHandle Skip = new(null, FileProcessArgs.VirtualSkip, null);
private readonly OAuth2SessionStore _sessions;
@@ -60,8 +64,6 @@ namespace VNLib.Plugins.Sessions.OAuth
private uint _waitingConnections;
- public bool IsConnected => _sessions.IsConnected;
-
public OAuth2SessionProvider(PluginBase plugin, IConfigScope config)
{
_sessions = plugin.GetOrCreateSingleton<OAuth2SessionStore>();
@@ -71,9 +73,40 @@ namespace VNLib.Plugins.Sessions.OAuth
//Schedule interval
plugin.ScheduleInterval(this, TimeSpan.FromMinutes(2));
+
+ IConfigScope o2Config = plugin.GetConfig(OAUTH2_CONFIG_KEY);
+
+ /*
+ * Route built-in oauth2 endpoints
+ */
+ if (o2Config.ContainsKey("token_path"))
+ {
+ /*
+ * Access token endpoint requires this instance as a token manager
+ * which would cause a circular dependency, so it needs to be routed
+ * manually
+ */
+ AccessTokenEndpoint tokenEndpoint = new(plugin, o2Config, this);
+ //Create token endpoint
+ plugin.Route(tokenEndpoint);
+ }
+
+ //Optional revocation endpoint
+ if (plugin.HasConfigForType<RevocationEndpoint>())
+ {
+ //Route revocation endpoint
+ plugin.Route<RevocationEndpoint>();
+ }
}
- public void SetLog(ILogProvider log) => _sessions.SetLog(log);
+ /*
+ * Called when
+ */
+ public bool CanProcess(IHttpEvent entity)
+ {
+ //If authorization header is set try to process as oauth2 session
+ return _sessions.IsConnected && entity.Server.Headers.HeaderSet(HttpRequestHeader.Authorization);
+ }
public ValueTask<SessionHandle> GetSessionAsync(IHttpEvent entity, CancellationToken cancellationToken)
{
@@ -217,9 +250,6 @@ namespace VNLib.Plugins.Sessions.OAuth
//Remove tokens by thier object id from cache
await _sessions.DeleteTokenAsync(token.Id, cancellationToken);
}
- //Ignore if the object has already been removed
- catch (ObjectNotFoundException)
- {}
catch (Exception ex)
{
#pragma warning disable CA1508 // Avoid dead conditional code
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionStore.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionStore.cs
index 8c65bc8..6cf25c4 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionStore.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2SessionStore.cs
@@ -34,19 +34,25 @@ using VNLib.Plugins.Sessions.Cache.Client;
using VNLib.Plugins.Extensions.VNCache;
using VNLib.Plugins.Extensions.Loading;
-
namespace VNLib.Plugins.Sessions.OAuth
{
- [ConfigurationName(O2SessionProviderEntry.OAUTH2_CONFIG_KEY)]
+ [ConfigurationName(OAuth2SessionProvider.OAUTH2_CONFIG_KEY)]
internal sealed class OAuth2SessionStore : SessionStore<OAuth2Session>
{
const int MAX_SESSION_BUFFER_SIZE = 16 * 1024;
private ILogProvider _log;
+ ///<inheritdoc/>
protected override ISessionIdFactory IdFactory { get; }
+
+ ///<inheritdoc/>
protected override IRemoteCacheStore Cache { get; }
+
+ ///<inheritdoc/>
protected override ISessionFactory<OAuth2Session> SessionFactory { get; }
+
+ ///<inheritdoc/>
protected override ILogProvider Log => _log;
public bool IsConnected => Cache.IsConnected;
@@ -56,11 +62,16 @@ namespace VNLib.Plugins.Sessions.OAuth
OAuth2SessionConfig o2Conf = config.DeserialzeAndValidate<OAuth2SessionConfig>();
//Get global cache
- IGlobalCacheProvider cache = plugin.GetOrCreateSingleton<VnGlobalCache>()
+ IGlobalCacheProvider? cache = plugin.GetDefaultGlobalCache()?
.GetPrefixedCache(o2Conf.CachePrefix, HashAlg.SHA256);
- //Create remote cache
- Cache = new GlobalCacheStore(cache, MAX_SESSION_BUFFER_SIZE);
+ _ = cache ?? throw new MissingDependencyException("A global cache provider is required to store OAuth2 sessions. Please configure a cache provider");
+
+ //Get debug log if enabled
+ ILogProvider? sessDebugLog = plugin.HostArgs.HasArgument("--debug-sessions") ? plugin.Log.CreateScope("OAuth2-Sessions") : null;
+
+ //Create cache store from global cache
+ Cache = new GlobalCacheStore(cache, MAX_SESSION_BUFFER_SIZE, sessDebugLog);
IdFactory = plugin.GetOrCreateSingleton<OAuth2TokenFactory>();
@@ -70,12 +81,6 @@ namespace VNLib.Plugins.Sessions.OAuth
_log = plugin.Log;
}
- public void SetLog(ILogProvider log)
- {
- _log = log;
- }
-
-
public Task DeleteTokenAsync(string token, CancellationToken cancellation)
{
return Cache.DeleteObjectAsync(token, cancellation);
diff --git a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2TokenFactory.cs b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2TokenFactory.cs
index b452e29..b97abae 100644
--- a/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2TokenFactory.cs
+++ b/libs/VNLib.Plugins.Sessions.OAuth/src/OAuth2TokenFactory.cs
@@ -33,7 +33,7 @@ using VNLib.Plugins.Essentials.Extensions;
namespace VNLib.Plugins.Sessions.OAuth
{
- [ConfigurationName(O2SessionProviderEntry.OAUTH2_CONFIG_KEY)]
+ [ConfigurationName(OAuth2SessionProvider.OAUTH2_CONFIG_KEY)]
internal sealed class OAuth2TokenFactory : ISessionIdFactory, IOauthSessionIdFactory
{
private readonly OAuth2SessionConfig _config;