将 OAuth 2.0 与自定义 API 集成的概述(用 Laravel 编写)

Posted

技术标签:

【中文标题】将 OAuth 2.0 与自定义 API 集成的概述(用 Laravel 编写)【英文标题】:Overview of integrating OAuth 2.0 with a Custom API (written in Laravel) 【发布时间】:2014-01-09 18:49:29 【问题描述】:

我创建了一个 android 应用程序,它与我使用 php 设置的 API 进行通信,并打算尝试使用 Laravel 重写 PHP 的东西。我想做的一项重大更改是允许 OAuth 登录到我的应用程序,该应用程序与我本地服务器上的用户帐户相关联,我对执行此操作所涉及的应用程序流程感到困惑。

我是否应该在注册之前在我的 Android 应用上进行 OAuth 身份验证,然后在我调用我的 API 以创建我的本地用户帐户时存储某种凭据和用户信息?

另外,当使用 OAuth 登录用户时,我如何知道通过提供商(例如 Facebook)进行身份验证的人是否与我服务器上的本地用户帐户相关联?我可以存储某种令牌吗?

感谢您提供的任何概述信息。

【问题讨论】:

【参考方案1】:

我对@9​​87654321@ 做了同样的事情(没有来自我的站点的 OAuth 提供程序)还有一个 composer package at packagist.org。

我为此准备了两张桌子:

users 列 id、email、密码(包含我的普通用户和用户信息的表格) 身份验证,列:id、user_id、provider、provider_uid(包含 OAuth 内容的身份验证表。)

我的 AuthController 中的代码(用于路由 /login/social Route::controller('login','AuthController');

<?php

class AuthController extends BaseController 

    //@see http://www.mrcasual.com/on/coding/laravel4-package-management-with-composer/
    public function getSocial($action = '')
    
        // check URL segment
        if ($action == 'auth') 
            // process authentication
            try 
                Hybrid_Endpoint::process();
            
            catch (Exception $e) 
                // redirect back to http://URL/social/
                return Redirect::to('login/social');
            
            return;
        
        try 
            // create a HybridAuth object
            $socialAuth = new Hybrid_Auth(app_path() . '/config/hybridauth.php');
            // authenticate with provider
            if($action != '')
                // only allow facebook and google
                if(in_array($action,array('google','facebook')))
                    $provider = $socialAuth->authenticate($action);
                else
                    // catch this form_error in the login form
                    return Redirect::to('login')->withErrors(array('form_errors'=>'The url was invalid'));
                
            else
                return Redirect::to('login');
            
            // fetch user profile
            $userProfile = $provider->getUserProfile();
        
        catch(Exception $e) 
            // exception codes can be found on HybBridAuth's web site
            return Redirect::to('login')->withErrors(array('form_errors'=>'Error on Login: #'.$e->getCode().': '.$e->getMessage()));
        
        /*access user profile data
        echo "Connected with: <b>$provider->id</b><br />";
        echo "As: <b>$userProfile->displayName</b><br />";
        echo "<pre>" . print_r( $userProfile, true ) . "</pre><br />";
        die();*/


        //check if User exists
        if($user_id = DB::table('authentications')->where('provider', $provider->id)->where('provider_uid',$userProfile->identifier)->pluck('user_id'))
            //login user
            Auth::loginUsingId($user_id);
            //update user details (eg photo, name, etc)
            //Here you can update the user details
            return Redirect::to('dashboard');
        else
            //lets see if we already know this email -> connect it with the registered account
            if($user = User::where('email',$userProfile->email)->first())
                $user->authentications()->save(new Authentication(array('provider'=>$provider->id, 'provider_uid'=>$userProfile->identifier)));
                Auth::login($user);
                //here you can update the user details 
                return Redirect::to('dashboard')->with('user_social_linked',$provider->id);
            else
                //register user
                $user = $this->createUser(array('email'=>$userProfile->email,'password'=>''));
                $user->authentications()->save(new Authentication(array('provider'=>$provider->id, 'provider_uid'=>$userProfile->identifier)));
                Auth::login($user);
                //here you can set/update the user details 
                return Redirect::to('dashboard')->with('user_created',true);
            
        
    

    private function createUser($credentials)
    
        $user = new User();
        $user->email = $credentials['email'];
        $user->password = $credentials['password'];
        $user->save();
        Auth::login($user);
        return $user;
    

User 模型还有以下功能

<?php
public function setPasswordAttribute($password)
    //disable blank passwords => disables account login (eg login only with third party aka social providers)
    if($password != '')
        $this->attributes['password'] = Hash::make($password);
    else
        $this->attributes['password'] = $password;
    

现在您可以像对待任何其他 OAuth 提供者一样对待自己的 OAuth 提供者,例如,通过添加/配置混合身份验证提供者。

对于您的问题:

我是否应该在注册之前在我的 Android 应用上进行 OAuth 身份验证,然后在我调用我的 API 以创建我的本地用户帐户时存储某种凭据和用户信息?

我会像处理任何其他 OAuth 提供程序一样处理它:就像上面的示例中要调用的一个函数(我只通过 Laravel Auth 使用登录,所以我没有过期提供程序会话的问题,用户确实不必创建另一个帐户)。

另外,当使用 OAuth 登录用户时,我如何知道通过提供商(例如 Facebook)进行身份验证的人是否与我服务器上的本地用户帐户相关联?我可以存储某种令牌吗?

这是由 authentications 表中的 user_id 列完成的。

希望对您有所帮助。

【讨论】:

非常有帮助。阅读 OAuth2 规范并拥有它让我上路。谢谢! 备注:如果用户创建了一个帐户,然后尝试使用(未链接的)社交提供商登录,如果用户使用不同的电子邮件地址(如一次性电子邮件),您最终可能会拥有多个帐户。

以上是关于将 OAuth 2.0 与自定义 API 集成的概述(用 Laravel 编写)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用带有 AsynceTask 的 Oauth 2.0 向自定义 api 发送 http 请求

将 OAuth 2.0 和 Google 电子表格 API 与 Java 结合使用的示例是啥?

春天。 REST API 的实现 Oauth.2.0

spring-security-oauth2 JwkTokenStore 与自定义用户详细信息服务

API网关对OAuth 2.0的实现调研

OAuth 2.0 与 JWT