Custom Authenticator Problem

<%- if @topic_view.topic.tags.present? %>
<%= t 'js.tagging.tags' %>: <%- @topic_view.topic.tags.each do |t| %> <%= t %> <%- end %>
<% end %>

Silverstripe Version: 4.5.2

Question: I am trying to create a custom login authenticator, but Security keeps failing when looking up the authenticators - line 268 of Security\Security.php

The following exception occurs:

[Emergency] Uncaught Error: Call to a member function supportedServices() on string

GET /Security/login?BackURL=%2Fadmin%2Fdashboard%2F

Line 268 in …/vendor/silverstripe/framework/src/Security/Security.php

which is the “$authenticator->supportedServices()” line below:

public function getApplicableAuthenticators($service = Authenticator::LOGIN)
 {
     $authenticators = $this->getAuthenticators();
      /** @var Authenticator $authenticator */
      foreach ($authenticators as $name => $authenticator) {
          if (!($authenticator->supportedServices() & $service)) {
              unset($authenticators[$name]);
          }
      }

I have configured the authenticator in my config yml file, and it registers ok, but $authenticator at this stage is just a string class name. If I look at the value of $authenticator, it is simply my class name, not an instance.

What am I missing?

nakhor

Maybe you need to do Injector::inst()->create($authenticator)->supportedServices()?

Thanks. Whilst this is in a framework provided class, I am keen to track down what the issue is to either see what I’ve done wrong or provide a fix.

Doing what you suggest just pushes the problem elsewhere, namely line 699 of the same class where again it is looking at the registered authenticators and expecting them to be instances but they are string class names instead.

There seems to me to be some disconnect between what is configured in my yml:

SilverStripe\Core\Injector\Injector:
  SilverStripe\Security\Security:
    properties:
      Authenticators:
        MyAuthenticator: My\Namespace\MyAuthenticator

and what ends up in code.

I also forgot to mention I followed the example in the docs about getting two factor authentication going, although I am not trying to achieve two factor authentication (The world's most useless 2FA · GitHub linked from https://docs.silverstripe.org/en/4/developer_guides/security/authentication/).

Ok, so it helped me to track down my issue: a missing %$ in the yaml. It should’ve been:

SilverStripe\Core\Injector\Injector:
  SilverStripe\Security\Security:
    properties:
      Authenticators:
        MyAuthenticator: %$My\Namespace\MyAuthenticator

Although now I’m looking for a definition of what %$ does.