Skip to content

Use the manager

Olivier Lefebvre edited this page Dec 20, 2018 · 6 revisions

The PersistentDynamicManager<SchemeDefinition> is responsible to add, update, delete and list schemes dynamically managed. And persist changes to the underlying database.

Here a sample of how to use it in a controller:

public class AuthenticationViewModel
{
    [Required]
    public string Scheme { get; set; }

    [Required]
    public string DisplayName { get; set; }

    [Required]
    public string ClientId { get; set; }

    [Required]
    public string ClientSecret { get; set; }

    public string HandlerType { get; set; }

    public PathString CallbackPath { get; internal set; }
}


public class HomeController : Controller
{
    private readonly PersistentDynamicManager<SchemeDefinition> _manager;
    private readonly SignInManager<IdentityUser> _signInManager;

    public HomeController(PersistentDynamicManager<SchemeDefinition> manager, SignInManager<IdentityUser> signInManager)
    {
        _manager = manager ?? throw new ArgumentNullException(nameof(manager));
        _signInManager = signInManager;
    }

    // Returns an empty details view to create a scheme for a type of handler
    [Route("Create/{type}")]
    public IActionResult Create(string type)
    {
        return View(new AuthenticationViewModel
        {
            HandlerType = type
        });
    }

    // Creates a new scheme
    [HttpPost]
    [Route("Create/{type}")]
    public async Task<IActionResult> Create(AuthenticationViewModel model)
    {
        if (ModelState.IsValid)
        {
            OAuthOptions oAuthOptions;
            if (HandlerHelper.GetProviderName(model.HandlerType) == "Google")
            {
                oAuthOptions = new GoogleOptions();
            }
            else
            {
                oAuthOptions = new OAuthOptions();
            }

            oAuthOptions.ClientId = model.ClientId;
            oAuthOptions.ClientSecret = model.ClientSecret;
            oAuthOptions.CallbackPath = "/signin-" + model.Scheme;

            await _manager.AddAsync(new SchemeDefinition
            {
                Scheme = model.Scheme,
                DisplayName = model.DisplayName,
                HandlerType = _manager.ManagedHandlerType.First(t => t.Name == model.HandlerType),
                Options = oAuthOptions
            });
            return RedirectToAction("List");
        }

        return View(model);
    }

    // Returns a scheme details view to update id
    [Route("Update/{scheme}")]
    public async Task<IActionResult> Update(string scheme)
    {
        AuthenticationViewModel model;
        var definition = await _manager.FindBySchemeAsync(scheme);
        if (definition == null)
        {
            return NotFound();
        }
        else
        {
            model = new AuthenticationViewModel
            {
                Scheme = definition.Scheme,
                DisplayName = definition.DisplayName,
                HandlerType = definition.HandlerType.Name
            };

            var oAuthOptions = definition.Options as OAuthOptions; // GoogleOptions is OAuthOptions
            model.ClientId = oAuthOptions.ClientId;
            model.ClientSecret = oAuthOptions.ClientSecret;
        }

        return View(model);
    }

    // Updates a scheme
    [HttpPost]
    [Route("Update/{scheme}")]
    public async Task<IActionResult> Update(AuthenticationViewModel model)
    {
        if (ModelState.IsValid)
        {
            var definition = await _manager.FindBySchemeAsync(model.Scheme);
            if (definition == null)
            {
                return NotFound();
            }

            if (definition.Options is OAuthOptions oAuthOptions) // GoogleOptions is OAuthOptions
            {
                oAuthOptions.ClientId = model.ClientId;
                oAuthOptions.ClientSecret = model.ClientSecret;                    
            }

            definition.DisplayName = model.DisplayName;

            await _manager.UpdateAsync(definition);
        }

        return View(model);
    }

    // Deletes a scheme
    [Route("Delete/{scheme}")]
    public async Task<IActionResult> Delete(string scheme)
    {
        var definition = await _manager.FindBySchemeAsync(scheme);
        if (definition == null)
        {
            return NotFound();
        }

        await _manager.RemoveAsync(scheme);
        return RedirectToAction("List");
    }

    // Lists all schemes we can manage
    [Route("List")]
    public async Task<IActionResult> List()
    {
        var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync();

        var managedSchemes = schemes.Where(s => _manager.ManagedHandlerType.Any(h => s.HandlerType == h))
            .Select(s => s.Name);

        var definitions = managedSchemes.Select(name => _manager.FindBySchemeAsync(name).GetAwaiter().GetResult());
        return View(definitions.Select(definition => new AuthenticationViewModel
        {
            Scheme = definition.Scheme,
            DisplayName = definition.DisplayName,
            CallbackPath = definition.Options is RemoteAuthenticationOptions remote ? remote.CallbackPath : null
        }));
    }
}

Clone this wiki locally