using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Options; namespace Oqtane.Infrastructure { internal class SiteAuthenticationSchemeProvider : IAuthenticationSchemeProvider { public SiteAuthenticationSchemeProvider(IOptions options) : this(options, new Dictionary(StringComparer.Ordinal)) { } public SiteAuthenticationSchemeProvider(IOptions options, IDictionary schemes) { _optionsProvider = options; _schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); _requestHandlers = new List(); foreach (var builder in _optionsProvider.Value.Schemes) { var scheme = builder.Build(); AddScheme(scheme); } } private readonly IOptions _optionsProvider; private readonly object _lock = new object(); private readonly IDictionary _schemes; private readonly List _requestHandlers; private Task GetDefaultSchemeAsync() => _optionsProvider.Value.DefaultScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultScheme) : Task.FromResult(null); public virtual Task GetDefaultAuthenticateSchemeAsync() => _optionsProvider.Value.DefaultAuthenticateScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultAuthenticateScheme) : GetDefaultSchemeAsync(); public virtual Task GetDefaultChallengeSchemeAsync() => _optionsProvider.Value.DefaultChallengeScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultChallengeScheme) : GetDefaultSchemeAsync(); public virtual Task GetDefaultForbidSchemeAsync() => _optionsProvider.Value.DefaultForbidScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultForbidScheme) : GetDefaultChallengeSchemeAsync(); public virtual Task GetDefaultSignInSchemeAsync() => _optionsProvider.Value.DefaultSignInScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultSignInScheme) : GetDefaultSchemeAsync(); public virtual Task GetDefaultSignOutSchemeAsync() => _optionsProvider.Value.DefaultSignOutScheme != null ? GetSchemeAsync(_optionsProvider.Value.DefaultSignOutScheme) : GetDefaultSignInSchemeAsync(); public virtual Task GetSchemeAsync(string name) => Task.FromResult(_schemes.ContainsKey(name) ? _schemes[name] : null); public virtual Task> GetRequestHandlerSchemesAsync() => Task.FromResult>(_requestHandlers); public virtual void AddScheme(AuthenticationScheme scheme) { if (_schemes.ContainsKey(scheme.Name)) { throw new InvalidOperationException("Scheme already exists: " + scheme.Name); } lock (_lock) { if (_schemes.ContainsKey(scheme.Name)) { throw new InvalidOperationException("Scheme already exists: " + scheme.Name); } if (typeof(IAuthenticationRequestHandler).IsAssignableFrom(scheme.HandlerType)) { _requestHandlers.Add(scheme); } _schemes[scheme.Name] = scheme; } } public virtual void RemoveScheme(string name) { if (!_schemes.ContainsKey(name)) { return; } lock (_lock) { if (_schemes.ContainsKey(name)) { var scheme = _schemes[name]; _requestHandlers.Remove(scheme); _schemes.Remove(name); } } } public virtual Task> GetAllSchemesAsync() => Task.FromResult>(_schemes.Values); } }