laravel5.6 passport with socialite

reference :

l5-passport : http://l5-passport.test

laravel new l5-passport --version=5.6
cd $_
sqlite3 database/database.sqlite .schema

Edit .env

# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=homestead
# DB_USERNAME=homestead
# DB_PASSWORD=secret
DB_CONNECTION=sqlite
chmod -R 777 bootstrap/cache storage
php artisan make:auth
php artisan migrate
npm install

Create first user

php artisan tinker
Psy Shell v0.8.17 (PHP 7.1.6 — cli) by Justin Hileman
>>> $user = new App\User
>>> $user->name = 'admin'
>>> $user->email = 'admin@l5-passport.test'
>>> $user->password = bcrypt('admin')
>>> $user->save()

Install passport

composer require laravel/passport
php artisan migrate
php artisan passport:install

Edit App/User.php

<?php
...
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use Notifiable;
    use HasApiTokens;
    
    ...
}

Edit App/Providers/AuthServiceProvider.php

...
use Laravel\Passport\Passport;

    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }

Edit config/auth.php

<?php
...

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

Add Quickstart Frontend

php artisan vendor:publish --tag=passport-components

Edit resources/assets/js/app.js

Vue.component('passport-clients', require('./components/passport/Clients.vue'));
Vue.component('passport-authorized-clients', require('./components/passport/AuthorizedClients.vue'));
Vue.component('passport-personal-access-tokens', require('./components/passport/PersonalAccessTokens.vue'));
npm run prod

Add routes/web.php

<?php
...

Route::get('/oauth', function () {
    return view('oauth');
})->middleware('auth')->name('oauth');

Add resources/oauth.blade.php

@extends('layouts.app')

@section('content')
    <div class="container ">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <passport-clients></passport-clients>
                <passport-authorized-clients></passport-authorized-clients>
                <passport-personal-access-tokens></passport-personal-access-tokens>
            </div>
        </div>
    </div>
@endsection

Edit resources/layouts/app.blade.php

<ul class="navbar-nav mr-auto">
    <li><a href="{{ route('oauth') }}">Passport Oauth</a></li>
</ul>

Add passport authorize view

php artisan vendor:publish --tag=passport-views

Create New Client at /oauth after login

  • Name : l5-socialite
  • Redirect URL : http://l5-socialite.test/login/l5-socialite/callback

l5-socialite : http://l5-socialite.test

laravel new l5-socialite --version=5.6
cd $_ sqlite3 database/database.sqlite .schema 

Edit .env

# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=homestead
# DB_USERNAME=homestead
# DB_PASSWORD=secret
DB_CONNECTION=sqlite
chmod -R 777 bootstrap/cache storage
php artisan make:auth
php artisan migrate

Install socialite

composer require laravel/socialite

Edit App\Http\Controller\Auth\LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use Socialite;

class LoginController extends Controller
{
    /**
     * Redirect the user to the GitHub authentication page.
     *
     * @return \Illuminate\Http\Response
     */
    public function redirectToL5Passport()
    {
        return Socialite::driver('l5-passport')->redirect();
    }

    /**
     * Obtain the user information from GitHub.
     *
     * @return \Illuminate\Http\Response
     */
    public function handleL5PassportCallback()
    {
        $user = Socialite::driver('l5-passport')->user();

        // $user->token;
    }
}

Edit routes/web.php

<?php
...
Route::get('login/l5-passport', 'Auth\LoginController@redirectTol5-passport');
Route::get('login/github/callback', 'Auth\LoginController@handleL5PassportCallback');

Add app\Socialite\L5PassportProvider.php

<?php

namespace App\Socialite;

use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;

class L5PassportProvider extends AbstractProvider implements ProviderInterface
{
    /**
     * {@inheritdoc}
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase('http://l5-passport.test/oauth/authorize', $state);
    }

    /**
     * {@inheritdoc}
     */
    protected function getTokenUrl()
    {
        return 'http://l5-passport.test/oauth/token';
    }

    /**
     * Get the POST fields for the token request.
     *
     * @param  string  $code
     * @return array
     */
    protected function getTokenFields($code)
    {
        return [
            'grant_type' => 'authorization_code',
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret,
            'code' => $code,
            'redirect_uri' => $this->redirectUrl,
        ];
    }

    /**
     * {@inheritdoc}
     */
    protected function getUserByToken($token)
    {
        $userUrl = 'http://l5-passport.test/api/user';

        $response = $this->getHttpClient()->get($userUrl, [
            'headers' => [
                'Authorization' => 'Bearer ' . $token,
            ],
        ]);

        return json_decode($response->getBody(), true);
    }

    /**
     * {@inheritdoc}
     */
    protected function mapUserToObject(array $user)
    {
        return (new User)->setRaw($user)->map([
            'id'       => $user['id'],
            'email'    => $user['email'],
            'name'     => $user['name'],
        ]);
    }
}

Edit app/Providers

<?php

namespace App\Providers;

use App\Socialite\L5PassportProvider;

...

    public function boot()
    {
        $socialite = $this->app->make(\Laravel\Socialite\Contracts\Factory::class);
        $socialite->extend(
            'l5-passport',
            function ($app) use ($socialite) {
                $config = config('services.l5-passport');
                return $socialite->buildProvider(L5PassportProvider::class, $config);
            }
        );
    }

Edit config/services.php

<?php
    ...
 
    'l5-passport' => [
        'client_id' => env('L5P_CLIENT_ID'),
        'client_secret' => env('L5P_CLIENT_SECRET'),
        'redirect' => env('L5P_REDIRECT'),
    ],

Edit routes/web.php

<?php
...

Route::get('login/l5-passport', 'Auth\LoginController@redirectToL5Passport');
Route::get('login/l5-passport/callback', 'Auth\LoginController@handleL5PassportCallback');

Edit resources/views/auth/login.blade.php

<a class="btn btn-default" href="/login/l5-passport">
    L5-Passport Login
</a>

Edit .env

L5P_CLIENT_ID=[client id at l5-passport]
L5P_CLIENT_SECRET=[client secret at l5-passport] L5P_REDIRECT=http://l5-socialite.test/login/l5-passport/callback 

Go l5-passport login at http://l5-socialite.test/login

Implicit Grant at l5-passport.test

references :

  • https://auth0.com/docs/api-auth/tutorials/implicit-grant

Edit app/ServiceProvider/AuthServiceProvider.php

<?php
...

    public function boot()
    {
        ...
        Passport::routes();

        Passport::enableImplicitGrant();
        ...
    }

Edit routes/web.php

<?php
Route::get('/login/l5-passport', function () {
    $query = http_build_query([
        'client_id' => 3,
        'redirect_uri' => 'http://l5-passport.test/callback',
        'response_type' => 'token',
        'scope' => '',
    ]);

    return redirect('http://l5-passport.test/oauth/authorize?'.$query);
});

Route::get('/login/l5-passport/callback', function (Request $request) {
    return view('auth.callback');
});

Edit resources/assets/js/components/passport/ImplicitGrantTest.vue

<template>
<div>
    <dl>
        <dt>Access token</dt>
        <dd>{{ access_token }}</dd>
        <dt>Token type</dt>
        <dd>{{ token_type }}</dd>
        <dt>Expires in</dt>
        <dd>{{ expires_in }}</dd>
    </dl>
</div>
</template> 

<script>
export default {
    data () {
        return {
            access_token: null,
            token_type: null,
            expires_in: null,
        };
    },
    mounted() {
        this.access_token = this.getParameterByName('access_token');
        this.token_type = this.getParameterByName('token_type');
        this.expires_in = this.getParameterByName('expires_in');
    },
    methods: {
        getParameterByName(name) {
            let match = RegExp('[#&]' + name + '=([^&]*)').exec(window.location.hash);
            return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
        }
    }
}
</script>

Edit resources/assets/js/app.js

Vue.component(
    'passport-implicit-grant-test',
    require('./components/passport/ImplicitGrantTest.vue')
);

Create resource/view/auth/callback.blade.php


@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <passport-implicit-grant-test></passport-implicit-grant-test>
            </div>
        </div>
    </div>
@endsection

Create New Client at /oauth after login

  • Name : l5-passport
  • Redirect URL : http://l5-passport.test/login/l5-passport/callback