尝试实现 OAuth2 服务器并集成到 ThingsBoard 平台

Pat*_*raj 5 php oauth-2.0 thingsboard

我正在尝试在 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"
}
Run Code Online (Sandbox Code Playgroud)

和资源 api 我得到以下响应

{
      "email":"test@gmail.com",
      "firstName":"Dave",
      "lastName":"Johnson",
      "profile":1828838378
}
Run Code Online (Sandbox Code Playgroud)

对此的任何帮助将非常感激

编辑:请找到终点的来源

授权.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

令牌.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

资源.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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

服务器.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__)));
    }
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*ski 3

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

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

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

    \n
      \n
    • 令牌端点 URI、用户信息 URI
    • \n
    • 客户端 ID 和客户端密钥
    • \n
    • 协议
    • \n
    • 任何主机名或端口,
    • \n
    • ETC。
    • \n
    \n
  4. \n
\n

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

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

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

    \n
  4. \n
  5. 由于某种原因,文档要求检查这一点:

    \n
  6. \n
\n
Check the General Settings -> Base URL should not contain \xe2\x80\x9c/\xe2\x80\x9d at the end (e.g. \xe2\x80\x9chttp://127.0.0.1:8080\xe2\x80\x9d instead of \xe2\x80\x9chttps://127.0.0.1:8080/\xe2\x80\x9d). \n
Run Code Online (Sandbox Code Playgroud)\n

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

\n