read

A couple years ago I was working on a Laravel API that had social authentication features. I was using the laravel/socialite package to handle these authentication features, but ran into issues because our app was stateless. We were using JWT for handling authentication between our frontend client and our backend Laravel api, and therefore didn't have need of sessions so we had stripped it all out. At the time there was no workaround for our issue, and it results in this pull request: https://github.com/laravel/socialite/pull/68

Nowadays this is a common usecase for the socialite package and you can find a reference to the stateless() method in the Socialite documentation here: https://github.com/laravel/socialite#stateless-authentication

Ever since that time, I have recieved messages asking me questions about how to implement this functionality into Laravel and Lumen apps. There are many applications where it might be useful to have stateless functionality with Socialite. I'm going to discuss that briefly.

Two common scenarios

  1. APIs that don't use session at all, and you still want to handle social authentication on the backend (Lumen etc).
  2. You want to handle the redirect and athorization part of social authentication from your client application. For example maybe you are using Angular and you use a popular social authentication plugin like Satellizer. But maybe you still want to handle the Callback on your API side.

How it looks

Socialite makes social authentication crazy easy! I will post a few code samples below to show you what it looks like in action. For my examples I will be using Lumen and I will setup a generic endpoint that does social authentication using facebook. If you want to support multiple providers this can be easily done by passing in the provider name to your endpoint, but I'll just be hardcoding 'facebook' in my examples.

Note: Please keep in mind that you will still need to implement an authenticaiton system to send to send a token to a client or something after you successfully authenticate using Socialite. The code samples below show the social authentication portion, but you will still need to implement JWT, Oauth (passport) or some other authentication method. If there is some interest I can add a guide for this as well.

/**
 * Redirect the user to the Facebook authentication page.
 *
 * @return Response
 */
public function redirectToProvider()
{
    return Socialite::driver('facebook')->stateless()->redirect();
}

The redirect method looks VERY simple. I think in many scenarios this method is optional. I've seen many implementations where the "redirect to provider" functionality is provided the front end client application. However I like to have my frontend client apps call this backend endpoint to start the authorization process. just don't forget to include the "stateless()" function.

/**
 * Obtain the user information from Facebook.
 *
 * @return JsonResponse
 */
public function handleProviderCallback()
{
    // this user we get back is not our user model, but a special user object that has all the information we need
    $providerUser = Socialite::driver('facebook')->stateless()->user();

    // we have successfully authenticated via facebook at this point and can use the provider user to log us in.

    // for example we might do something like... Check if a user exists with the email and if so, log them in.
    $user = User::query()->firstOrNew(['email' => $providerUser->getEmail()]);

    // maybe we can set all the values on our user model if it is new... right now we only have name
    // but you could set other things like avatar or gender
    if (!$user->exists) {
        $user->name = $providerUser->getName();
        $user->save(); 
    }

    /**
     * At this point we done.  You can use whatever you are using for authentication here...
     * for example you might do something like this if you were using JWT
     */

    $token = JWTAuth::fromUser($user);

    return new JsonResponse([
        'token' => $token
    ]);
}

This is a very basic example and I have included some comments in my code sample to explain a few things. However the basic idea is this: When you configure your facebook integration, or integration with any other platform... you will have to setup a "callback url". Which is basically just the endpoint it hits after you successfully authorize the app. In this method we can take the provider user that socialite gives us and we can build our real user and save the information down to our database. You can then use whatever authentication you like to create a token etc and send it back to the user.

We need the stateless functionality here because our app isn't going to remember the state, and it is an optional parameter for oauth. It doesn't matter what we used to authorize as long as the callback url hits this endpoint and we use the stateless method.

Resources and Conclusion

I've setup a repo withe a basic Lumen application and Socialite integration. You can find it here: https://github.com/isaackearl/socialite-lumen-demo. Let me know if you have questions or thoughts.

Blog Logo

Isaac Earl

Web dev & whatever else


Published

Blog Comments powered by Disqus.
Image

Isaac's Blog

Ramblings of a software dev

Back to Overview