Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

prodix's avatar

Apple login with Socialite - clears my cart session

Hi everybody!

I have an ecommerce project where I've added social login with Socialite package. For apple login i have a problem that after returning from apple login form, it clears my cart session, so the user loses the products in cart.

Because apple requires a POST callback, I've excluded the URL in VerifyToken.php. I think this is the problem because it invalidates my session after coming back to my website.

Any suggestion how i can make this work?

Thank you in advance.

0 likes
9 replies
martinbean's avatar

@prodix Can you show how you’re authorising Apple? Because Apple isn’t a built-in provider for Socialite. So it sounds like whatever solution you are using, it calling $request->session()->regenerate() or something.

Snapey's avatar

Because apple requires a POST callback, I've excluded the URL in VerifyToken.php. I think this is the problem because it invalidates my session after coming back to my website.

Yes, you would need to exclude the post back, but the issue is that this is seen as a different session to the one that initiated the authentication. Not something I have experienced, but perhaps you could pass the original session ID as part of the callback URL and then find the cart in the original session. Alternatively write the cart into cache under a key which includes the userID and then retrieve it from cache later.

prodix's avatar

thank you for taking time to give me some ideas.

@sergiu17 thanks, i'll try this.

@martinbean besides socialite, am using socialiteproviders/apple package. it's the same socialite code, basically 2 functions redirectToProvider and handleProviderCallback. The authorization works well because i receive email from apple i create the new user.

@snapey ill try more on this. i think i;ve tried to pass some variable to apple but didn't received back. i'll try to test this more.

Snapey's avatar

@prodix if you set the callback on each request it could have a user parameter either as part of 5he route, or querystring?

MN-HettigerM's avatar
Level 22

Warning: This workaround does no longer work due to changes by Apple.

See: https://github.com/SocialiteProviders/Providers/issues/1181#issuecomment-2243577153

I've created two classes to fix this:

<?php

namespace MN\SocialLogin\Apple\Socialite;

use SocialiteProviders\Apple\AppleExtendSocialite;
use SocialiteProviders\Manager\SocialiteWasCalled;

class SocialiteExtensionApple extends AppleExtendSocialite
{
    public function handle(SocialiteWasCalled $socialiteWasCalled): void
    {
        $socialiteWasCalled->extendSocialite('apple', SocialiteProviderApple::class);
    }
}
<?php

namespace MN\SocialLogin\Apple\Socialite;

use SocialiteProviders\Apple\Provider;
use Throwable;

/**
 * Custom Apple Socialite Provider that hits the callback with GET requests instead of POST requests
 *
 * The original implementation uses `response_mode=form_post` in order to support scopes.
 * Supported scopes are: `name` and `email`
 * Apple only returns the requested scopes the very first time a user authorizes the app.
 * Laravel seems to identify Apples `form_post` requests as new PHP sessions.
 * This causes all sorts of issues and introduces a lot of complexity.
 *
 * We're dropping support for scopes here in order to be able to use `response_mode=query`.
 * We still have access to the users email address every time the user authorizes the app.
 * However, we never have access to the users name. This is a tradeoff that we can accept.
 *
 * In practice this means that new users that hide their emails via iCloud Privat-Relay will
 * get weird usernames because their email addresses look something like this:
 *
 * [email protected]
 *
 * The default `SocialLoginStrategy::username` implementation would return `5zhkkwxrtt` in this case.
 *
 * @see https://laracasts.com/discuss/channels/laravel/apple-login-with-socialite-clears-my-cart-session?page=1&replyId=930156
 * @see https://developer.apple.com/documentation/sign_in_with_apple/request_an_authorization_to_the_sign_in_with_apple_server#query-parameters
 */
class SocialiteProviderApple extends Provider
{
    /**
     * {@inheritdoc}
     */
    protected $scopes = [];

    /**
     * {@inheritdoc}
     *
     * @throws Throwable
     */
    protected function getCodeFields($state = null): array
    {
        throw_if(
            count($this->scopes),
            'Scopes are not supported when using the `apple` driver. '
                .'Scopes would require us to use `response_mode=form_post` which regenerates the PHP session.',
        );

        $fields = parent::getCodeFields($state);

        unset($fields['scope']);

        $fields['response_mode'] = 'query';

        return $fields;
    }
}

Then instead of this:

protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        // ... other providers
        \SocialiteProviders\Apple\AppleExtendSocialite::class.'@handle',
    ],
];

I registered my own handler:

protected $listen = [
    \SocialiteProviders\Manager\SocialiteWasCalled::class => [
        // ... other providers
        \MN\SocialLogin\Apple\Socialite\SocialiteExtensionApple::class.'@handle',
    ],
];

Now you can also use a simple GET route for the callback. Also no need to mess with CSRF token protection etc.

Make sure to read the doc block of SocialiteProviderApple it explains what's going on. There is a tradeoff!

1 like
prodix's avatar

@mn-hettigerm thank you , its working now!

1 like
vagkaefer's avatar

Guys,

I was suffering here and made a "technical adaptation"

The "nonce" field has a uuid, I used this uuid to pass my uuid (getCodeFields function) and after I receive the post from Apple I get this uuid again (user function) and I can get the session/cookie data before the Login.

class SocialiteProviderApple extends Provider
{
	protected function getCodeFields($state = null)
    {
        [...]

        if ($this->usesState()) {
            $fields['state'] = $state;
            $userIdNonce = 'MY_UUID_IDENTIFIER_HERE' ?? Str::uuid();
            $fields['nonce'] = $userIdNonce . '.' . $state;
        }
        return array_merge($fields, $this->parameters);
    }

    public function user()
    {
        [...]

        if ($this->usesState()) {

            $state = explode('.', $appleUserToken['nonce'])[1];

            $MyUserID = explode('.', $appleUserToken['nonce'])[0];

            //Make something with that

            if ($state === $this->request->input('state')) {
            [...]
    }
   			
}

Do you believe this could be a problem? From what I understand, one of the functions of the nonce is precisely this:

nonce field: A unique, single-use string that your app provides to associate a client session with the user’s identity token. This value is also used to prevent replay attacks, and allows you to correlate the initial authentication request with the identity token provided in the authorization response.

https://developer.apple.com/documentation/sign_in_with_apple/request_an_authorization_to_the_sign_in_with_apple_server#query-parameters

1 like

Please or to participate in this conversation.