2
votes

I have a problem when I want to authenticate a user with WSSE from my REST API created with Symfony. I followed the guide on the site symfony wsse authentication (http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html) and have completed the tutorial (http://obtao.com/blog/2013/06/configure-wsse-on-symfony-with-fosrestbundle/) and user management is handled with FOSUserBundle.

By default, I wsse authenticates requests accessing the resource /api. So I in my security.yml

security:
    encoders:
        FOS\UserBundle\Model\UserInterface: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        wsse_secured:
            pattern:   /api/.*
            stateless: true
            wsse:      true
            anonymous : false

        #dev:
        #    pattern:  ^/(_(profiler|wdt)|css|images|js)/
        #    security: false


        main:
            pattern: ^/
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            logout:       true
            anonymous:    true

    access_control:
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN } 

And to access my resource /api/hello, I added to my request header:

Authorization: Authorization profile=”UsernameToken”
x-wsse: UsernameToken Username="foo", PasswordDigest="9/dyW92Vp+mWEbyXeblRMqTQSJc=", Nonce="MDc1MGNkZjAwMjNmZjk2YQ==", Created="2014-04-17T16:18:34Z"

But after sending the query I get an error that is returned to me:

WSSE Login failed for foo. Why? No Authentication Provider found for token of class "Acme \ UserBundle \ Security \ Authentication \ Token \ WsseUserToken".

This error message is an exception raised in my WsseListener Class:

try {
        $authToken = $this->authenticationManager->authenticate($token);
        $this->securityContext->setToken($authToken);
    return;
    } catch (AuthenticationException $failed) {
         $failedMessage = 'WSSE Login failed for '.$token->getUsername().'. Why ? '.$failed->getMessage();
         // Deny authentication with a '403 Forbidden' HTTP response
         $response = new Response();
         $response->setStatusCode(403);
         $response->setContent($failedMessage);
         $event->setResponse($response);
         return; 
    }
2

2 Answers

1
votes

Ok, I just found the problem...

In my authentificate method (WsseProvider Class), I did return nothing !

BEFORE (doesn't works):

public function authenticate(TokenInterface $token)
 {
    $user = $this->userProvider->loadUserByUsername($token->getUsername());
    if(!$user){
      throw new AuthenticationException("Bad credentials... Did you forgot your username ?");
    }
    if ($user && 
        $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) {
    }
}

AFTER(works):

    public function authenticate(TokenInterface $token)
    {
        $user = $this->userProvider->loadUserByUsername($token->getUsername());
        if(!$user){
            throw new AuthenticationException("Bad credentials... Did you forgot your username ?");
        }
        if ($user && $this->validateDigest($token->digest, $token->nonce, $token->created, $user->getPassword())) {
        $authenticatedToken = new WsseUserToken($user->getRoles());
        $authenticatedToken->setUser($user);

        return $authenticatedToken;
    }
    throw new AuthenticationException('The WSSE authentication failed.');
}

Everything is OK now !

0
votes

Make sure that the authorization header is not being stripped by apache (It strips it by default).

You can force it by adding the following line to your .htaccess file:

    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]