Quickbooks Online - 如何在 Ruby/Rails 中使用 intuit 实现 SSO

Quickbooks Online - How to implement SSO with intuit in Ruby/Rails

我能够使用 Minimul/QboApi gem 连接到 Intuit,并根据 Github 上提供的示例让 "Connect to Quickbooks" 按钮与 oauth2 一起工作。然而,gem 和示例均未显示如何使用 Intuit 实现单点登录。在 Minimul 提供的示例中,“连接到 Quickbooks”按钮是由位于 https://appcenter.intuit.com/Content/IA/intuit.ipp.anywhere-1.3.5.js 的 intuit javascript 生成的 以及安装脚本和标签。该标签似乎已被弃用。或者至少,除了生成带有正确文本和徽标的按钮外,它似乎没有做任何其他事情。

但最重要的是,我一直找不到关于 ipp.anywhere.js 包的任何文档,甚至不确定我是否打算与 oauth2 一起使用,因为它在任何地方都没有提到。我相信 connect to intuit 按钮会做正确的事情,但指南似乎非常严格地规定按钮需要说出正确的事情并具有正确的徽标,否则他们会在商店中拒绝它。他们似乎还建议,如果启用了带有 Intuit 工作流的 SSO,用户更有可能尝试一些事情。任何帮助表示赞赏。

经过一些进一步的工作,我想出了一个可以创建 'log in with Inuit button' 的解决方案,尽管它有点像 javascript hack。首先,我确定我唯一真正需要更改的是按钮图像。在其他方面,` 后面的代码对于 "login with intuit" 或 "connect to intuit work flow" 都可以正常工作。唯一的问题是按钮图像。

这是通过 "Connect to Quickbooks" 按钮获取访问权限和 oauth2 刷新令牌的代码(改编自 Minimul/QboApi)。

在登录或会​​话控制器的控制器代码中设置:

def new
  @app_center = QboApi::APP_CENTER_BASE # "https://appcenter.intuit.com" 
  state= SecureRandom.uuid.to_s
  intuit_id = ENV["CLIENT_ID"]
  intuit_secret = ENV["CLIENT_SECRET"]
  client = Rack::OAuth2::Client.new(
    identifier: intuit_id,
    secret: intuit_secret,
    redirect_uri: ENV["OAUTH_REDIRECT_URL"],
    uthorization_endpoint:"https://appcenter.intuit.com/connect/oauth2",
    token_endpoint: "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
    response_type: "code"
  )
  #make sure to include at least "openid profile email" 
  #in the scope to you can retrieve user info.
  @uri = client.authorization_uri(scope: 'com.intuit.quickbooks.accounting openid profile email phone address', state: state)
end

这是在视图上生成按钮所需的代码。 (视图也需要加载 jquery 才能使脚本正常工作。)

<script type="text/javascript" src="<%= @app_center %>/Content/IA/intuit.ipp.anywhere-1.3.5.js">
</script>
<script>
    intuit.ipp.anywhere.setup({
        grantUrl: "<%== @uri %>",
        datasources: {
            quickbooks: true,
            payments: false
        }
    });
</script>
<div>
 <ipp:connecttointuit></ipp:connecttointuit>

此代码在交付给客户的页面上生成以下 html:

<ipp:connecttointuit>
   <a href="javascript:void(0)" class="intuitPlatformConnectButton">Connect with QuickBooks</a>
</ipp:connecttointuit>

此代码生成一个带有 Connect with QuickBooks 图像的按钮,intuit.ipp.anywhere-1.3.5.js 中的事件处理程序将自身附加到单击事件。

问题是该按钮的样式由生成的 <a> 标记内的 class=intuitPlatformConnectButton 属性设置,因此如果您想要“使用 intuit 按钮登录而不是使用 intuit 按钮连接”[锚点上的 =55=] 需要更改为 class='intuitPlatformLoginButtonHorizontal' 但仍需要附加到为 <ipp:connecttointuit> 定义的事件处理程序。不需要使用 intuit.ipp.anywhere 的最佳解决方案是创建连接按钮并隐藏它,然后创建另一个样式为 class=intuitPlatformLoginButtonHorizontal 的标签,其点击事件调用点击隐藏的连接按钮。我在登录页面上使用 AngularJs,所以我处理点击ng-click,但仅用 jquery 就可以完成。

new.html.erb:

<div>
   <a href="javascript:void(0)"  ng-class="'intuitPlatformLoginButtonHorizontal'"ng-click="intuit_login()"></a>
</div>
<div>
   <ipp:connecttointuit id="connectToIntuit" ng-hide="true"><  </ipp:connecttointuit>
</div>

和控制器代码:

 $scope.intuit_login = function() {
   let el = angular.element("#connectToIntuit:first-child")
   el[0].firstChild.click();
 }

这将导致在身份验证时重定向到提供的重定向 url,您可以在其中使用 openid 获取用户凭据。