1
votes

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

1 Answers

4
votes

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