繁体   English   中英

带有Ionic 3和Rails的OAuth(devise_token_auth)

[英]OAuth with Ionic 3 and Rails (devise_token_auth)

我正在使用Ruby on Rails后端构建Ionic 3(Angular 4)应用程序。

我正在使用angular2-tokendevise_token_auth进行用户和API调用身份验证,这两个功能可以一起使用。

它们的工作方式很简单:它们在每个API调用标头上创建并跟踪一些字段(即auth-tokenclientuidexpiry )。

它可以完美地使用电子邮件注册/登录。 我现在想为我的应用程序实现Instagram OAuth登录,这在常规的Angular Web应用程序中应该是InAppBrowser事,但是在Ionic中,我无法控制路由或URL,因此可以采取的策略是启动InAppBrowser并在其上设置事件以检测其何时到达我的API回调URL。

基本上:

  1. 我加载myapi.com/auth/instagram内部InAppBrowser
  2. Instagram登录,重定向到回调URL
  3. InAppBrowser加载myapi.com/omniauth/instagram/callback?code=57... ,我检测到它。

至此,我的后端已经根据Instagram数据成功创建了一个用户。

问题是,我不知道如何在客户端进行处理。

当我使用电子邮件/密码登录时, angular2-token作用是POST /auth/sign_in ,请求标头包含auth_token和东西,然后对其进行处理并存储以供后续调用。 现在,OAuth流位于InAppBrowser实例中,不受我的控制。

我真的很沮丧,因为我看到OAuth流程在后端运行,而前端部分可以在InAppBrowser之外的常规Web应用程序上轻松完成。

我将复制一些前端和后端代码以提供更多上下文,希望这有助于理解问题。

处理OAuth流程的前端:

  public logInWithInstagram(): Promise<any>{
    var callbackURL = environment.token_auth_config.apiBase + "/omniauth/instagram/callback";
    var oauthURL = environment.token_auth_config.apiBase + "/auth/instagram";
    var parsedResponse = {};

    return new Promise(function(resolve, reject) {
      var browserRef = window.cordova.InAppBrowser.open(oauthURL, "_blank", "location=no,clearsessioncache=yes,clearcache=yes");
      browserRef.addEventListener("loadstart", (event) => {
        if ((event.url).indexOf(callbackURL) === 0) {
          browserRef.removeEventListener("exit", (event) => {});
          browserRef.close();
          var responseParameters = ((event.url).split("?")[1]).split("&");
          var parsedResponse = {};
          for (var i = 0; i < responseParameters.length; i++) {
            parsedResponse[responseParameters[i].split("=")[0]] = responseParameters[i].split("=")[1];
          }
          if (typeof(parsedResponse["code"]) !== 'undefined' && parsedResponse["code"] !== null) {
            // Successful Instagram OAuth, backend has already created the user by now
            resolve(parsedResponse);
          } else {
            reject("Problem authenticating");
          }
        }
      });
      browserRef.addEventListener("exit", function(event) {
        reject("The sign in flow was canceled");
      });
    });
  }

后端,用于创建用户并处理回调URL的部分:

class Users::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController

  def redirect_callbacks    
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user
    else
      session["devise.instagram_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end

  end

  def failure
    redirect_to root_path
  end
end

任何帮助,策略或想法,我都将不胜感激。 非常感谢你!

Angular2令牌位于Alpha中,并且尚未处理返回给inAppBrowser的凭据。

我们最终分叉了该项目,并在angular2-token包中添加了一个逻辑分支来解决该问题。

仍然有点麻烦(例如,oAuthLogin尚未返回可观察到的消息,您必须轮询登录成功),但是它可以工作。

如果您想尝试一下,该软件包就在这里: https : //github.com/chadnaylor/angular2-token-ionic3

除了离子逻辑外,它与angular2-token基本相同。 希望我们将其清理干净后再将其合并。

如果您想自己进行调整,则我们更改的内容如下所示:

browser.on('loadstop').subscribe((ev: InAppBrowserEvent) => {
        if (0 === ev.url.indexOf(this.atOptions.oAuthBrowserCallback)) {
          browser.executeScript({code: "requestCredentials();"})
            .then((credentials) => {
              // alert(JSON.stringify(credentials[0]));
              this.getAuthDataFromPostMessage(credentials[0]);

              let pollerObserv = Observable.interval(400);

              let pollerSubscription = pollerObserv.subscribe(() => {
                if(this.userSignedIn()){
                  pollerSubscription.unsubscribe();
                  browser.close();
                }
              });

            })
        }

      });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM