【问题标题】:Laravel socialite + vue spa return access token to clientLaravel socialite + vue spa 将访问令牌返回给客户端
【发布时间】:2019-01-21 23:44:34
【问题描述】:

如何将社交名流回调中获得的访问令牌返回给客户端? 我需要将此数据返回给 vue 以便用户登录。 token data

这是我在 vue 中获取重定向 url 的代码

googleLogin(){
      const self = this;

      let socialLogin = {
          name: 'google'
      };

      self.$http.post(`api/googleLogin`, socialLogin)
          .then(response => {
              console.log('GOOGLE LOGIN RESPONSE ', response.body);
              window.location = response.body;
          })

  }

对于后端

 public function googleLogin(Request $request){

    $socialType = $request->name;

    return response()->json(
        Socialite::driver($socialType)
            ->with(['social_type' => $socialType])
            ->stateless()
            ->redirect()
            ->getTargetUrl()
    );
}

public function googleLoginCallback(){

    $http = new \GuzzleHttp\Client;

    $user = Socialite::with('google')->stateless()->user();

    $userCredentials = [
        'token' => $user->token,
        'refreshToken' => $user->refreshToken,
        'expiresIn' => $user->expiresIn,
    ];


    $response = $http->post(env('LOGIN_ENDPOINT'), [
        'form_params' => [
            'grant_type' => 'social',
            'client_id' => env('CLIENT_ID'),
            'client_secret' => env('CLIENT_SECRET'),
            'network' => 'google',
            'access_token' => $userCredentials['token'],
        ]
    ]);
    return json_decode((string) $response->getBody(), true);
}

【问题讨论】:

    标签: vue.js single-page-application laravel-5.6 laravel-socialite


    【解决方案1】:

    我正在研究类似的东西,我找到了解决方案。代码基于这个伟大的入门主题:https://github.com/cretueusebiu/laravel-vue-spa

    --

    在 googleLoginCallback() 中,假设您使用的是 Passport API 身份验证,您可以尝试在 Controller 中使用:

    public function googleCallback()
        {
            $provider = 'google';
    
            $user = Socialite::driver($provider)->stateless()->user();
    
            /* HERE CREATE USER WITH YOUR APP LOGIC. If email is unique... */
    
            // Login the created user
            Auth::login($user, true);
    
            // Get the username (or wathever you want to return in the JWT).
            $success['name'] = Auth::user()->name;
            // Create a new access_token for the session (Passport)
            $success['token'] = Auth::user()->createToken('MyApp')->accessToken;
    
            // Create new view (I use callback.blade.php), and send the token and the name.
            return view('callback', [
                'name' => $success['name'],
                'token' => $success['token'],
            ]);
        }
    

    对于 callback.blade.php 视图,您唯一需要做的就是将请求的令牌和用户名发送到 Vue 应用程序。为此,您可以使用 window.postMessage() 方法,该方法允许在窗口、iframe 之间发送数据...

    <html>
    <head>
      <meta charset="utf-8">
      <title>Callback</title>
      <script>
        window.opener.postMessage({ token: "{{ $token }}", name: "{{ $name }}" }, "YOUR DOMAIN");
        window.close();
      </script>
    </head>
    <body>
    </body>
    </html>
    

    最后这是我在 vue 应用中登录组件的逻辑:

    export default {
            // Waiting for the callback.blade.php message... (token and username).
            mounted () {
              window.addEventListener('message', this.onMessage, false)
            },
    
            beforeDestroy () {
              window.removeEventListener('message', this.onMessage)
            },
    
            methods : {
                // This method call the function to launch the popup and makes the request to the controller. 
                loginGoogle () {
                  const newWindow = openWindow('', 'message')
                  axios.post('api/login-google')
                        .then(response => {
                          newWindow.location.href = response.data;
                        })
                        .catch(function (error) {
                          console.error(error);
                        });
                  },
                  // This method save the new token and username
                  onMessage (e) {
                    if (e.origin !== window.origin || !e.data.token) {
                      return
                    }
                    localStorage.setItem('user',e.data.name)
                    localStorage.setItem('jwt',e.data.token)
    
                    this.$router.go('/board')
                  }
            }
        }
    
        // The popup is launched.
    
        function openWindow (url, title, options = {}) {
          if (typeof url === 'object') {
            options = url
            url = ''
          }
    
          options = { url, title, width: 600, height: 720, ...options }
    
          const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : window.screen.left
          const dualScreenTop = window.screenTop !== undefined ? window.screenTop : window.screen.top
          const width = window.innerWidth || document.documentElement.clientWidth || window.screen.width
          const height = window.innerHeight || document.documentElement.clientHeight || window.screen.height
    
          options.left = ((width / 2) - (options.width / 2)) + dualScreenLeft
          options.top = ((height / 2) - (options.height / 2)) + dualScreenTop
    
          const optionsStr = Object.keys(options).reduce((acc, key) => {
            acc.push(`${key}=${options[key]}`)
            return acc
          }, []).join(',')
    
          const newWindow = window.open(url, title, optionsStr)
    
          if (window.focus) {
            newWindow.focus()
          }
    
          return newWindow
        }
    
    </script> 
    

    希望对你有帮助!

    【讨论】:

    • 到目前为止似乎是最好的解决方案。我没有找到其他任何东西。
    猜你喜欢
    • 2019-03-22
    • 1970-01-01
    • 2021-05-18
    • 2019-12-01
    • 2023-03-15
    • 2016-10-19
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多