【问题标题】:Trying to implement OAuth2 server and integrate in ThingsBoard platform尝试实现 OAuth2 服务器并集成到 ThingsBoard 平台
【发布时间】:2022-02-21 16:38:07
【问题描述】:

我正在尝试在 ThingsBoard 实例中实现自定义 OAuth2 实现,因为我已经在 php 中实现了 OAuth2 服务器

https://github.com/bshaffer/oauth2-demo-php

http://brentertainment.com/oauth2/

根据他们的 bshaffer 演示,它工作正常,当我将它与第三方应用程序thingboard 实例集成时,第一步工作正常,直到身份验证,之后它重定向到登录页面,说明 Oauth2 错误但不知道它在这里是什么是 OAuth2 服务器的示例 URL 和响应

http://34.226.xxx.xx/oauth2/web/lockdin/authorize

http://34.226.xxx.xx/oauth2/web/lockdin/token

http://34.226.xxx.xx/oauth2/web/lockdin/resource

第 1 步:

http://34.226.xxx.xx/oauth2/web/lockdin/authorize?response_type=code&client_id=demoapp&scope=email&state=2r3TIvWotKyjXJ3Nzef-DA_0EZdJFdMm_bO2wCF7S8%3D&redirect_uri=https://thingsboard.io/login/oauth2/code/

第 2 步:

授权发生在它发送回成功响应之后

https://thingsboard.io/login/oauth2/code/?code=something&state=2r3TIvWotKyjXJ3Nzef-DA_0EZ-dJFdMm_bO2wCF7S8%3D

在这之后它失败了

我已经测试了这个手动生成令牌之后的步骤,它工作正常

http://34.226.xxx.xx/oauth2/web/lockdin/token它给了我回应

{
    "access_token": "4a01f8b9e8548420425c8f335eda2a3dbde7ef75",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "email",
    "refresh_token": "ccbb9b8a03949e0e013acdb7f8e79426aa1a0a58"
}

和资源 api 我得到以下响应

{
      "email":"test@gmail.com",
      "firstName":"Dave",
      "lastName":"Johnson",
      "profile":1828838378
}

对此的任何帮助将不胜感激

编辑:请找到终点的来源

Authorize.php

namespace OAuth2Demo\Server\Controllers;
use Silex\Application;
class Authorize
{
    public static function addRoutes($routing)
    {
        $routing->get('/authorize', array(new self(), 'authorize'))->bind('authorize');
        $routing->post('/authorize', array(new self(), 'authorizeFormSubmit'))->bind('authorize_post');
    }
  
    public function authorize(Application $app)
    {
     
        $server = $app['oauth_server'];
        $response = $app['oauth_response'];
        
        if (!$server->validateAuthorizeRequest($app['request'], $response)) {
            return $server->getResponse();
        }

        return $app['twig']->render('server/authorize.twig', array(
            'client_id' => $app['request']->query->get('client_id'),
            'response_type' => $app['request']->query->get('response_type')
        ));
    }
  
    public function authorizeFormSubmit(Application $app)
    {      
        $server = $app['oauth_server'];
        $response = $app['oauth_response'];
        $authorized = (bool) $app['request']->request->get('authorize');
        return $server->handleAuthorizeRequest($app['request'], $response, $authorized);
    }
}

Token.php

namespace OAuth2Demo\Server\Controllers;
use Silex\Application;
class Token
{
    
    public static function addRoutes($routing)
    {
        $routing->post('/token', array(new self(), 'token'))->bind('grant');
    }
    public function token(Application $app)
    {       
        $server = $app['oauth_server'];
        $response = $app['oauth_response'];
        return $server->handleTokenRequest($app['request'], $response);
    }
}

Resource.php

namespace OAuth2Demo\Server\Controllers;    
use Silex\Application;
use Symfony\Component\HttpFoundation\Response;    
class Resource
{       
    public static function addRoutes($routing)
    {
        $routing->get('/resource', array(new self(), 'resource'))->bind('access');
    }
  
    public function resource(Application $app)
    {         
        $server = $app['oauth_server'];
        $response = $app['oauth_response'];

        if (!$server->verifyResourceRequest($app['request'], $response)) {
            return $server->getResponse();
        } else {            
            $api_response = array(
                    "email"=> "xxx@gmail.com",
                     "name"=> "Pattatharasu Nataraj",
                     "family_name"=>"Nataraj",
                     "given_name"=>"Pattatharasu",
                     "middle_name"=>"",
                     "nickname"=>"",
                     "picture"=>"",
                     "updated_at"=>""
            );
            return new Response(json_encode($api_response));
        }
    }
}

Server.php

class Server implements ControllerProviderInterface
{
    
    public function setup(Application $app)
    {
       
        if (!file_exists($sqliteFile = __DIR__.'/../../../data/oauth.sqlite')) {
            $this->generateSqliteDb();
        }
        
        $storage = new Pdo(array('dsn' => 'mysql:host=localhost;dbname=demoapp'));       
        $grantTypes = array(
            'authorization_code' => new AuthorizationCode($storage),
            'user_credentials'   => new UserCredentials($storage),
            'refresh_token'      => new RefreshToken($storage, array(
                'always_issue_new_refresh_token' => true,
            )),
        );
        $server = new OAuth2Server($storage, array(
            'enforce_state' => true,
            'allow_implicit' => true,
            'use_openid_connect' => true,
            'issuer' => $_SERVER['HTTP_HOST'],
        ),$grantTypes);

        $server->addStorage($this->getKeyStorage(), 'public_key');      
        $app['oauth_server'] = $server;
        $app['oauth_response'] = new BridgeResponse();
    }
   
    public function connect(Application $app)
    {          
        $this->setup($app);
        $routing = $app['controllers_factory'];
        Controllers\Authorize::addRoutes($routing);
        Controllers\Token::addRoutes($routing);
        Controllers\Resource::addRoutes($routing);
        return $routing;
    }

    private function generateSqliteDb()
    {
        include_once($this->getProjectRoot().'/data/rebuild_db.php');
    }

    private function getKeyStorage()
    {
        $publicKey  = file_get_contents($this->getProjectRoot().'/data/pubkey.pem');
        $privateKey = file_get_contents($this->getProjectRoot().'/data/privkey.pem');
        $keyStorage = new Memory(array('keys' => array(
            'public_key'  => $publicKey,
            'private_key' => $privateKey,
        )));
        return $keyStorage;
    }

    private function getProjectRoot()
    {
        return dirname(dirname(dirname(__DIR__)));
    }
}

【问题讨论】:

  • after that it is redirecting to login page stating Oauth2 error - 什么是重定向到登录页面?您的 OAuth 服务器、后端代码、前端代码?是什么触发了重定向?另外,您得到的确切错误是什么? After this Its getting failed - 错误是什么?服务器的日志说什么?您如何调用令牌端点?为了帮助您回答这个问题,我们需要比“它失败了”更多的信息。也许您可以显示相关的错误响应、日志,也许还有一些代码?
  • 请求您与 fiddler 进行检查,以便您可以追踪失败的位置。如果是回调函数即将在您的主应用程序中调用,则应该是匿名的。在进行网络检查 TLS 握手之前,现在大多数网站在提供对任何内容的访问之前都需要非常安全的握手,前提是调用的 URI 都是正确的。
  • 还要检查托管实例,有时它会显示 2 个实例,一个用于主应用程序,而 owin 用于其他应用程序。
  • 请点击以下链接,我也遇到了同样的问题。你可能会有所了解stackoverflow.com/questions/70861411/…
  • 希望您在 okta 中配置了相同的单点登录 URL:{base uri}/saml2/acs 示例:localhost:2687/saml2/acs 受众 URI(SP 实体 ID):{base uri}/saml2 示例:@ 987654331@

标签: php oauth-2.0 thingsboard


【解决方案1】:

根据您的描述,thingsboard 应用程序似乎在将授权代码交换为访问令牌时出现问题。看起来您的服务器工作正常(正如您使用 Postman 验证的那样)。您需要找出 thingsboard 应用程序无法正确交换代币代码的原因。这就是我要做的:

  1. 向您的令牌端点添加一些日志记录,以验证 thingboard 应用程序是否到达您的令牌端点。如果看到thingsboard的请求,请检查该请求中有哪些数据(代码是否正确、grant_type、其他请求参数、授权标头等)。验证该请求在您的服务器中是成功还是失败。含义 - 记录您发出的访问令牌以及您是否发送回 200 响应。

  2. 如果您没有看到对令牌端点的请求,请确保 thingsboard 应用程序中的所有配置对于您的 OAuth 服务器实例都是正确的:

    • 令牌端点 URI,用户信息 URI
    • 客户端 ID 和客户端密码
    • 协议
    • 任何主机名或端口,

您可以查看他们的文档,其中显示了与 Auth0 集成的示例:https://thingsboard.io/docs/user-guide/oauth-2-support/ 这显示了您需要为集成设置的所有内容。

  1. 如果您设法验证您收到令牌请求并返回访问令牌,然后确保 thingsboard 能够调用您的用户信息端点 - 再次检查配置,尤其是 URL。检查 thingsboard 正在使用的任何映射 - 确保您的 userifo 端点以 thingsboard 可识别的格式返回数据。

  2. 如果您在服务器的日志中没有看到令牌请求,那么您可能要检查的另一件事是您的实现是否没有以某种方式更改状态参数(可能完成了一些冗余编码?)。如果 state 参数不匹配,Thingsboard 可能会拒绝您的重定向响应。

  3. 出于某种原因,文档要求对此进行检查:

Check the General Settings -> Base URL should not contain “/” at the end (e.g. “http://127.0.0.1:8080” instead of “https://127.0.0.1:8080/”). 

不确定这会如何破坏 OAuth 集成,但我认为它在文档中是有原因的。

【讨论】:

  • 感谢您的解决方案,我将尝试对此进行故障排除
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
  • 2016-04-16
  • 2015-04-12
  • 2013-03-23
  • 1970-01-01
相关资源
最近更新 更多