HWIOAuthBundle: Symfony 6 login issue: loadUserByIdentifier(): Argument #1 ($identifier) must be of type string, null given

Q A
Bug? no
New Feature? no
Support question? yes
Version 2.0.0-BETA2

Actual Behavior

What is the actual behavior? When you call the Application Login URI (which is /connect/auth0) and correctly filled in your credentials, I got redirected to the callback url (/login/check-auth0?code=123456) the following error messages:

Uncaught PHP Exception TypeError: "HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider::loadUserByIdentifier(): Argument #1 ($identifier) must be of type string, null given, called in /vendor/hwi/oauth-bundle/src/Security/Core/User/OAuthUserProvider.php on line 43" at /vendor/hwi/oauth-bundle/src/Security/Core/User/OAuthUserProvider.php line 24
HWI\Bundle\OAuthBundle\Security\Core\User\OAuthUserProvider::loadUserByIdentifier(): Argument #1 ($identifier) must be of type string, null given, called in /vendor/hwi/oauth-bundle/src/Security/Core/User/OAuthUserProvider.php on line 43

Like the error is displaying, my UserResponseInterface is empty. Even when the Auth0 logs contain the Success Login and Success Exchange.

Expected Behavior

When you call the Application Login URI (which is /connect/auth0) and correctly filled in your credentials, a new OAuthUser should be created and stored by the Symfony application.

Steps to Reproduce

I’m on Symfony version 6.0 and PHP version 8.1, using hwi/oauth-bundle version 2.0.0-BETA2.

But the same error was visible in Symfony 5.2 and PHP 7.4.

This is my config/packages/security.yaml:

security:
    providers:
        hwi:
            id: hwi_oauth.user.provider
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            pattern: ^/
            oauth:
                resource_owners:
                    auth0: "/login/check-auth0"
                login_path: /login
                use_forward: false
                failure_path: /

                oauth_user_provider:
                    service: hwi_oauth.user.provider
            logout:
                path: /auth0/logout
                target: /

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/tool, roles: ROLE_OAUTH_USER }
        - { path: ^/admin, roles: ROLE_OAUTH_USER }

This is my config/packages/hwi_oauth.yaml:

hwi_oauth:
    firewall_names: [main]

    resource_owners:
        auth0:
            type: oauth2
            class: 'App\Client\Auth0ResourceOwner'
            client_id: "%env(AUTH0_CLIENT_ID)%"
            client_secret: "%env(AUTH0_CLIENT_SECRET)%"
            base_url: "https://%env(AUTH0_DOMAIN)%"
            scope: "%env(AUTH0_SCOPES)%"

This is my \App\Client\Auth0ResourceOwner:

<?php

namespace App\Client;

use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use HWI\Bundle\OAuthBundle\OAuth\ResourceOwner\GenericOAuth2ResourceOwner;

class Auth0ResourceOwner extends GenericOAuth2ResourceOwner
{
    /**
     * {@inheritdoc}
     */
    protected array $paths = [
        'identifier'     => 'user_id',
        'nickname'       => 'nickname',
        'realname'       => 'name',
        'email'          => 'email',
        'profilepicture' => 'picture',
    ];

    /**
     * {@inheritdoc}
     */
    public function getAuthorizationUrl($redirectUri, array $extraParameters = []): string
    {
        return parent::getAuthorizationUrl($redirectUri, array_merge(array(
            'authorization_url' => $this->options['authorization_url'],
            'audience' => $this->options['audience'],
        ), $extraParameters));
    }

    /**
     * {@inheritdoc}
     */
    protected function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);

        $resolver->setDefaults([
            'authorization_url' => '{base_url}/authorize',
            'access_token_url'  => '{base_url}/oauth/token',
            'infos_url'         => '{base_url}/userinfo',
            'audience'          => '{base_url}/userinfo',
            'scope'             => 'openid user profile'
        ]);

        $resolver->setRequired([
            'base_url',
        ]);

        $normalizer = function (Options $options, $value) {
            return str_replace('{base_url}', $options['base_url'], $value);
        };

        $resolver->setNormalizer('authorization_url', $normalizer);
        $resolver->setNormalizer('access_token_url', $normalizer);
        $resolver->setNormalizer('infos_url', $normalizer);
        $resolver->setNormalizer('audience', $normalizer);
    }
}

Possible Solutions

I have absolutely no idea what I’m doing wrong or which setting I forgot. This is a project that was working in August 2021, but now (April 2022) I’m dusting off. Can someone point me in the right direction to solve this login issue?

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 15

Most upvoted comments

@jasperpoppe I had the same error you have until I set the scope option to openid profile email. Also, I’m using the Auth0ResourceOwner shipped with the library.