https://d226lax1qjow5r.cloudfront.net/blog/blogposts/using-vonage-apis-with-mongodb-atlas-part-2/mongodb_vonage_p2.png

MongoDB AtlasでVonage APIを使う - パート2

最終更新日 May 4, 2023

所要時間:1 分

このシリーズでは

前回に引き続き、MongoDB AtlasとVonageの各種APIを紹介します。パート 1 では MongoDB Atlas がどんなもので、どんなサービスを提供しているのかを見てきました。パート2では、サンプルアプリケーションに飛び込んで、MongoDB を使ってどのように登録プロセスをバックアップし、さらに Vonage Verify を使ってユーザーセキュリティを強化するかを見ていきます。

Vonage Verifyとは何ですか?

Verify二要素認証サービスです。簡単なAPIコールでユーザーにコードを送信し、別のAPIコールでその有効性をチェックすることができます。これにより、ユーザが自分のパスワードを知っているだけでなく、コードを受け取るための物理的なデバイスを持っていることを確認することで、さらなるセキュリティを提供します。ほとんどの人がモバイル・デバイスを持っているので、そのデバイスでコードを受け取ることができると仮定するのはかなり安全だ。

Vonage Verifyはお客様に代わってコードを生成し、お客様に連絡します。また、さまざまな方法でお客様に複数回連絡しようとします。例えば、お客様が一定の時間内に顧客からのコードを検証しようとしない場合、当社は自動メッセージで顧客に電話をかけ、コードを提供しようとします。それでもお客様がコードを入力しなかったり、電話に出なかったりした場合は、再度SMSを試みます。ワークフロー(Workflows)と呼ばれるものを使って、どのように顧客に連絡を取るかをコントロールすることができます。

当社のレガシーVerify製品は、顧客とのコンタクトにSMSとVoiceをサポートしています。 ベリファイ製品は、SMS、Voice、WhatsApp、Eメール、デバイスベースの認証チャネルを完全にカスタマイズ可能なワークフローでサポートしています。どちらの製品も、顧客に通知を手動で送信し、その応答を追跡する手間を省きます。 また、苦情メッセージを送信したり、電話会社のスパムフィルターに引っかかったりする心配もありません。

あなたはAPIリクエストを私たちに送り、私たちはコードを送り、あなたはそれをVerifyするだけです。

データベースの作成

私たちのデモを動かすには、ユーザーが注文する食べ物が必要です!MongoDBデータベースに情報を追加するのは、PostgresやMySQLのような伝統的なリレーショナルデータベース管理システムにデータを追加するのとは少し違います。MongoDBはドキュメントベースのシステムなので、テーブルでデータベースを作るのではなく、コレクションでデータベースを作ります。このCollectionsにはドキュメントが格納されます。ドキュメントとはJSONのような特別なドキュメントで、これを検索して使うことができます。

最初のデータベースを作ってみましょう。MongoDB Atlas のダッシュボードから コレクションを見るボタンをクリックします。

MongoDB DashboardMongoDB Dashboard

これでクラスター内のすべての情報が表示される。今のところ、データベースも情報もないので、かなり素っ気ない。ユーザーが購入できる食品をいくつか追加してみましょう。をクリックしてください。 自分のデータボタンをクリックします。

Adding DataAdding Data

そして、データベース名とコレクション名を尋ねます。私たちのデモでは、"restaurant_pos_demo" とします。 データベース名そして コレクション名.デモはすでにこのデータベースとコレクションを探すように設定されているので、カスタム名ではなく、これらの名前を使用してください。入力が完了したら 作成ボタンをクリックします。

Create new CollectionCreate new Collection

これでデータを入力できる。次に ドキュメントの挿入ボタンをクリックする。ドキュメント・エディターが表示されます。情報を入力するためのドロップダウンが表示されますが、ドキュメントを貼り付けることもできます。をクリックします。 {}ボタンをクリックしてテキスト入力モードに切り替え、ハンバーガー・ドキュメントのJSONの小さなブロックを貼り付ける。をクリックして 挿入をクリックすると、インベントリアイテムが保存されます。もう一度この操作を行いますが、2回目はソーダ・ドキュメントをペーストします。

// Document 1
{
  "name": "Hamburger",
  "price": 995
}

// Document 2
{
  "name": "Soda",
  "price": 199
}

Document EditorDocument Editor

つのドキュメントを入力すると、データベースビューでそれらを見ることができます。このエディターは、データベースを構築している間、ドキュメントやデータで遊ぶのに最適な方法です。大規模な本番環境では、クエリを実行してデータをフィルタリングすることができますが、今のところ、これはデータを入力する良い迅速な方法です。

DocumentsDocuments

デモのセットアップ

これでデータがいくつか揃ったので、デモを配線することができる。デモを https://github.com/Vonage-Community/sample-mongodb-vonage-integration-restaurant-demo.webapp" フォルダにはソースコードがあり、"app-service" フォルダには後で使う MongoDB の設定があります。とりあえず、"webapp" フォルダに入って、好きなエディタで開いてください。

アプリケーションで MongoDB クラスタと通信できるように、設定の詳細を追加する必要があります。リポジトリに .env.distファイルをコピーして .env.このファイルには、インストールに必要な情報がすべて含まれます。

を開き .envを開き、以下の変更を加える:

  1. ENABLE_Verify "を "1 "に変更し、Vonage Verify APIの動作を確認できるようにする。

  2. VONAGE_API_KEY」をVonage Customer Dashboardで利用可能なVonage APIキーに設定します。

  3. VONAGE_API_SECRET」をVonage Customer Dashboardで利用可能なVonage APIシークレットに設定します。

  4. JWT_SIGNING_KEY」を任意の値に変更する。この文字列は実際には重要ではないが、後でAPIコールを検証するために使用する。

また、"MONGODB_DSN" の値をクラスタの接続文字列に設定する必要があります。この値を調べるには、MongoDB Atlas のダッシュボードで 接続ボタンをクリックします。ポップアップで アプリケーションを接続する.接続文字列が表示されます。その値をコピーして、"MONGODB_DSN" の値に貼り付けます。 .env.の <password>部分をクラスタのパスワードに変更してください。

Connecting to the applicationConnecting to the application

これでデモを実行できるはずだ!

デモの実行

デモ自体は、Vite、Vue.js、Typescriptを使って作られている。デモを実行するには、フロントエンドのクライアント・アプリケーションとバックエンドのサーバー・アプリケーションの両方を実行する必要がある。2つのコマンドライン・ターミナルを開いてください。

最初のターミナルで webapp/フォルダで npm ciを実行してすべての依存関係をインストールし、次に npm run dev.すべてが正しく行われていれば、"Vite <version>「という画面が表示され ローカルへのリンクが表示されます。 http://localhost:5173.ポート5173をリッスンしている他のものがある場合、リンクは少し異なるかもしれません。

つ目の端末で webapp/server.他のウィンドウと同様に npm ciを実行してすべての依存関係をインストールし、次に npm run dev.この画面には nodemonと表示され、最終的に "Server Started" と表示されるはずです。接続できないというエラーが表示されたら、MongoDB クラスタの接続文字列を確認します。

Starting the demoStarting the demo

ブラウザーを開き http://localhost:5173/website/login(ポート番号は、Viteがあなたのために実行していると言っているものに置き換えてください)。以下のログイン画面が表示されます!

Login PageLogin Page

Verifyを試す

現在ユーザーはいないので、ユーザーを作りましょう。をクリックしてください。 またはフレーバー登録リンクをクリックします。ユーザー名、パスワード、携帯電話番号を入力します。電話番号には国番号のプレフィックスを含め、ダッシュ記号は使用しないでください。ユーザーログインの一部として、この携帯電話番号に二要素認証コードを送信しますので、Google Voice番号ではなく、必ず実際の携帯電話番号を使用してください。米国の場合は、「15556661234」のようになります。

ユーザー情報を入力したら 登録.

これでログインできるはずです。登録したばかりのユーザー名とパスワードを入力してください。認証に成功すると、2FAコードの入力を求める小さなフォームが表示されます。

M2FA Form2FA Form

数秒後、4桁のコードが記載されたSMSが届くはずです。そのコードをフォームに入力し 送信.うまくいくと、ハンバーガーとソーダの注文画面が表示されます!

どのように機能するのか?

ユーザがログインすると、Vue.jsクライアント側アプリケーションはユーザ名とパスワードをバックエンドサーバに送信します。 /api/website/authenticate.このルートはMongoDBクラスタに直接接続し、ユーザーを usersコレクションからユーザーを見つけます。新しいユーザーを登録すると、MongoDBは自動的にコレクションを作成して、そのユーザーのドキュメントを保存します。このドキュメントを取得し、パスワードをドキュメントに保存されているハッシュ化されたコピーと比較します。

MongoDB Node.jsクライアントはフルエントクライアントなので、メソッドコールをつなげてクエリを生成できる。この行は

const userRecord = await client.db('restaurant_pos_demo').collection('users').findOne({ username });

MongoDB クライアントに、"restaurant_pos_demo" データベースを使い、"users" コレクションで検索し、リクエストで指定された "username" を持つドキュメントをひとつ見つけるように指示します。パスワードは bcrypt ハッシュとして保存されているので bcrypt.compare()を使って、ユーザが入力したパスワードと、 ユーザのドキュメントに保存したパスワードを照合することができます。もし一致すれば、ユーザは正しいパスワードを入力したことになります!

// webapp/server/server.ts

app.all('/api/website/authenticate', async (req, res) => {
    const { username, password } = req.body
    const userRecord = await client.db('restaurant_pos_demo').collection('users').findOne({ username });

    if (userRecord) {
        await bcrypt.compare(password, userRecord.password)
            .then(async (match) => {
                if (match) {
                    const token = jwt.sign({user_id: userRecord._id }, process.env.JWT_SIGNING_KEY, { expiresIn: '15m'})
                    let verifyId = {request_id: 'abcd'};
                    if (process.env.ENABLE_VERIFY === "1") {
                        verifyId = await vonage.verify.start({number: userRecord.phone, brand: 'Vonage Restaurant'})
                        console.log(verifyId);
                    } else {
                        console.log('Verify Disabled');
                    }
                    
                    res.status(200).json({ token, verifyId: verifyId.request_id })
                } else {
                    res.status(401).send()
                }
            })
        return
    }

    res.status(401)
    res.send()
    return
})

そして、Vue.jsアプリケーションに送り返す一時的なJWTを生成します。Vue.jsアプリケーションは、ユーザーがクライアント側アプリケーションでコードを入力するときに、この一時的なJWTを使用します。デモで "ENABLE_VERIFY "でVerifyが有効になっている場合、Vonage Node.jsアプリケーションでこのJWTを使用します。 Vonage Node.js SDKを使用して Verify API を呼び出します。ユーザの電話番号を渡し、ブランドを "Vonage Restaurant "に設定します。ユーザがSMSメッセージや音声通話を受信すると、"Vonage Restaurant "として識別されます。

Vonage APIは "リクエストID "を返します。これをフロントエンドに送り返し、このリクエストIDを使ってユーザーからのコードをチェックします。そして、一時的なJWTトークンとリクエストIDをVue.jsアプリに送り返します。

ユーザーが本人であることを確認したら、Vue.jsのフォームを2FAコードの入力を求めるように変更した。ユーザーがコードを入力すると、Vue.jsアプリはトークン、Verify Request ID、ユーザーが入力したコードを含むリクエストを /api/website/authenticate/verifyに、トークン、VerifyリクエストID、ユーザが入力したコードとともにリクエストを送信する。

JWTにはユーザーのドキュメントIDが含まれているので、トークンをデコードしてMongoDBでユーザーを検索する。もし見つかったら、Verify APIを呼び出します。 check()メソッドを使い、リクエストIDとコードを送ります。コードが一致すればAPIは成功を返す。一致すれば、有効期限の長い本物のJWTを生成し、Vue.jsアプリケーションに返す。

// webapp/server/server.ts

app.all('/api/website/authenticate/verify', async (req, res) => {
    const { token, verifyId, tfaPin } = req.body
    const decodedToken = jwt.decode(token)
    const userRecord = await client.db('restaurant_pos_demo').collection('users').findOne({ _id: new ObjectId(decodedToken.user_id) });

    if (userRecord) {
        if (process.env.ENABLE_VERIFY === "1") {
            await vonage.verify.check(verifyId, tfaPin)
                .then(resp => {
                    console.log(resp)
                    const token = jwt.sign({user_id: userRecord._id }, process.env.JWT_SIGNING_KEY, { expiresIn: '2h'})
                    res.status(200).json({ token })
                })
                .catch(err => {
                    console.error("there was an error", err);
                })
            return
        } else {
            const token = jwt.sign({user_id: userRecord._id }, process.env.JWT_SIGNING_KEY, { expiresIn: '2h'})
            res.status(200).json({ token })
        }
    }

    res.status(500)
    res.send()
    return
})

Vue.jsアプリケーションは、適切なJWTを取得した時点で、私たちが完全に認証されたことを認識します。このトークンは "authenticationStore "と呼ばれるグローバル・ストアに保存され、アプリケーションの残りの部分はこのJWTを使用して、それ以降のAPI呼び出しでユーザーを認証します。

// src/views/Website/Login.vue

const verify = async() => {
    fetch(import.meta.env.VITE_API_URL + '/api/website/authenticate/verify', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            token: tempJWT.value,
            verifyId,
            tfaPin: tfaPin.value
        })
    })
        .then(resp => resp.json())
        .then(async (json) => {
            console.log(json)
            authStore.setToken(json.token)
            router.push({ name: 'website.order' });
            
            return
        })
        .catch(err => console.log(err)); 
}

結論

アプリケーションにすでに認証ステップがある場合、Vonage Verifyを追加するのはほんの数行の追加コードで済みます。私たちのVue.jsアプリでは、バックエンドへの追加の呼び出しと新しいフォームを意味し、サーバー側では、コードを送信するためのAPI呼び出しと、コードを検証するための新しいルートを作るだけでした。Vonageがコードの生成、送信、チェックという重労働をすべて処理してくれるので、コードベースへの影響は最小限です。MongoDBのドキュメントベースのストレージの柔軟性により、データベースのマイグレーションを実行する必要がなく、新しいユーザーを挿入してルックアップを行うコードをすぐに書くことができました。

ユーザーがログインできるようになったので、何か食べ物を注文するべきだ!

次のセクションでは、MongoDB を使って注文を保存し、Vonage SMS API を使って注文確認を送信します。また、Vonage Meetings API を使って、顧客サービス解決用のアプリケーションにビデオ会議を素早く追加する方法についても見ていきます。

シェア:

https://a.storyblok.com/f/270183/384x384/3bc39cbd62/christankersley.png
Chris Tankersleyデベロッパー・リレーションズ・ツーリング・マネージャー

クリスはデベロッパー・リレーションズ・ツーリング・マネージャーで、お気に入りのツールを開発するチームを率いています。彼は15年以上、クライアントワークからビッグデータ、大規模システムに至るまで、様々な言語と種類のプロジェクトでプログラミングをしてきました。オハイオ州に住み、家族と過ごしたり、ビデオゲームやTTRPGゲームをしたりしている。