Thanks

https://medium.com/laravel-news/adding-auth-providers-to-laravel-socialite-ca0335929e42

This have problems

https://socialiteproviders.com/Line/

  1. create app/Providers/LineProvider.php
    https://github.com/SocialiteProviders/Line/blob/master/Provider.php

namespace App\Providers;

use GuzzleHttp\RequestOptions;
use Laravel\Socialite\Two\InvalidStateException;
use \SocialiteProviders\Manager\OAuth2\AbstractProvider;
use \SocialiteProviders\Manager\OAuth2\User;

class LineProvider extends AbstractProvider
{
    public const IDENTIFIER = 'LINE';

    /**
     * The separating character for the requested scopes.
     *
     * @var string
     */
    protected $scopeSeparator = ' ';

    /**
     * The scopes being requested.
     *
     * @var array
     */
    protected $scopes = [
        'openid',
        'profile',
        'email',
    ];

    /**
     * Get the authentication URL for the provider.
     *
     * @param  string  $state
     * @return string
     */
    protected function getAuthUrl($state)
    {
        return $this->buildAuthUrlFromBase(
            'https://access.line.me/oauth2/v2.1/authorize',
            $state
        );
    }

    /**
     * Get the token URL for the provider.
     *
     * @return string
     */
    protected function getTokenUrl()
    {
        return 'https://api.line.me/oauth2/v2.1/token';
    }

    /**
     * Get the raw user for the given access token.
     *
     * @param  string  $token
     * @return array
     */
    protected function getUserByToken($token)
    {
        $response = $this->getHttpClient()->get(
            'https://api.line.me/v2/profile',
            [
                RequestOptions::HEADERS => [
                    'Authorization' => 'Bearer '.$token,
                ],
            ]
        );

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

    /**
     * Map the raw user array to a Socialite User instance.
     *
     * @param  array  $user
     * @return \Laravel\Socialite\User
     */
    protected function mapUserToObject(array $user)
    {
        return (new User())->setRaw($user)->map([
            'id'       => $user['userId'] ?? $user['sub'] ?? null,
            'nickname' => null,
            'name'     => $user['displayName'] ?? $user['name'] ?? null,
            'avatar'   => $user['pictureUrl'] ?? $user['picture'] ?? null,
            'email'    => $user['email'] ?? null,
        ]);
    }

    // /**
    //  * Get the POST fields for the token request.
    //  *
    //  * @param string $code
    //  *
    //  * @return array
    //  */
    // protected function getTokenFields($code)
    // {
    //     return array_merge(parent::getTokenFields($code), [
    //         'grant_type' => 'authorization_code',
    //     ]);
    // }

    /**
     * @return \SocialiteProviders\Manager\OAuth2\User
     */
    public function user()
    {
        if ($this->hasInvalidState()) {
            throw new InvalidStateException();
        }

        $response = $this->getAccessTokenResponse($this->getCode());

        if ($jwt = $response['id_token'] ?? null) {
            $bodyb64 = explode('.', $jwt)[1];
            $user = $this->mapUserToObject(json_decode(base64_decode(strtr($bodyb64, '-_', '+/')), true));
        } else {
            $user = $this->mapUserToObject($this->getUserByToken(
                $token = $this->parseAccessToken($response)
            ));
        }

        $this->credentialsResponseBody = $response;

        if ($user instanceof User) {
            $user->setAccessTokenResponseBody($this->credentialsResponseBody);
        }

        return $user->setToken($this->parseAccessToken($response))
            ->setRefreshToken($this->parseRefreshToken($response))
            ->setExpiresIn($this->parseExpiresIn($response));
    }
}
  1. edit app/Providers/AppServiceProvider.php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->bootLineSocialite();
    }

    public function bootLineSocialite(): void
    {
        // // laravel Socialite 和 Socialite Line 有問題,就是 在初始載入不了
        // // 看Socialite Line 作者還有在3星期前維謢,所以就不知道怎麼回事
        // // https://medium.com/laravel-news/adding-auth-providers-to-laravel-socialite-ca0335929e42
        $socialite = $this->app->make('Laravel\Socialite\Contracts\Factory');

        $socialite->extend(
            'line',
            function ($app) use ($socialite) {
                $config = config('services.line');

                // https://github.com/SocialiteProviders/Line/blob/master/Provider.php
                return $socialite->buildProvider(LineProvider::class, $config); // \SocialiteProviders\Line\Provider::class
            }
        );
    }
}
  1. routes/web.php
Route::get('/auth/redirect', function () {
    return Socialite::driver('line')->redirect();
});

Route::get('/auth/callback', function () {
    $user = Socialite::driver('line')->user();

    dd($user);
});