2016-05-25 24 views
2

現在Auth0経由でサードパーティ認証を設定しているドメイン(たとえばhttp://backend.com)にホストされているloopbackJS APIがあります。私は別のドメイン(例えばhttp://frontend.com)のSPAとしてホストされているフロントエンドを持っていますAuth0サードパーティのログインを使用するLoopbackJS APIアクセストークン

フロントエンドがAPIと同じドメインにあるときにループバックコンポーネントパスポートがうまく動作していると思われ、userIdとそれに応じてaccess_tokenのクッキー。バックエンドは、loopback-passport-exampleと同じ認証パターンを使用してい

"http://backend.com/auth/auth0?returnTo=" + encodeURIComponent("http://frontend.com")

:しかし、生産の私のフロントエンドは、例えばAPIの認証リンクのようなものになるだろう、APIとは異なるドメインにありますここでproviders.jsonファイルはAuth0の接続の詳細を指定します(私はFacebookなどの他のソーシャルプロバイダも試しましたが)。

"auth0-login": { 
    "provider": "auth0", 
    "module": "passport-auth0", 
    "clientID": "AUTH0_CLIENT_ID", 
    "clientSecret": "AUTH0_CLIENT_SECRET", 
    "callbackURL": "/auth/auth0/callback", 
    "authPath": "/auth/auth0", 
    "callbackPath": "/auth/auth0/callback", 
    "successRedirect": "/", 
    "failureRedirect": "/login", 
    "scope": ["email"], 
    "failureFlash": true 
    } 

フロントエンド(http://frontend.com)は、APIの認証にリダイレクトするページのリンクがあります。このリンク上の

<a href="http://backend.com/auth/auth0">Login</a> 

クリックすると、適切Auth0にリダイレクトする、と私は、ログインすることができます。その後、指定されたターゲット(http://backend.comまたはhttp://frontend.comのいずれか指定されている方)にリダイレクトされます。 returnToクエリパラメータも期待どおりに機能しているようです。

access_tokenをフロントエンドにリダイレクトする直前にキャプチャし、何らかの形で通信します(クエリパラメータなど)。あまりにも安全でない場合を除きます。

+0

あなたは[あるドメインから別のドメインにクッキーを渡すことはできません] [http://stackoverflow.com/questions/6761415/how-to-set-a-cookie-for-another-domain]。アクセストークンを取得する別の方法を見つける必要があります(ちなみに、oauthの一時トークンではなく、ループバックによって生成されたアクセストークンと思われます) – Overdrivr

+0

クライアントAPIを配布する外部APIとサーバーアプリケーションに関する詳細を教えてください私は答えを公式化することができます – Overdrivr

+0

ありがとう、私は具体的な詳細についていくつかの詳細で質問を変更しました。この問題を回避するために、ドメインの分離を前提にアプローチするのが最善でしょうか、可能であれば、同じドメインにフロントエンドとAPIを配置する方が良いでしょうか? – J3Y

答えて

1

もう少し調査した後、ループバックのバックエンドからアクセストークンとuserIdを別のフロントエンドに渡すためにこの方法を使用することに決めました。これは、passport-configuratorのcustomCallbackを使用して、github pull-requestでdocumentedでした。

これを参照した他の場所は、this fork,issue #102,issue #14およびpull request #155です。

npmの依存関係としてloopback-component-passportのフォーク(例:上記のreferenced)を使用するか、パスポート設定オプションとしてcustomCallbackをdocumentedとして指定します。

URLのフォーマットをもう少しコントロールしたかったので、customCallbackメソッドで終わりました。 loopback-example-passportにおいて、/server/server.js内部パスポートコンフィギュレータにproviders.jsonを通過させるためのいくつかの基本的なコードがある:

var config = {}; 
try { 
    config = require('../providers.json'); 
} catch (err) { 
    console.trace(err); 
    process.exit(1); // fatal 
} 
passportConfigurator.init(); 
for (var s in config) { 
    var c = config[s]; 
    c.session = c.session !== false; 
    passportConfigurator.configureProvider(s, c); 
} 

これは本質的にpassport変数はpassportConfigurator.init()によって割り当てられると、文書customCallbackコードに置き換えることができる。

var providers = {}; 
try { 
    providers = require('../providers.json'); 
} catch (err) { 
    console.trace(err); 
    process.exit(1); // fatal 
} 

const passport = passportConfigurator.init(); 
Object.keys(providers).forEach(function(strategy) { 

    var options = providers[strategy]; 
    options.session = options.session !== false; 

    var successRedirect = function(req) { 
    if (!!req && req.session && req.session.returnTo) { 
     var returnTo = req.session.returnTo; 
     delete req.session.returnTo; 
     return returnTo; 
    } 
    return options.successRedirect || ''; 
    }; 

    options.customCallback = !options.redirectWithToken 
    ? null 
    : function (req, res, next) { 
     var url = require('url'); 
     passport.authenticate(
     strategy, 
     {session: false}, 
     function(err, user, info) { 
      if (err) { 
      return next(err); 
      } 

      if (!user) { 
      return res.redirect(options.failureRedirect); 
      } 
      var redirect = url.parse(successRedirect(req), true); 

      delete redirect.search; 

      redirect.query = { 
      'access_token': info.accessToken.id, 
      'userId': user.id.toString() 
      }; 
      redirect = url.format(redirect); 
      return res.redirect(redirect); 
     } 
    )(req, res, next); 
    }; 

    passportConfigurator.configureProvider(strategy, options); 
}); 

上記の例では、passport-configurator.jsで使用されているsuccessRedirect関数を基本的にコピーして、同じreturnToクエリパラメータを使用しました。 providers.json内のオプションを設定することができます。 "redirectWithToken": trueとなり、外部リダイレクトを必要とする認証戦略だけがリダイレクトされます。

returnToリダイレクトが必要な場合のコードのもう1つのコードがもう1つあります。それはクエリパラメータとして存在している場合は、セッションレベルで追加する必要があります。バックエンドAPIはURLなどhttp://api.comであれば、

app.use(function(req, res, next) { 
    var returnTo = req.query.returnTo; 
    if (returnTo) { 
    req.session = req.session || {}; 
    req.session.returnTo = require('querystring').unescape(returnTo); 
    } 
    next(); 
}); 

さて、フロントエンドは別のドメインでホストされている例http://gui.com、認証リンクは、フロントエンドに配置することができます:

<a href="http://api.com/auth/facebook?returnTo=http%3A%2F%2Fgui.com">Login!</a> 

これは、クエリパラメータでトークンとのuserIdアクセスバックreturnToリンクにリダイレクトし、その後、APIの認証コールになります。

将来的には、サードパーティのドメインリダイレクトに理想的な方法を提供する可能性がある問題またはその他のプルリクエストの1つがマージされますが、これまではこの方法がうまく機能します。

関連する問題