1

I am trying to authenticate a user via external api key request following this http://symfony.com/doc/current/cookbook/security/api_key_authentication.html#cookbook-security-api-key-config

What is ["@your_api_key_user_provider"] ? If I put something like ["test"] I get an error.

[UPDATE]

This is my ApiKeyAuthenticator.php:

// src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php

 namespace Acme\HelloBundle\Security;
 use ////

 class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
 {
protected $userProvider;

public function __construct(ApiKeyUserProvider $userProvider)
{
    $this->userProvider = $userProvider;
}

public function createToken(Request $request, $providerKey)
{
    if (!$request->query->has('apikey')) {
        throw new BadCredentialsException('No API key found');
    }

    return new PreAuthenticatedToken(
        'anon.',
        $request->query->get('apikey'),
        $providerKey
    );
}

public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
    $apiKey = $token->getCredentials();
    $username = $this->userProvider->getUsernameForApiKey($apiKey);

    if (!$username) {
        throw new AuthenticationException(
            sprintf('API Key "%s" does not exist.', $apiKey)
        );
    }

    $user = $this->userProvider->loadUserByUsername($username);

    return new PreAuthenticatedToken(
        $user,
        $apiKey,
        $providerKey,
        $user->getRoles()
    );
}

public function supportsToken(TokenInterface $token, $providerKey)
{
    return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}

}

While the user provider is this:

// src/Acme/HelloBundle/Security/ApiKeyUserProvider.php

namespace Acme\HelloBundle\Security;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

  class ApiKeyUserProvider implements UserProviderInterface
 {
public function getUsernameForApiKey($apiKey)
{
    // Look up the username based on the token in the database, via
    // an API call, or do something entirely different
    $username = ...;

    return $username;
}

public function loadUserByUsername($username)
{
    return new User(
        $username,
        null,
        // the roles for the user - you may choose to determine
        // these dynamically somehow based on the user
        array('ROLE_USER')
    );
}

public function refreshUser(UserInterface $user)
{
    // this is used for storing authentication in the session
    // but in this example, the token is sent in each request,
    // so authentication can be stateless. Throwing this exception
    // is proper to make things stateless
    throw new UnsupportedUserException();
}

public function supportsClass($class)
{
    return 'Symfony\Component\Security\Core\User\User' === $class;
}
}

The service should be just this:

services:
# ...

apikey_authenticator:
    class:     Acme\SeedBundle\Security\ApiKeyAuthenticator
    arguments: ["@ApiKeyUserProvider"]

But i got this error: The service "apikey_authenticator" has a dependency on a non-existent service "apikeyuserprovider".

Thanks

1 Answer 1

4

That is the user provider service that you should have created following this doc:

http://symfony.com/doc/current/cookbook/security/custom_provider.html

So you register your user provider as a service IE: apikey_userprovider http://symfony.com/doc/current/cookbook/security/custom_provider.html#create-a-service-for-the-user-provider

Then pass it using ["@apikey_userprovider"]

So your Services File should look like:

parameters:
    apikey_userprovider.class: Acme\HelloBundle\Security\ApiKeyUserProvider
    apikey_authenticator.class: Acme\SeedBundle\Security\ApiKeyAuthenticator
services:
    apikey_userprovider:
        class: %apikey_userprovider.class%
    apikey_authenticator:
      class: %apikey_authenticator.class%
      arguments: ["@apikey_userprovider"]

You need to define your user provider as a service. This is what the @ operator is telling symfony to look for. Defining your classes in the parameters is just part of Symfony Coding Standards

Sign up to request clarification or add additional context in comments.

3 Comments

Check my updated answer, you need to make sure you are defining your user provider as a service and calling it by the right name.
thanks! it worked! now I am trying to store the session "Storing Authentication in the Session" as described in the manual, but I get this error: Argument 1 passed to Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager::authenticate() must be an instance of Symfony\Component\Security\Core\Authentication\Token\TokenInterface, null given
Take a look at my answer to this other question that addresses storing authentication in the season stackoverflow.com/questions/5886713/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.