🔎

Algoliaで特定のユーザーのデータのみしか検索できないようにする

2020/12/24に公開

この記事は Algolia Advent Calendar 2020 24 日目の記事です。この記事では、ユースケースとしてよくありそうな利用方法について解説します。機能自体は、この記事最下部の参考の欄に載せている公式ドキュメントにも掲載されているのでそちらもあわせてご覧ください。

Algolia とは

フルマネージドな Search as a Service です。レスポンスがとても速く、サクッと全文検索を導入したいときに非常に便利です。ElasticSearch などの従来の検索エンジンと違うのは、Web ブラウザ、ネイティブアプリなどのいわゆるクライアントサイドから直接 Algolia の API を叩けるように設計されています。Firebase を頻繁に使う私にとっては非常に扱いやすく、検索が必要になったときには必ずと言っていいほどお世話になっています。

ちなみに 2020 年 7 月頃に料金体系が変わっており、これ以前に利用を検討されていた場合に無料のみではなかなか使えなかった方も、使って見やすい体系になっているのでそちらもご確認いただくとよいかもしれません。(料金プランが変わっていて驚いている当時の私)

コレ以上の情報がほしい方は、ぜひ公式サイトAdvent Calendar のページに行って他の記事を読んでみてください 👍

Secured API Key

クライアントから直接 Algolia の API を叩いて検索するため、アクセスコントロールを行うには少し工夫が必要です。例えば Notion や Evernote のようなノートテイキングサービスの場合を考えてみます。キーワードで自身のすべてのノートから検索する機能を作りたいとしましょう。

Algolia でこれを実現する場合、prod_notesという Index(RDB で例えるならば Table)に全ユーザーのノートを登録しておくことになります。Algolia のコンソールにある Search-only API Key を使って、クライアント側で userID で filtering すると一応は実現できます。しかし、ブラウザから通信を覗くと Search-only API Key も Index の名前も見えてしまうため、悪用すれば他人のノートが容易に取得できてしまいます(※公式ドキュメントにも記載されていますが API Key はクライアント側にハードコードすべきではありません)。

これに対応するために、Secured API Key(virtual)を活用します。Algolia のコンソールに載っている API Key をベースにして Algolia 上では管理されないバーチャルな API Key を作成でき、これを各ユーザーごとに作成してクライアント側から利用します。例えば、Firestore を利用している場合ですと/algoliaKeys/:userIDに adminSDK を使って Secured API Key を保存しておき、クライアントからそれを読み取って Algolia の API を叩く形になります。

Algolia の API Key の便利なところは、必ず適用させたい filtering や limit などの設定を API Key 自体に埋め込んでおけるところです。今回のケースだと、各ユーザーごとに自身の userID での filtering を設定した API Key を生成してクライアントで利用させれば、必ず自身のデータからしか検索できないようになります。

では実際に生成してみましょう。

Secured API Key を生成する

コンソールでの設定

Algolia のコンソールから Indexprod_notesを作成します。Configuration タブを押して左のメニューから Facets を押し、Attributes for faceting にuserIDを追加し、filter only に変更しておきます(👇 の画像参照)。

Secured API Key のベースとなる Key を作成します。コンソールから API Keys を開いて、All API Keys のタブを押し、右上にある New API Key を押します(👇 の画像参照)。

Indecies には対象の Index 名(prod_notes)を入れて、その他の項目は要件に合わせて設定していきます。私は hits には念の為 100 を設定しておくことが多いです(👇 の画像参照)。ここで設定した内容は、これから生成する Secured API Key にも引き継がれることにご注意ください。共通で設定しておきたい内容をここで適用できるイメージですね。

コードから Secured API Key を生成する

ここからは TypeScript で記述していきます。バックエンド側で実行するようにしてください。また、他言語で利用される方は公式ドキュメントを参照いただくか、各 SDK のインターフェースは共通だと思いますので適宜読み替えてください。

SDK をインストールします。

$ npm i algoliasearch
$ npm i -D @types/algoliasearch

Secured API Key を生成する関数を作成します。

import algolia from 'algoliasearch'

const client = algolia('your app id', 'your Admin API Key')

export const generateSecuredAPIKey = async (userID: string) => {
  return client.generateSecuredApiKey('先程作っておいたベースとなるSearch Key', {
    filters: `userID:${userID}`,
  })
}

この関数を呼べば、userID で必ず filtering される API Key が生成できます 🎉 あとは各ユーザーがこの Key を取得できるように DB に保存しておけば OK です。

おわりに

Algolia はとても便利なサービスですが、API Key の仕組みを理解して活用しないと悪用されてしまったときに、とんでもない利用をされてしまったり脆弱性を生み出してしまったりする可能性があります。公式ドキュメントをしっかり読んだ上で活用していきたいですね 🙌

ちなみに、この記事は中の人 @shinodoggさんにお誘いいただき書くことになりました。ありがとうございます 🕺

参考

Discussion