humhub-contrib / auth-facebook

0 stars 2 forks source link

Registration failed: No token (query) or authclient (session) found! #4

Open ArchBlood opened 8 months ago

ArchBlood commented 8 months ago

As stated in https://github.com/humhub/humhub/issues/6882, we should track down the underlying issue where sometimes no token sessions are found when Login/Sign Up is done through the Facebook OAuth module.

ArchBlood commented 8 months ago

I've only successfully been able to reproduce this issue once, after that I can't anymore. 🤔

After some time I switched from using yii\authclient\clients\Facebook to using yii\authclient\OAuth2 to extend from and implemented code from the Yii2 Facebook OAuth class which I haven't seen any issues as of yet, so maybe syncing user data for existing users?

Another issue that I've found is that Facebook generates a random access token which can be from 100 to even above 255 characters, I'm currently not sure how HumHub stores these access tokens when it comes to sessions as I've not had the time to look into this more but that can also be something to look at.

We should also take into account that Facebook has also implemented a rate limiting within their API now as well.

Facebook Limited

Facebook Login Docs

ArchBlood commented 8 months ago

For being able to run checks through Facebook's side I'd also suggest we adopt the same methods in https://github.com/humhub-contrib/auth-microsoft/pull/3 in all OAuth modules if possible or required by API.

martincodeinc commented 8 months ago

It maybe is interesting to see why the yii Facebook auth when setup through the humhub config file never fails. What is the difference?

I hope we’ll find a solution .

martin

ArchBlood commented 8 months ago

It maybe is interesting to see why the yii Facebook auth when setup through the humhub config file never fails. What is the difference?

I hope we’ll find a solution .

martin

The module itself is an in between connection service that allows for more configurability through actual UI settings whereas the other requires manually editing the common.php file which if not done correctly will cause errors. It's not really important about why something works, it's why the other only works sometimes but not all the time;

I've stated a few possibilities of why this can happen in https://github.com/humhub-contrib/auth-facebook/issues/4#issuecomment-1991164874, note that this does not exclude the common.php practice provided in the Docs nor is it to discourage the use of it.

martincodeinc commented 8 months ago

Please let me know if there is anything I can help you with. thanks for taking a look at things!

Martin

ArchBlood commented 8 months ago

Currently this is what I'm using instead of the current code in the Facebook Sign-in module;

This leads me to believe that the token isn't being set right in the authentication process, @luke- would you know where the access token be temporarily stored? Normally I would have thought it would temporarily be stored in the session or user_auth table but I'm not seeing this.

<?php

namespace humhubContrib\auth\facebook\authclient;

use Yii;
use yii\authclient\OAuth2;
use yii\authclient\OAuthToken;
use yii\web\NotFoundHttpException;

/**
 * Facebook allows authentication via Facebook OAuth.
 */
class FacebookAuth extends OAuth2
{
    /**
     * @inheritdoc
     */
    public $authUrl = 'https://www.facebook.com/dialog/oauth';

    /**
     * @inheritdoc
     */
    public $tokenUrl = 'https://graph.facebook.com/oauth/access_token';

    /**
     * @inheritdoc
     */
    public $apiBaseUrl = 'https://graph.facebook.com';

    /**
     * @inheritdoc
     */
    public $scope = 'email';

    /**
     * @var array list of attribute names, which should be requested from API to initialize user attributes.
     * @since 2.0.5
     */
    public $attributeNames = [
        'name',
        'email',
    ];

    /**
     * @inheritdoc
     */
    public $autoRefreshAccessToken = false;

    /**
     * @var bool whether to automatically upgrade short-live (2 hours) access token to long-live (60 days) one, after fetching it.
     * @see exchangeToken()
     * @since 2.1.3
     */
    public $autoExchangeAccessToken = false;

    /**
     * @var string URL endpoint for the client auth code generation.
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
     * @see fetchClientAuthCode()
     * @see fetchClientAccessToken()
     * @since 2.1.3
     */
    public $clientAuthCodeUrl = 'https://graph.facebook.com/oauth/client_code';

    /**
     * @inheritdoc
     */
    protected function defaultName()
    {
        return 'facebook';
    }

    /**
     * @inheritdoc
     */
    protected function defaultTitle()
    {
        return 'Facebook';
    }

    /**
     * @inheritdoc
     */
    protected function defaultViewOptions()
    {
        return [
            'popupWidth' => 860,
            'popupHeight' => 480,
            'cssIcon' => 'fa fa-facebook',
            'buttonBackgroundColor' => '#e0492f',
        ];
    }

    /**
     * @inheritdoc
     */
    protected function initUserAttributes()
    {
        return $this->api('me', 'GET', [
            'fields' => implode(',', $this->attributeNames),
        ]);
    }

    /**
     * @inheritdoc
     */
    protected function defaultNormalizeUserAttributeMap()
    {
        return [
            'username' => 'name',
            'firstname' => function ($attributes) {
                if (!isset($attributes['name'])) {
                    return '';
                }
                $parts = mb_split(' ', $attributes['name'], 2);
                if (isset($parts[0])) {
                    return $parts[0];
                }
                return '';
            },
            'lastname' => function ($attributes) {
                if (!isset($attributes['name'])) {
                    return '';
                }
                $parts = mb_split(' ', $attributes['name'], 2);
                if (isset($parts[1])) {
                    return $parts[1];
                }
                return '';
            },
            'email' => function ($attributes) {
                if (empty($attributes['email'])) {
                    throw new NotFoundHttpException(Yii::t('AuthFacebookModule.base', 'Please add a valid email address to your Facebook account to be able to proceed.'));
                }
                return $attributes['email'];
            },
        ];
    }

    /**
     * @inheritdoc
     */
    public function applyAccessTokenToRequest($request, $accessToken)
    {
        parent::applyAccessTokenToRequest($request, $accessToken);

        $data = $request->getData();
        if (($machineId = $accessToken->getParam('machine_id')) !== null) {
            $data['machine_id'] = $machineId;
        }
        $data['appsecret_proof'] = hash_hmac('sha256', $accessToken->getToken(), $this->clientSecret);
        $request->setData($data);
    }

    /**
     * {@inheritdoc}
     */
    public function fetchAccessToken($authCode, array $params = [])
    {
        $token = parent::fetchAccessToken($authCode, $params);
        if ($this->autoExchangeAccessToken) {
            $token = $this->exchangeAccessToken($token);
        }
        return $token;
    }

    /**
     * Exchanges short-live (2 hours) access token to long-live (60 days) one.
     * Note that this method will success for already long-live token, but will not actually prolong it any further.
     * Pay attention, that this method will fail on already expired access token.
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
     * @param OAuthToken $token short-live access token.
     * @return OAuthToken long-live access token.
     * @since 2.1.3
     */
    public function exchangeAccessToken(OAuthToken $token)
    {
        $params = [
            'grant_type' => 'fb_exchange_token',
            'fb_exchange_token' => $token->getToken(),
        ];

        $request = $this->createRequest()
            ->setMethod('POST')
            ->setUrl($this->tokenUrl)
            ->setData($params);

        $this->applyClientCredentialsToRequest($request);

        $response = $this->sendRequest($request);

        $token = $this->createToken(['params' => $response]);
        $this->setAccessToken($token);

        return $token;
    }

    /**
     * Requests the authorization code for the client-specific access token.
     * This make sense for the distributed applications, which provides several Auth clients (web and mobile)
     * to avoid triggering Facebook's automated spam systems.
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
     * @see fetchClientAccessToken()
     * @param OAuthToken|null $token access token, if not set [[accessToken]] will be used.
     * @param array $params additional request params.
     * @return string client auth code.
     * @since 2.1.3
     */
    public function fetchClientAuthCode(OAuthToken $token = null, $params = [])
    {
        if ($token === null) {
            $token = $this->getAccessToken();
        }

        $params = array_merge([
            'access_token' => $token->getToken(),
            'redirect_uri' => $this->getReturnUrl(),
        ], $params);

        $request = $this->createRequest()
            ->setMethod('POST')
            ->setUrl($this->clientAuthCodeUrl)
            ->setData($params);

        $this->applyClientCredentialsToRequest($request);

        $response = $this->sendRequest($request);

        return $response['code'];
    }

    /**
     * Fetches access token from client-specific authorization code.
     * This make sense for the distributed applications, which provides several Auth clients (web and mobile)
     * to avoid triggering Facebook's automated spam systems.
     * @see https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension
     * @see fetchClientAuthCode()
     * @param string $authCode client auth code.
     * @param array $params
     * @return OAuthToken long-live client-specific access token.
     * @since 2.1.3
     */
    public function fetchClientAccessToken($authCode, array $params = [])
    {
        $params = array_merge([
            'code' => $authCode,
            'redirect_uri' => $this->getReturnUrl(),
            'client_id' => $this->clientId,
        ], $params);

        $request = $this->createRequest()
            ->setMethod('POST')
            ->setUrl($this->tokenUrl)
            ->setData($params);

        $response = $this->sendRequest($request);

        $token = $this->createToken(['params' => $response]);
        $this->setAccessToken($token);

        return $token;
    }
}
luke- commented 8 months ago

@ArchBlood I would expect, that the token is stored somewhere in the session with the AuthClient.

ArchBlood commented 8 months ago

@ArchBlood I would expect, that the token is stored somewhere in the session with the AuthClient.

I'll take another look but I'm not sure that I'm seeing anything stored in session or user_auth

luke- commented 8 months ago

Don't think its store in user_http_auth. It could also be that it is not saved at all.

In the OAuth2 workflow, we get the token back, use it directly for the REST API call to retrieve more user data and then it is no longer needed.

ArchBlood commented 8 months ago

Don't think its store in user_http_auth. It could also be that it is not saved at all.

In the OAuth2 workflow, we get the token back, use it directly for the REST API call to retrieve more user data and then it is no longer needed.

I believe that would be for the best outcome, as Facebook only requires authorization to be sent server-to-server when it comes to access tokens, the issue I'm seeing is we're either;

  1. We're not catching correctly for some OAuth clients or;
  2. We have a misconfiguration when it comes to access tokens in general

Now that I'm looking closer, other client modules also have this issue, namely the ones that extend from the yii2-authclient package, I'm not sure it's the package itself rather than our extended version of the classes.

ArchBlood commented 8 months ago

My suggestion would be to do the following;

martincodeinc commented 8 months ago

I can loosely follow your thread and i wonder why the "config version" of the facebook auth works fine. That gives me hope that there hopefully is a quick patch to get facbeook auths AND basic form auth working together.

I'll tell you a little bit about my motivation to get the FB auth working a.s.a.p.

I am in the process of migrating over 10,000 users from another website to our humhub installation. This is a difficult taks, specially because they are almost all older people ranging from 60 to over 100 years of age. For most people the standard humhub registration is too difficult on a mobile phone. The captcha, the email verification, it's all a bit much for them. We are now manually adding accounts on a daily basis with two people, sometimes over 200 per day and deep into the night. This is getting too much for us and we're still below one 1000 after a week of mailing an calling people.

But... luckily most of them have a facebook account!!

Martin

ArchBlood commented 8 months ago

@luke- I believe I've found that user_http_session would be where the tokens are stored, but they're under the id column, we should think about making it so that OAuth modules store the access token under user_auth directly.

user_http_session

user_auth

luke- commented 8 months ago

Hmm not sure it's the token stored here....

ArchBlood commented 8 months ago

Hmm not sure it's the token stored here....

No, but it is the token used regardless of login status, this means that the access token isn't stored at all nor can be refreshed for new access tokens. The suggestion was to fix this by adding a column to user_auth for this specific issue.

luke- commented 8 months ago

The token is only required during the login process in order to retrieve further information about the user via the API.

After that, the token or refresh token is no longer required. Since no more API requests are performed.

ArchBlood commented 8 months ago

The token is only required during the login process in order to retrieve further information about the user via the API.

After that, the token or refresh token is no longer required. Since no more API requests are performed.

Correct, but this issue isn't related to the login process to be specific, rather the registration process, where either the token, OAuth client or both are causing the issue that is why I suggested the following in https://github.com/humhub-contrib/auth-facebook/issues/4#issuecomment-1994218770.

ArchBlood commented 8 months ago

The only other idea that I can come up with is setting up a function that implements registration session handling through the Facebook client.

Example

    /**
     * Handles session when registering through Facebook.
     * Saves user attributes to session for later use during registration process.
     *
     * @param array $attributes User attributes obtained from Facebook
     */
    protected function handleSession($attributes)
    {
        // Save user attributes to session for later use
        Yii::$app->session->set('facebookUserAttributes', $attributes);
    }

    /**
     * Retrieves user attributes stored in session.
     *
     * @return array|null User attributes if found, null otherwise
     */
    protected function getSessionAttributes()
    {
        return Yii::$app->session->get('facebookUserAttributes');
    }
martincodeinc commented 7 months ago

I'm a little more hopeful now that it might work again in the near future.

ArchBlood commented 7 months ago

Well the issue is that the Session doesn't correctly append the access token during registration but login only which is an issue with all OAuth clients

I've correctly done so with the Discord Integrations module only partly, the access token is appended only after the account is connected, I don't think I can fix this from the OAuth client side of things without actually being able to append access tokens to a session.

martincodeinc commented 7 months ago

Thank you for all the research and your time! Is this something that can be fixed on a short term?

Thanks and kind regards, Martin.

ArchBlood commented 7 months ago

Thank you for all the research and your time! Is this something that can be fixed on a short term?

Thanks and kind regards, Martin.

I can look into a patch for both this module and the core registration process but I'm currently working on other things as well that are of higher priority.

martincodeinc commented 7 months ago

I understand. Thank you for your consideration. I personally do hope that a patch (or do-it-yourself php instructions) can be provided eventually. If you find the time. Thanks again and i'll keep an eye on this repository.

Martin

ArchBlood commented 7 months ago

So I've made a few breakthroughs of sorts with this issue @luke-, I'll continue working on this as soon as I can;

From what I can say is we need to implement this but also a onSuccess($token) which checks for existing users by email.

    /**
     * @inheritdoc
     */
    protected function defaultStateStorage(): StateStorageInterface
    {
        // Use the session state storage for CSRF protection
        return Yii::$app->session;
    }

Implementing the above will connect the OAuth client account with the existing account but will throw the "Registration failed." error and give the warning message "Registration failed: No token (query) or authclient (session) found!", but I can confirm that the account connection is made correctly, so we need to fix the RegistrationController function handleAuthClientRegistration().

ArchBlood commented 6 months ago

@luke- I believe I've found a fix for the RegistrationController which allows for account creation and connection, these changes seem to allow for user's to register with an authclient as well as login with them, would you like a P/R for these changes?

actionIndex()

    /**
     * Registration Form
     *
     * @throws HttpException
     * @throws Exception
     */
    public function actionIndex()
    {
        $registration = new Registration();

        /**
         * @var BaseClient
         */
        $authClient = null;

        if (Yii::$app->request->get('token')) {
            $inviteRegistrationService = new InviteRegistrationService(Yii::$app->request->get('token'));
            if (!$inviteRegistrationService->isValid()) {
                throw new HttpException(404, 'Invalid registration token!');
            }
            $inviteRegistrationService->populateRegistration($registration);
        } elseif (Yii::$app->session->has('authClient')) {
            $authClient = Yii::$app->session->get('authClient');
            $this->handleAuthClientRegistration($authClient, $registration);
        }

        if ($registration->submitted('save') && $registration->validate()) {
            $existingUser = User::findIdentity($registration->getUser()->email);

            if ($existingUser) {
                // Log in the existing user
                Yii::$app->user->login($existingUser);

                if (Yii::$app->request->getIsAjax()) {
                    return $this->htmlRedirect(Yii::$app->user->returnUrl);
                }
                return $this->redirect(Yii::$app->user->returnUrl);
            }

            // Proceed with the registration process
            if ($registration->register($authClient)) {
                Yii::$app->session->remove('authClient');

                // Autologin when user is enabled (no approval required)
                if ($registration->getUser()->status === User::STATUS_ENABLED) {
                    // Log in the user
                    Yii::$app->user->login($registration->getUser());

                    if (Yii::$app->request->getIsAjax()) {
                        return $this->htmlRedirect(Yii::$app->user->returnUrl);
                    }
                    return $this->redirect(Yii::$app->user->returnUrl);
                }

                // If user requires approval, render success page
                return $this->render('success', [
                    'form' => $registration,
                    'needApproval' => ($registration->getUser()->status === User::STATUS_NEED_APPROVAL),
                ]);
            }
        }

        return $this->render('index', [
            'hForm' => $registration,
            'showRegistrationForm' => $this->module->showRegistrationForm,
            'hasAuthClient' => $authClient !== null,
        ]);
    }

handleAuthClientRegistration()

    /**
     * Handles registration using attributes from the authentication client.
     *
     * @param ClientInterface $authClient The authentication client.
     * @param Registration $registration The registration data.
     * @throws \InvalidArgumentException If no user ID is provided by the auth client.
     * @throws \Exception If token or auth client is not found.
     */
    protected function handleAuthClientRegistration(ClientInterface $authClient, Registration $registration)
    {
        // Check if the necessary token or auth client is present
        if (!$this->isTokenAndAuthClientAvailable()) {
            throw new \Exception("Registration failed: No token (query) or authclient (session) found!");
        }

        $attributes = $authClient->getUserAttributes();

        if (!isset($attributes['id'])) {
            throw new \InvalidArgumentException("No user ID provided by auth client.");
        }

        $registration->enablePasswordForm = false;
        if ($authClient instanceof ApprovalBypass) {
            $registration->enableUserApproval = false;
        }

        // Do not store the 'id' attribute in the user or profile model.
        unset($attributes['id']);

        // Attempt to find the user by email
        $user = User::findOne(['email' => $attributes['email']]);

        if ($user) {
            // Existing user found, log in the user
            Yii::$app->user->login($user);
        } else {
            // User not found, proceed with registration
            $registration->getUser()->setAttributes($attributes, false);
            $registration->getProfile()->setAttributes($attributes, false);
        }
    }

isTokenAndAuthClientAvailable()

    /**
     * Checks if the necessary token or auth client is available.
     *
     * @return bool True if token or auth client is available, false otherwise.
     */
    private function isTokenAndAuthClientAvailable(): bool
    {
        // Check if the necessary token is present in the query parameters
        $token = isset($_GET['token']) ? $_GET['token'] : null;

        // Check if the necessary auth client is present in the session variables
        $authClient = isset($_SESSION['authClient']) ? $_SESSION['authClient'] : null;

        // Return true if both token and auth client are available, false otherwise
        return !empty($token) && !empty($authClient);
    }
ArchBlood commented 6 months ago

@martincodeinc can you test https://github.com/humhub/humhub/pull/7001 to see if this fixes the issue?

martincodeinc commented 5 months ago

Do i understand this correctly; that the Facebook authclient module will not work until HumHub 1.16.x ?

thanks

Martin.

luke- commented 5 months ago

@ArchBlood We need to remove these anonymous functions https://github.com/humhub-contrib/auth-facebook/blob/master/authclient/FacebookAuth.php#L35-L60

Then the AuthClient can be serialized and it should work.

ArchBlood commented 5 months ago

@ArchBlood We need to remove these anonymous functions https://github.com/humhub-contrib/auth-facebook/blob/master/authclient/FacebookAuth.php#L35-L60

Then the AuthClient can be serialized and it should work.

Would you like this done for each module?

Google

https://github.com/humhub-contrib/auth-google/blob/master/authclient/GoogleAuth.php#L33-L50

GitHub

https://github.com/humhub-contrib/auth-github/blob/master/authclient/GithubAuth.php#L34-L59

Microsoft

https://github.com/humhub-contrib/auth-microsoft/blob/main/authclient/MicrosoftAuth.php#L85-L106

Twitter

https://github.com/humhub-contrib/auth-twitter/blob/master/authclient/TwitterAuth.php#L39-L56

luke- commented 5 months ago

@ArchBlood Did this solves the problem? We may find some alternative solution for the attribute mapping.

ArchBlood commented 5 months ago

@ArchBlood Did this solves the problem? We may find some alternative solution for the attribute mapping.

Not exactly, but it provides some important information on the issue;

Removing them is advised as by default some of the attributes are already used, the issue still remains for the registration for some of the auth clients when it comes to the username attribute being used, I don't think we should make this a default option as some usernames can be different on other platforms and could cause issues when trying to register an account which is then connected to an existing account, I've tested this with the Discord auth where if the username is different from the existing user's then it tries to enforce creation of a new account with the same email, but of course, this causes a registration fail error. We should think of handling this better in the future.

luke- commented 5 months ago

We do not currently use the GitHub or Google modules on our community. I would switch to such a module and check whether I can also reproduce the error with this AuthClient.

It is important to note that the error only occurs if the registration cannot be automated (e.g. because mandatory profile fields are still missing).

ArchBlood commented 5 months ago

We do not currently use the GitHub or Google modules on our community. I would switch to such a module and check whether I can also reproduce the error with this AuthClient.

It is important to note that the error only occurs if the registration cannot be automated (e.g. because mandatory profile fields are still missing).

I've tested with the GitHub module and the same behavior happens, instead of attempting to connect an existing user with an email the user is directed to account creation.

I also get the return warnings for "Registration failed: No token (query) or authclient (session) found!" and "User object is null" so this still makes me think that the issue is the same as I stated here https://github.com/humhub/humhub/pull/7001#discussion_r1608409617

luke- commented 5 months ago

@ArchBlood I've just tested it with GitHub and it's as expected.

On a fresh HumHub install the module works fine out of the box.

However, if I set a profile field such as “title” to “Required” and “Show registration”. And delete the GitHub test user. I get the error “Registration failed...”, when the user tries to login (and register) using GitHub.

I have fixed it here as an example: https://github.com/humhub-contrib/auth-github/commit/3e31e60106f029ce4829cafa9988fbe3117dfe4d

https://github.com/humhub-contrib/auth-github/commit/3e31e60106f029ce4829cafa9988fbe3117dfe4d

ArchBlood commented 5 months ago

@ArchBlood I've just tested it with GitHub and it's as expected.

On a fresh HumHub install the module works fine out of the box.

However, if I set a profile field such as “title” to “Required” and “Show registration”. And delete the GitHub test user. I get the error “Registration failed...”, when the user tries to login (and register) using GitHub.

I have fixed it here as an example: https://github.com/humhub-contrib/auth-github/commit/3e31e60106f029ce4829cafa9988fbe3117dfe4d

https://github.com/humhub-contrib/auth-github/commit/3e31e60106f029ce4829cafa9988fbe3117dfe4d

After testing the registration process through the GitHub module I'm given the "Missing E-Mail Attribute from AuthClient." error, so in turn the same result but has a different error. I can mark off any possibility of custom fields being marked as required because I don't have any other than the default fields, no configuration modifications or core modifications either, no connection it made during the registration process at all with this.

ArchBlood commented 5 months ago

@luke- using the following will fetch the user email correctly, but again the issue is regarding the registration process which does not work;

    /**
     * @inheritdoc
     */
    protected function initUserAttributes()
    {
        $attributes = parent::initUserAttributes();

        // Fetch the primary email address
        $emails = $this->api('user/emails', 'GET');
        foreach ($emails as $email) {
            if (isset($email['primary']) && $email['primary'] && isset($email['email'])) {
                $attributes['email'] = $email['email'];
                break;
            }
        }

        if (isset($attributes['name'])) {
            $parts = mb_split(' ', $attributes['name'], 2);
            if (isset($parts[0])) {
                $attributes['firstname'] = $parts[0];
            }
            if (isset($parts[1])) {
                $attributes['lastname'] = $parts[1];
            }
        }
        return $attributes;
    }

I'd like to note that when it comes to GitHub, the API respects if the primary email is not shown so the error will popup and there are no workarounds for this that I can see. I would think that the Facebook API probably also does something similar.

I also tried using yii2's option here in the following which also doesn't seem to work correctly either for the usecase;

    /**
     * {@inheritdoc}
     */
    protected function initUserAttributes()
    {
        $attributes = $this->api('user', 'GET');

        if (empty($attributes['email'])) {
            // in case user set 'Keep my email address private' in GitHub profile, email should be retrieved via extra API request
            $scopes = explode(' ', $this->scope);
            if (in_array('user:email', $scopes, true) || in_array('user', $scopes, true)) {
                $emails = $this->api('user/emails', 'GET');
                if (!empty($emails)) {
                    foreach ($emails as $email) {
                        if ($email['primary'] == 1 && $email['verified'] == 1) {
                            $attributes['email'] = $email['email'];
                            break;
                        }
                    }
                }
            }
        }

        return $attributes;
    }
luke- commented 5 months ago

@ArchBlood I've just tested it with GitHub and it's as expected. On a fresh HumHub install the module works fine out of the box. However, if I set a profile field such as “title” to “Required” and “Show registration”. And delete the GitHub test user. I get the error “Registration failed...”, when the user tries to login (and register) using GitHub. I have fixed it here as an example: humhub-contrib/auth-github@3e31e60 humhub-contrib/auth-github@3e31e60

After testing the registration process through the GitHub module I'm given the "Missing E-Mail Attribute from AuthClient." error, so in turn the same result but has a different error. I can mark off any possibility of custom fields being marked as required because I don't have any other than the default fields, no configuration modifications or core modifications either, no connection it made during the registration process at all with this.

Does the GitHub login work for you on our community.humhub.com page? I've also switched to the module here.

luke- commented 5 months ago

@ArchBlood There was indeed an incorrect scope definition.

See the change here: https://github.com/humhub-contrib/auth-github/commit/1f8eab02587f9b94fbffd332c13686fd533e688f

The login should now work. I have already installed the version on our community.

ArchBlood commented 5 months ago

@ArchBlood There was indeed an incorrect scope definition.

See the change here: humhub-contrib/auth-github@1f8eab0

The login should now work. I have already installed the version on our community.

After testing both on my own test site and on the community site the issue where registration processing still seems to try creating a new account occurs instead of automatically attempting to connect the account with an existing email; Screenshot_1

luke- commented 5 months ago

@ArchBlood Thanks for testing. There is indeed a bug with automatic mapping.

It is fixed in this PR: https://github.com/humhub/humhub/pull/7024/files

The fix has already been applied to the community.

ArchBlood commented 5 months ago

@ArchBlood Thanks for testing. There is indeed a bug with automatic mapping.

It is fixed in this PR: https://github.com/humhub/humhub/pull/7024/files

The fix has already been applied to the community.

Now the mapping is working correctly, all that's needed now is updating the modules.

vilmosnagy commented 1 month ago

Any news on this? I'd like to set up a sign in with Google in my Humhub instance (1.16.1, with the mriedmann/humhub docker image), but I got the same error:

Registration failed: No token (query) or authclient (session) found!

Any idea how to solve this? Thanks,
Vilmos

edit: I cannot even register on the https://community.humhub.com/ with a Google account, seemingly with the same error :\

andreasmuellergin commented 2 weeks ago

Hey @vilmosnagy and everyone who is experiencing this issue, i want to share my way to getting it work, for you to skip the trial and error i have been through. Turns out that it started working as soon as i ignored the module configuration but instead configured the module through the common.php 'authClientCollection' => [ 'clients' => [ // ... 'facebook' => [ 'class' => 'humhub\modules\user\authclient\Facebook', 'clientId' => 'Your Client ID here', 'clientSecret' => 'Your Client Secret here', 'returnUrl' => 'Your Return URL here', ], ], ], Hope it was not obvious for everyone already and can help someone save some time.