sahat / satellizer

Token-based AngularJS Authentication
https://satellizer-sahat.rhcloud.com
MIT License
7.86k stars 1.13k forks source link

[PHP] Laravel improvements #462

Open barryvdh opened 9 years ago

barryvdh commented 9 years ago

Thanks for this project! Here are some improvements for Laravel. If you want I can PR them:

For OAuth2, it's something like this for every provider:

public function provider(Request $request, $name)
{
    if ($request->has('redirectUri')) {
        config()->set("services.{$name}.redirect", $request->get('redirectUri'));
    }        

    $provider = \Socialite::driver($name);
    $provider->stateless();

    try {
        /** @var AbstractUser $profile */
        $profile = $provider->user();
    } catch (ClientException $e) {
        return response()->json(['message' => (string) $e->getResponse()->getBody()], 500);
    }

    $user->$name = $profile->getId();
    $user->name = $profile->getName();
    $user->avatar = $profile->getAvatar();
    $user->email = $profile->getEmail();
    $user->save();

    return response()->json(['token' => $this->createToken($user)]);
}

OAuth1 is a bit different, but can get the same Profile information:

    $provider = \Socialite::driver($name);

    // Part 1 of 2: Initial request from Satellizer.
    if ( ! $request->input('oauth_token') || ! $request->input('oauth_verifier')) {
        // Redirect to fill the session (without actually redirecting)
        $provider->redirect();

        /** @var TemporaryCredentials $temp */
        $credentials = $request->getSession()->get('oauth.temp');

        return response()->json(['oauth_token' => $credentials->getIdentifier()]);
    }
    // Part 2 of 2: Second request after Authorize app is clicked.
    else
    {
        $credentials = new TemporaryCredentials();
        $credentials->setIdentifier($request->input('oauth_token'));
        $request->getSession()->set('oauth.temp', $credentials);

        try {
            /** @var AbstractUser $profile */
            $profile = $provider->user();
        } catch (ClientException $e) {
            return response()->json(['message' => (string) $e->getResponse()->getBody()], 500);
        }
    }

This will make it a lot simpler to add more drivers :)

Common pitfalls:

sahat commented 9 years ago

:+1: for the first suggestion. I am not too familiar with Laravel's Authenticate middleware, so I did what I could in order to get the User object after successful authentication.

I don't like the idea of using a 3rd-party library to abstract away all implementation details of oauth providers in this specific case. The only reason I was able to write so many backend examples, when I am only comfortable with Node.js, is because the flow is exactly the same, regardless of which language or server-side framework you are using. Another advantage is that it could be used as a learning resource, because it isn't a black box like passport.js, omniauth, socialite.

There used to be a .htaccess that fixed the CORS problem, but I guess it was nuked during Laravel 4 to Laravel 5 conversion. I'll see if I can revert it back.

barryvdh commented 9 years ago

I understand about the 'black box' thing, but isn't that pretty much the same for users using sattelizer? If they wanted to do the whole process manually, they wouldn't need to use sattelizer ;)

sahat commented 9 years ago

I see your point. Both arguments are valid, in one case it is explicit and easy to understand, in another case it is short & simple and "don't care how it works,I just want it to work".

I'll think about it, meanwhile I would appreciate that PR for the new Laravel middleware.

syropian commented 9 years ago

@barryvdh I'd love to see an example of Socialite and JWT playing nice together with something like GitHub authentication.

barryvdh commented 9 years ago

I'll see if I can put up an example or blog post about it soon :)

syropian commented 9 years ago

@barryvdh That'd be amazing! Thanks :)

aligajani commented 9 years ago

@barryvdh Thanks +1, by the way, with this method, Auth::check() or Auth::user() doesn't work. How can I make JWT play nicely with Laravel, and if you can guide us more on the Socialite integration, I'd be grateful :)

barooney commented 9 years ago

You may have a look at this tutorial, which shows the use of JWTs within Laravel and Angular: https://scotch.io/tutorials/token-based-authentication-for-angularjs-and-laravel-apps

I forked the repository from @chenkie and added Socialite support to it: https://github.com/barooney/jot-bot/

Maybe you want to have a look at it, @barryvdh.

barryvdh commented 9 years ago

Can you check out http://barryvdh.nl/laravel/lumen/angular/2015/07/19/oauth-in-javascript-apps-with-angular-lumen-using-satellizer-laravel-socialite/ ?

I've written about these changes. Let me know if something is unclear, so I'll fix it before I announce it ;)

aligajani commented 9 years ago

Barry , thanks. I was looking for using Socialite with Satellizer! By the way, Lumen and Laravel setup should be similar right ?

On Sunday, July 19, 2015, Barry vd. Heuvel notifications@github.com wrote:

Can you check out http://barryvdh.nl/laravel/lumen/angular/2015/07/19/oauth-in-javascript-apps-with-angular-lumen-using-satellizer-laravel-socialite/ ?

I've written about these changes. Let me know if something is unclear, so I'll fix it before I announce it ;)

— Reply to this email directly or view it on GitHub https://github.com/sahat/satellizer/issues/462#issuecomment-122698701.

Ali Gajani Founder at Mr. Geek www.mrgeek.me www.aligajani.com

barryvdh commented 9 years ago

Yes

asantibanez commented 9 years ago

Hi! Just started implementing Satellizer + Socialite. I am getting a server error with Socialite.

ClientException in Middleware.php line 69: Client error: 400

I am trying to implement Google authentication. Any suggestions to debug this error? Thanks in advance.

barryvdh commented 9 years ago

Catch the exception and print the response body. Something like (string) $e->getResponse()->getBody()

asantibanez commented 9 years ago

Thanks @barryvdh. Sorry about the trouble. I had my route set to "any" verb instead of only "post". This resolved the issue with Socialite on the server side.

Your article http://barryvdh.nl/laravel/lumen/angular/2015/07/19/oauth-in-javascript-apps-with-angular-lumen-using-satellizer-laravel-socialite/ is fantastic. Thanks for the help.