aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/Fido/FidoMfaProcessor.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/MFAConfig.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserEnocdedData.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecConfig.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/ClientWebAuthManager.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/ClientClaimManager.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginClaim.cs4
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginUriBuilder.cs2
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/OAuthSiteAdapter.cs3
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/OauthClientConfig.cs38
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/SocialOauthBase.cs18
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdPortalConfig.cs46
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdProviderValidator.cs70
-rw-r--r--plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdResolver.cs67
-rw-r--r--plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Auth0Portal.cs2
-rw-r--r--plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Endpoints/LoginEndpoint.cs5
17 files changed, 226 insertions, 43 deletions
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
index bda5898..618a053 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/PkiLoginEndpoint.cs
@@ -478,7 +478,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
[JsonPropertyName("failed_attempt_timeout_sec")]
public double FailedCountTimeoutSec { get; set; } = 300;
- public void Validate()
+ public void OnValidate()
{
Validator.ValidateAndThrow(this);
}
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/Fido/FidoMfaProcessor.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/Fido/FidoMfaProcessor.cs
index 63aa46e..70bc070 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/Fido/FidoMfaProcessor.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/Fido/FidoMfaProcessor.cs
@@ -114,7 +114,7 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA.Fido
{
return new FidoDevUpgradeJson
{
- Base64UrlChallange = VnEncoding.ToBase64UrlSafeString(challenge, false),
+ Base64UrlChallange = VnEncoding.Base64UrlEncode(challenge, includePadding: false),
Timeout = conf.Timeout,
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/MFAConfig.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/MFAConfig.cs
index e44006a..7b7a73f 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/MFAConfig.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/MFAConfig.cs
@@ -95,6 +95,6 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA
public TimeSpan UpgradeValidFor { get; private set; } = TimeSpan.FromSeconds(120);
- public void Validate() => _validator.ValidateAndThrow(this);
+ public void OnValidate() => _validator.ValidateAndThrow(this);
}
}
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserEnocdedData.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserEnocdedData.cs
index 8711fb9..4ccf93a 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserEnocdedData.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/MFA/UserEnocdedData.cs
@@ -93,7 +93,7 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA
JsonSerializer.Serialize(ms, instance, Statics.SR_OPTIONS);
- store[index] = VnEncoding.ToBase64UrlSafeString(ms.AsSpan(), false);
+ store[index] = VnEncoding.Base64UrlEncode(ms.AsSpan(), false);
}
}
}
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecConfig.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecConfig.cs
index 4c80eac..512add2 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecConfig.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/AccountSecConfig.cs
@@ -190,7 +190,7 @@ namespace VNLib.Plugins.Essentials.Accounts.SecurityProvider
[JsonPropertyName("strict_user_agent")]
public bool StrictUserAgent { get; set; } = true;
- void IOnConfigValidation.Validate()
+ void IOnConfigValidation.OnValidate()
{
//Validate the current instance
_validator.ValidateAndThrow(this);
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/ClientWebAuthManager.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/ClientWebAuthManager.cs
index 2c2058d..804e486 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/ClientWebAuthManager.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/SecurityProvider/ClientWebAuthManager.cs
@@ -216,7 +216,7 @@ namespace VNLib.Plugins.Essentials.Accounts.SecurityProvider
clientToken = Convert.ToBase64String(outputBuffer[..(int)bytesEncrypted]);
//Encode base64 url safe
- serverToken = VnEncoding.ToBase64UrlSafeString(secretBuffer, false);
+ serverToken = VnEncoding.Base64UrlEncode(secretBuffer, includePadding: false);
}
finally
{
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/ClientClaimManager.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/ClientClaimManager.cs
index d078964..033f577 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/ClientClaimManager.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/ClientClaimManager.cs
@@ -120,7 +120,7 @@ namespace VNLib.Plugins.Essentials.Auth.Social
Cookies.SetCookie(entity, jwt.Compile());
//Encode and store the signing key in the clien't session
- entity.Session[SESSION_SIG_KEY_NAME] = VnEncoding.ToBase64UrlSafeString(sigKey, false);
+ entity.Session[SESSION_SIG_KEY_NAME] = VnEncoding.Base64UrlEncode(sigKey, false);
//Clear the signing key
MemoryUtil.InitializeBlock(sigKey);
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginClaim.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginClaim.cs
index 30a51fa..5d1b2dc 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginClaim.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginClaim.cs
@@ -65,11 +65,11 @@ namespace VNLib.Plugins.Essentials.Auth.Social
RandomHash.GetRandomBytes(buffer.Span);
//Base32-Encode nonce and save it
- Nonce = VnEncoding.ToBase64UrlSafeString(buffer.Span, false);
+ Nonce = VnEncoding.Base64UrlEncode(buffer.Span, includePadding: false);
}
finally
{
- MemoryUtil.InitializeBlock(buffer.Span);
+ MemoryUtil.InitializeBlock(ref buffer.GetReference(), buffer.IntLength);
}
}
}
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginUriBuilder.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginUriBuilder.cs
index 4ed6ffd..fc94d5a 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginUriBuilder.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/LoginUriBuilder.cs
@@ -96,7 +96,7 @@ namespace VNLib.Plugins.Essentials.Auth.Social
ForwardOnlyWriter<char> writer = new(charBuffer);
//Append the config redirect path
- writer.Append(Config.AccessCodeUrl.OriginalString);
+ writer.Append(Config.AuthorizationUrl.OriginalString);
//begin query arguments
writer.AppendSmall("&client_id=");
writer.Append(Config.ClientID.Value);
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OAuthSiteAdapter.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OAuthSiteAdapter.cs
index 37dd7e0..ef90185 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OAuthSiteAdapter.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OAuthSiteAdapter.cs
@@ -22,6 +22,7 @@
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
+using System;
using System.Net;
using System.Text;
using System.Threading;
@@ -49,7 +50,7 @@ namespace VNLib.Plugins.Essentials.Auth.Social
{
RestClientOptions poolOptions = new()
{
- MaxTimeout = 5000,
+ Timeout = TimeSpan.FromSeconds(5),
AutomaticDecompression = DecompressionMethods.All,
Encoding = Encoding.UTF8,
//disable redirects, api should not redirect
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OauthClientConfig.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OauthClientConfig.cs
index a3b43ad..7efd4df 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OauthClientConfig.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/OauthClientConfig.cs
@@ -29,6 +29,8 @@ using System.Collections.Generic;
using VNLib.Utils.Logging;
using VNLib.Utils.Extensions;
using VNLib.Plugins.Extensions.Loading;
+using VNLib.Plugins.Essentials.Auth.Social.openid;
+using VNLib.Plugins.Extensions.Loading.Configuration;
namespace VNLib.Plugins.Essentials.Auth.Social
{
@@ -42,25 +44,25 @@ namespace VNLib.Plugins.Essentials.Auth.Social
public OauthClientConfig(PluginBase plugin, IConfigScope config)
{
- EndpointPath = config["path"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'path' in config {config.ScopeName}");
-
- //Set discord account origin
- AccountOrigin = config["account_origin"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'account_origin' in config {config.ScopeName}");
-
- //Get the auth and token urls
- string authUrl = config["authorization_url"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'authorization_url' in config {config.ScopeName}");
- string tokenUrl = config["token_url"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'token_url' in config {config.ScopeName}");
- string userUrl = config["user_data_url"].GetString() ?? throw new KeyNotFoundException($"Missing required key 'user_data_url' in config {config.ScopeName}");
+ EndpointPath = config.GetRequiredProperty("path", p => p.GetString()!);
+ AccountOrigin = config.GetRequiredProperty("account_origin", p => p.GetString()!);
+
+ OpenIdPortalConfig portalConf = config.Deserialze<OpenIdPortalConfig>()!;
+
+ Validate.NotNull(portalConf.AuthorizationEndpoint, $"Missing authorization endpoint for {config.ScopeName}");
+ Validate.NotNull(portalConf.TokenEndpoint, $"Missing token endpoint for {config.ScopeName}");
+ Validate.NotNull(portalConf.UserDataEndpoint, $"Missing user-data endpoint for {config.ScopeName}");
+
//Create the uris
- AccessCodeUrl = new(authUrl);
- AccessTokenUrl = new(tokenUrl);
- UserDataUrl = new(userUrl);
+ AuthorizationUrl = new(portalConf.AuthorizationEndpoint);
+ AccessTokenUrl = new(portalConf.TokenEndpoint);
+ UserDataUrl = new(portalConf.UserDataEndpoint);
- AllowForLocalAccounts = config["allow_for_local"].GetBoolean();
- AllowRegistration = config["allow_registration"].GetBoolean();
- NonceByteSize = config["nonce_size"].GetUInt32();
- RandomPasswordSize = config["password_size"].GetInt32();
- InitClaimValidFor = config["claim_valid_for_sec"].GetTimeSpan(TimeParseType.Seconds);
+ AllowForLocalAccounts = config.GetValueOrDefault("allow_for_local", p => p.GetBoolean(), false);
+ AllowRegistration = config.GetValueOrDefault("allow_registration", p => p.GetBoolean(), false);
+ NonceByteSize = config.GetRequiredProperty("nonce_size", p => p.GetUInt32());
+ RandomPasswordSize = config.GetRequiredProperty("password_size", p => p.GetInt32());
+ InitClaimValidFor = config.GetRequiredProperty("claim_valid_for_sec", p => p.GetTimeSpan(TimeParseType.Seconds));
//Setup async lazy loaders for secrets
ClientID = plugin.GetSecretAsync($"{config.ScopeName}_client_id")
@@ -101,7 +103,7 @@ namespace VNLib.Plugins.Essentials.Auth.Social
/// The URL to redirect the user to the OAuth2 service
/// to begin the authentication process
/// </summary>
- public Uri AccessCodeUrl { get; }
+ public Uri AuthorizationUrl { get; }
/// <summary>
/// The remote endoint to exchange codes for access tokens
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/SocialOauthBase.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/SocialOauthBase.cs
index 91bf147..f381fb8 100644
--- a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/SocialOauthBase.cs
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/SocialOauthBase.cs
@@ -63,7 +63,11 @@ namespace VNLib.Plugins.Essentials.Auth.Social
const string AUTH_GRANT_SESSION_NAME = "auth";
const string SESSION_TOKEN_KEY_NAME = "soa.tkn";
const string CLAIM_COOKIE_NAME = "extern-claim";
-
+
+ private static readonly IValidator<LoginClaim> ClaimValidator = GetClaimValidator();
+ private static readonly IValidator<string> NonceValidator = GetNonceValidator();
+ private static readonly AccountDataValidator AccountDataValidator = new ();
+
/// <summary>
/// The client configuration struct passed during base class construction
@@ -81,19 +85,13 @@ namespace VNLib.Plugins.Essentials.Auth.Social
/// <summary>
/// The user manager used to create and manage user accounts
/// </summary>
- protected IUserManager Users { get; }
-
- private readonly IValidator<LoginClaim> ClaimValidator;
- private readonly IValidator<string> NonceValidator;
- private readonly IValidator<AccountData> AccountDataValidator;
+ protected IUserManager Users { get; }
+
+
private readonly ClientClaimManager _claims;
protected SocialOauthBase(PluginBase plugin, IConfigScope config)
{
- ClaimValidator = GetClaimValidator();
- NonceValidator = GetNonceValidator();
- AccountDataValidator = new AccountDataValidator();
-
//Get the configuration element for the derrived type
Config = plugin.CreateService<OauthClientConfig>(config);
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdPortalConfig.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdPortalConfig.cs
new file mode 100644
index 0000000..97736ab
--- /dev/null
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdPortalConfig.cs
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Essentials.Auth.Social
+* File: OpenIdPortalConfig.cs
+*
+* OpenIdPortalConfig.cs is part of VNLib.Plugins.Essentials.Auth.Social which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Essentials.Auth.Social 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.Auth.Social 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.Text.Json.Serialization;
+
+namespace VNLib.Plugins.Essentials.Auth.Social.openid
+{
+ public sealed class OpenIdPortalConfig
+ {
+ [JsonPropertyName("issuer")]
+ public string IssuerUrl { get; set; }
+
+ [JsonPropertyName("authorization_endpoint")]
+ public string AuthorizationEndpoint { get; set; }
+
+ [JsonPropertyName("token_endpoint")]
+ public string TokenEndpoint { get; set; }
+
+ [JsonPropertyName("userinfo_endpoint")]
+ public string UserDataEndpoint { get; set; }
+
+ [JsonPropertyName("jwks_uri")]
+ public string KeysEndpoint { get; set; }
+ }
+}
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdProviderValidator.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdProviderValidator.cs
new file mode 100644
index 0000000..bde0a88
--- /dev/null
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdProviderValidator.cs
@@ -0,0 +1,70 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Essentials.Auth.Social
+* File: OauthClientConfig.cs
+*
+* OauthClientConfig.cs is part of VNLib.Plugins.Essentials.Auth.Social which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Essentials.Auth.Social 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.Auth.Social 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 FluentValidation;
+
+namespace VNLib.Plugins.Essentials.Auth.Social.openid
+{
+ public sealed class OpenIdProviderValidator : AbstractValidator<OpenIdPortalConfig>
+ {
+ public OpenIdProviderValidator(string discoveryUrl)
+ {
+ /*
+ * Discovery url will be compared to make sure the
+ * host is on the same domain as the issuer
+ */
+ Uri discUrl = new(discoveryUrl);
+
+ RuleFor(i => i.IssuerUrl)
+ .Matches($"^{discUrl.Scheme}://{discUrl.Host}")
+ .WithMessage("Issuer must be on the same domain as the discovery url");
+
+ RuleFor(i => i.AuthorizationEndpoint)
+ .NotEmpty()
+ .WithMessage("Authorization endpoint is required")
+ .Matches($"^{discUrl.Scheme}://{discUrl.Host}")
+ .WithMessage("Authorization endpoint must be on the same domain as the discovery url");
+
+ RuleFor(i => i.TokenEndpoint)
+ .NotEmpty()
+ .WithMessage("Token endpoint is required")
+ .Matches($"^{discUrl.Scheme}://{discUrl.Host}")
+ .WithMessage("Token endpoint must be on the same domain as the discovery url");
+
+ RuleFor(i => i.UserDataEndpoint)
+ .NotEmpty()
+ .WithMessage("User data endpoint is required")
+ .Matches($"^{discUrl.Scheme}://{discUrl.Host}")
+ .WithMessage("User data endpoint must be on the same domain as the discovery url");
+
+ RuleFor(i => i.KeysEndpoint)
+ .NotEmpty()
+ .WithMessage("Keys endpoint is required")
+ .Matches($"^{discUrl.Scheme}://{discUrl.Host}")
+ .WithMessage("Keys endpoint must be on the same domain as the discovery url");
+ }
+ }
+}
diff --git a/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdResolver.cs b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdResolver.cs
new file mode 100644
index 0000000..652b622
--- /dev/null
+++ b/plugins/VNLib.Plugins.Essentials.Auth.Social/src/openid/OpenIdResolver.cs
@@ -0,0 +1,67 @@
+/*
+* Copyright (c) 2024 Vaughn Nugent
+*
+* Library: VNLib
+* Package: VNLib.Plugins.Essentials.Auth.Social
+* File: OauthClientConfig.cs
+*
+* OauthClientConfig.cs is part of VNLib.Plugins.Essentials.Auth.Social which is part of the larger
+* VNLib collection of libraries and utilities.
+*
+* VNLib.Plugins.Essentials.Auth.Social 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.Auth.Social 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.Threading.Tasks;
+using System.Threading;
+using VNLib.Net.Rest.Client.Construction;
+using RestSharp;
+
+namespace VNLib.Plugins.Essentials.Auth.Social.openid
+{
+ /// <summary>
+ /// Resolves the openid connect configuration from a discovery url
+ /// </summary>
+ public sealed class OpenIdResolver
+ {
+ private readonly RestSiteAdapterBase _defaultAdapter = RestSiteAdapterBase.CreateSimpleAdapter();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OpenIdResolver"/> class
+ /// </summary>
+ public OpenIdResolver()
+ {
+ _defaultAdapter.DefineSingleEndpoint()
+ .WithEndpoint<DiscoveryRequest>()
+ .WithMethod(Method.Get)
+ .WithUrl(m => m.DiscoUrl)
+ .WithHeader("Accept", "application/json")
+ .OnResponse((r, rr) => rr.ThrowIfError());
+ }
+
+ /// <summary>
+ /// Resolves the openid connect configuration from the discovery url
+ /// </summary>
+ /// <param name="discoveryUrl">The openid connect discovery url</param>
+ /// <param name="cancellation">A token to cancel the resolution operation</param>
+ /// <returns>A task that resolves the openid connect configuration data</returns>
+ public Task<OpenIdPortalConfig?> ResolveAsync(string discoveryUrl, CancellationToken cancellation)
+ {
+ return _defaultAdapter.ExecuteAsync(entity: new DiscoveryRequest(discoveryUrl), cancellation)
+ .AsJson<OpenIdPortalConfig>();
+ }
+
+ sealed record class DiscoveryRequest(string DiscoUrl)
+ { }
+ }
+}
diff --git a/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Auth0Portal.cs b/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Auth0Portal.cs
index a698806..2f91999 100644
--- a/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Auth0Portal.cs
+++ b/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Auth0Portal.cs
@@ -30,7 +30,7 @@ using VNLib.Plugins.Essentials.Auth.Auth0.Endpoints;
namespace VNLib.Plugins.Essentials.Auth.Auth0
{
-
+
[ServiceExport]
[ConfigurationName(ConfigKey)]
public sealed class Auth0Portal(PluginBase plugin, IConfigScope config) : IOAuthProvider
diff --git a/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Endpoints/LoginEndpoint.cs b/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Endpoints/LoginEndpoint.cs
index 52be461..1937aef 100644
--- a/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Endpoints/LoginEndpoint.cs
+++ b/plugins/providers/VNLib.Plugins.Essentials.Auth.Auth0/src/Endpoints/LoginEndpoint.cs
@@ -27,7 +27,6 @@ using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
-using System.Collections.Generic;
using RestSharp;
@@ -56,7 +55,7 @@ namespace VNLib.Plugins.Essentials.Auth.Auth0.Endpoints
public LoginEndpoint(PluginBase plugin, IConfigScope config) : base(plugin, config)
{
- string keyUrl = config["key_url"].GetString() ?? throw new KeyNotFoundException("Missing Auth0 'key_url' from config");
+ string keyUrl = config.GetRequiredProperty("key_url", p => p.GetString()!);
//Define the key endpoint
SiteAdapter.DefineSingleEndpoint()
@@ -88,7 +87,7 @@ namespace VNLib.Plugins.Essentials.Auth.Auth0.Endpoints
//Create a new jwk from each key element in the response
ReadOnlyJsonWebKey[] keys = doc.RootElement.GetProperty("keys")
.EnumerateArray()
- .Select(static k => new ReadOnlyJsonWebKey(k))
+ .Select(static k => new ReadOnlyJsonWebKey(in k))
.ToArray();
Log.Debug("Found {count} Auth0 signing keys", keys.Length);