3

シングルページアプリに Auth0 認証を追加しようとしています。私のアプリは app.mycompany.com などのドメインで実行されていますが、このアプリで使用される API は別のドメイン (api.mycompany.com など) で実行されています。

私はこのスレッドを知っています:

シングル ページ アプリ (SPA) のシングル サインオン (SSO) ソリューション/アーキテクチャ

ここでリンクされている auth0 の記事と github リポジトリ。しかし、いくつかの異なるシングルページ アプリ間でシングル サインオンを行う必要は必ずしもないため、私のシナリオは少し単純であると感じています。まず、API とアプリを分離したいだけです。

これが私がすでに試したことです:

React Login With Auth0の記事から始めて、スターター プロジェクトをダウンロードしました。問題なく確実にログインでき、Auth0 によって発行された JWS を含む id_token が localStorage に残ります。

また、api.mycompany.com (私の FeathersJS API アプリケーション) に直接ログインすることもできます。OAuth リダイレクト プロセス中に、id_token トークンが魔法のように私の Feathers アプリケーションによって発行された、feathers-jwt トークンに変換されていることがわかります。 auth0-ID に一致するユーザー オブジェクト。また、Auth0-ID から内部 ID へのマッピングに使用されるロジックも実装しました。さらに、トークンの検証やユーザーの人口など、すべての Feathers フックが機能しています。

私が理解できないのは、app.mycompany.com で実行されている react-application を localStorage の Auth0-token で変更して、このトークンが api.mycompany.com によって Feathers-jwt トークンに変換されるようにする方法です。後続のすべての API 呼び出しに、フェザーズ jwt トークンが自動的に含まれるようにして、API がユーザーを検証し、正しいデータを返すことができるようにします。

続行する方法についての提案は大歓迎です。

いくつかの背景の詳細​​:

  • APIはnode.jsとfeatherjs(基本的にはExpressの拡張)に基づいて構築されています
  • single-page-app は ReactJS 上に構築され、シンプルな Express サーバーによって提供されますが、http 経由で静的ファイルを提供できる任意のサーバーによって提供される可能性があります。single-page-app は、データを読み取って操作を実行するために、API に対して http 要求を行います。
  • API には、認証を処理する次のコード行があります。

    const authentication = require('feathers-authentication');
    const Auth0Strategy = require('passport-auth0').Strategy;
    app.configure(authentication({
        local:false,
        token: {
          secret: 'mysecret',
          payload: ['email', 'auth0Nickname'],
          issuer: 'mycompany'
        },
        idField: 'id',
        shouldSetupSuccessRoute: false,
        auth0: {
          strategy: Auth0Strategy,
          domain: 'mycompany.eu.auth0.com',
          'clientID': 'xxx',
          'clientSecret': 'yyy'
        }
    }));
    
4

2 に答える 2

3

私はあなたとまったく同じ問題を抱えていました。他のサーバーにある API を呼び出して、単一ページのアプリケーションからユーザーを認証したかったのです。

公式のauth0 の例は、認証を行い、html ページをレンダリングする従来の Express Web アプリケーションですが、他のドメインでホストされている API に接続された SPA ではありません。

この例でユーザーが認証するときに何が起こるかを分けてみましょう。

  • /auth/auth0ユーザーが呼び出し経路を要求する
  • ユーザーは自動的に Auth0 認証プロセスにリダイレクトされます (プロバイダーを選択するための Auth0 ログイン フォーム、次にプロバイダー ログイン画面)。
  • /auth/successユーザーはルートにリダイレクトされます
  • /auth/successリダイレクトを静的 html ページにルーティングし、ユーザーのトークンを含む Cookiepublic/success.htmlも送信しますjwt-token
  • クライアント側では、public/success.html読み込み時に Feathers クライアントauthenticate()メソッドが Cookie からトークンを読み取り、それをローカル ストレージに保存します。

これ以降、Feathers クライアントは、ローカル ストレージから Cookie を読み取るユーザーを認証します。

このシナリオを単一ページのアプリケーション アーキテクチャに適応させ、次のプロセスを実装しようとしました。

  • sourceSPA から、 SPA URL を含むクエリ文字列パラメーターを使用して認証 API を呼び出します。例えば:http://my-api.com/auth/auth0?source=http://my-spa.com
  • サーバー側の/auth/auth0ルート ハンドラーで、その URL を格納するための Cookie を作成します。
  • ログインに成功したら、 sourceCookie を読み取ってユーザーを SPA にリダイレクトし、JWT トークンを Cookie で送信します。

しかし、特定のドメイン (API サーバー ドメイン) に Cookie を設定して、ユーザーを別のドメインにリダイレクトすることができないため、最後の手順は機能しませんでした。(これについては Stackoverflow で詳しく説明しています)

実際、私は次の方法で問題を解決しました。

  • サーバー側: URL ハッシュを使用してトークンをクライアントに送り返します。
  • クライアント側: URL ハッシュからトークンを読み取る新しい html ページを作成します

サーバー側コード:

// Add a middleware to write in a cookie where the user comes from
// This cookie will be used later to redirect the user to the SPA
app.get('/auth/auth0', (req, res, next) => {
  const { origin } = req.query
  if (origin) {
    res.cookie(WEB_CLIENT_COOKIE, origin)
  } else {
    res.clearCookie(WEB_CLIENT_COOKIE)
  }
  next()
})

// Route called after a successful login
// Redirect the user to the single-page application "forwarding" the auth token
app.get('/auth/success', (req, res) => {
  const origin = req.cookies[WEB_CLIENT_COOKIE]
  if (origin) {
    // if there is a cookie that contains the URL source, redirect the user to this URL
    // and send the user's token in the URL hash
    const token = req.cookies['feathers-jwt']
    const redirectUrl = `${origin}/auth0.html#${token}`
    res.redirect(redirectUrl)
  } else {
    // otherwise send the static page on the same domain.
    res.sendFile(path.resolve(process.cwd(), 'public', 'success.html'))
  }
})

クライアント側、auth0.htmlSPA のページ

SPA で、次のauth0.html3 つのことを行う新しい html ページを作成しました。

  • ハッシュからトークンを読み取ります
  • ローカル ストレージに保存します (Feathers クライアントの動作を模倣するため)。
  • ユーザーをSPAのメインページにリダイレクトしますindex.html

html コード:

<html>
<body>
  <script>
  function init() {
    const token = getToken()
    if (!token) {
      console.error('No auth token found in the URL hash!')
    }
    // Save the token in the local storage
    window.localStorage.setItem('feathers-jwt', token)
    // Redirect to the single-page application
    window.location.href = '/'
  }

  // Read the token from the URL hash
  function getToken() {
    const hash = self.location.hash
    const array = /#(.*)/.exec(hash)
    if (!array) return
    return array[1]
  }

  init()
  </script>
</body>
</html>

これで、SPA で Feathers クライアントを使用して、アプリの起動時にローカル ストレージからトークンを読み取ることができます。

それが理にかなっているかどうか教えてください、ありがとう!

于 2016-11-13T13:16:05.253 に答える