1. 应用 user.68hub.comoauth.68hub.com 提供 redirect_uri client_name 用来申请认证IDclient_id 和密钥client_secret

  2. 用户使用 user.68hub.com 需要登录时会带上自己从 oauth.68hub.com 获取的 client_idredirect_uriscope (授权范围) 和 response_type (请求类型) state (用来验证参数防止CSRF) 重定向到 oauth.68hub.com 的授权页面。 以下是php示例代码,

    Route::get('/redirect', function (Request $request) {
        $request->session()->put('state', $state = Str::random(40));
    
        $query = http_build_query([
            'client_id' => 'client-id',
            'redirect_uri' => 'http://user.68hub.com/callback',
            'response_type' => 'code',
            'scope' => '',
            'state' => $state,
        ]);
    
        return redirect('http://oauth.com/oauth/authorize?'.$query);
    });
    
  3. oauth.68hub.com 根据传过来的参数进行验证,如果用户没有登录,则需要用户登录,登录之后根据传过来的参数确定是否有 user.68hub.com 这个应用。并向用户展示是否授权界面(approve) 这一步可以通过配置默认同意授权(达到sso效果)。用户同意授权之后 生成一个 code (此code 中会在 oauth.68hub.com 服务器上存储当前登录用户的相关信息) 并且带上 user.68hub.com 之前传过来的 state 参数 重定向到 user.68hub.com 提供的 回调页面。

  4. user.68hub.com 的回调页面首先会验证之前传递给 oauth.68hub.comstate 参数。如果验证通过则会发起一个post请求到 oauth.68hub.com 获得一个访问令牌。

    Route::get('/callback', function (Request $request) {
        $state = $request->session()->pull('state');
    
        throw_unless(
            strlen($state) > 0 && $state === $request->state,
            InvalidArgumentException::class
        );
    
        $http = new GuzzleHttp\Client;
    
        $response = $http->post('http://oauth.com/oauth/token', [
            'form_params' => [
                'grant_type' => 'authorization_code',
                'client_id' => 'client-id',
                'client_secret' => 'client-secret', //user.68hub.com 原先保存的数据
                'redirect_uri' => 'http://user.68hub.com/callback',
                'code' => $request->code, // oauth.com 服务上用户的相关信息的code
            ],
        ]);
    
        return json_decode((string) $response->getBody(), true);
    });
    
  5. oauth.68hub.com 依据传过来的 client_id, client_secretcode 判断请求的准确性,并根据 code 对应的用户信息生成 相应的 access_token refresh_token expires_in

  6. user.68hub.com 拿到 上一步骤的 token 信息 向 oauth.68hub.com 提供的接口请求用户的相关信息。这一步也可以在第5步的时候一起返回。拿到用户相关信息之后,存入数据库,更新用户 session (让用户登录)。

客户端在拿到用户信息和 access_token 之后,可以根据 expires_in 的过期时间来设置用户的 session 有效期。

有效期过了之后通过 refresh_token 继续刷新 用户信息、access_token

References :

https://yu-jack.github.io/2020/04/13/sso-vs-oauth/

http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html