PLAY DEVELOPERS BLOG

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

OAuth 2.0 クライアントID作成から Gmail API 呼び出しまで

皆さん、こんにちは。 プラットフォーム技術部の林と申します。

前回の投稿から気づけば2年が経ってしまいました。 しばらくご無沙汰しておりましたが、また記事を書いてみようと思います。

もし以前の記事の Playwright にご興味がある方は、こちらもぜひご覧ください。
developers.play.jp

今回は、個人的に学習している Google APIOAuth 認証について、Google Cloud Console とバックエンドに焦点を当てて解説します。フロントエンドとバックエンドの役割を分け、バックエンドで Gmail API を使って実際にメールを送信するまでの流れを紹介します。

OAuthとは

OAuth(Open Authorization)は、ユーザーが自分のIDやパスワードを直接アプリに渡さず、Google、Facebook、X(旧Twitter)などの信頼できる外部サービスを経由して、自分の情報や利用権限をアプリに共有できるようにする「認可」の仕組みを提供するプロトコルです。

より詳しい仕組みについてはこちらをご覧ください

developers.play.jp

Gmail APIとは

Gmail API は、Google が提供するAPIで、ユーザーの Gmail メールボックスにアクセスしたり、メールの送受信・管理を行ったりできます。 今回は OAuth を使った認可 により取得したトークンを用いて、アプリケーションから Gmail を経由してメールを送信する方法を紹介します。

Google Cloud Console の設定手順

今回はGoogleのOAuthGmail APIを利用するため、先のGoogle側から説明します。
まずはGoogle アカウントでGoogle Cloud Consoleにログインします。

Google Cloud Platform

プロジェクトを作成

Google Cloud Console にログインしたら、次はアプリやサービスごとに管理するため、新しいプロジェクトを作成します。

  • 左上のプロジェクト選択 → 新しいプロジェクトを作成
  • 任意の名前を付けて作成

Fig. 1 プロジェクト作成

  • 対象
    • 今回は OAuth の動作確認をしますが、他のGoogle ユーザーに利用させたくないため、対象は内部を選択してください。

Fig. 2 対象

Fig. 3 連絡先情報

Fig. 4 終了

Gmail API を有効化

プロジェクトを作成した後、バックエンドから Gmail API を利用するためには、まずプロジェクト内で Gmail API を有効化する必要があります。 この手順により、作成したアプリケーションがGoogleのGmailサービスにアクセスし、メールの送受信や情報取得などを行えるようになります。

  • 検索ボックスにGmail APIと入力

Fig. 5 Gmail API検索

  • Gmail APIを選択し、有効にするボタンをクリック

Fig. 6 Gmail有効化

OAuth 同意画面の設定

Gmail APIを利用する際、ユーザーはOAuth同意画面を介して、アプリケーションに自身のGmailデータへのアクセスを許可する必要があります。そのため、これからこの同意画面を設定します。

Fig. 7 OAuth認証画面

  • 検索ボックスにブランディングと入力

Fig. 8 ブランディング

  • アプリ名
    • ユーザーに表示されるアプリの名前
  • サポートメール
    • 問い合わせ用のメールアドレス
  • デベロッパーの連絡先情報
    • プロジェクトの変更について Google からお知らせするために使用

Fig. 9 ブランディング設定

同意画面にアクセス可能テストアカウント設定

今回の目的は OAuth の動作確認であるため、意図しないユーザーが同意画面にアクセスしないよう、アクセス可能なアカウントを制限します。
これにより、OAuth フローの動作確認を安全に実施できます。

  • 検索ボックスに対象と入力

Fig. 10 対象検索

  • OAuth同意画面にアクセス可能なGoogleアカウントを設定します

Fig. 11 テストユーザー設定

OAuth クライアントID作成

バックエンドで Gmail API を利用するには、アプリケーション自身がGoogleによって信頼されていることを証明するための トークン が必要です。この トークン を取得するためには、事前に取得した クライアントIDクライアントシークレット が不可欠となります。

トークンがなければ、バックエンドから Gmail API を呼び出すことはできません。
そのため、引き続き クライアントIDクライアントシークレット を取得する手順について説明します。

  • 検索ボックスにクライアントと入力

Fig. 12 クライアント検索

  • クライアントを作成ボタンから作成に遷移
  • アプリケーションの種類
    • バックエンドを利用するため、今回の例では、ウェブアプリケーションを選択
  • 承認済みの JavaScript 生成元
    • ブラウザから直接 Google API にアクセスする場合にのみ必要です。今回の構成ではバックエンド経由で送信するため設定不要です
  • 承認済みのリダイレクト
    • 認証完了後、Google が結果を返す URL例: http://localhost:{ポート番号}/oauth2callback
  • 作成すると クライアントIDクライアントシークレット が発行されるので記録します

Fig. 13 クライアントID作成

データアクセス設定

OAuthで認証を行う際、アプリケーションがどのGoogle APIにアクセスできるかを定義する必要があります。そのために、データアクセススコープを設定します。

このスコープ設定の画面には、有効化されていないAPIのスコープは表示されません。そのため、先にGmail APIを有効化する手順を完了していない場合、この画面で Gmail API のスコープを選択することはできませんのでご注意ください。

  • 検索ボックスにデータアクセスと入力

Fig. 14 データアクセス

  • 今回はGmail APIを利用するので、スコープを追加または削除https://mail.google.com/を追加します

Fig. 15 スコープ追加・削除

これで、Google 側の設定が全部終わりました。次はバックエンドの設定を説明します。

バックエンドの設定

OAuth認証を用いてメール送信を行うバックエンドは、フロントエンドからのリクエストを受け取り、Gmail APIを介してメールを送信する役割を担います。ここでは、Node.jsとExpressを使ったバックエンドの構成例を説明します。

ライブラリのインストール

まず、プロジェクトのディレクトリで以下のコマンドを実行し、必要なライブラリをインストールします。

npm install express googleapis
  • express
    • ウェブサーバーの構築
  • googleapis
    • Googleの公式ライブラリ
ディレクトリ構造例例

以下のシンプルなディレクトリ構造で進めます。

/backend
  ├─ server.js
  ├─ send.js
  └─node_modules/
server.js

このファイルは、Expressサーバーの起動、OAuthのトークン取得処理、そしてメール送信リクエストの受付を担います。

まず、OAuth2Clientを作成します。これはクライアントIDなどを用いて、Google APIへの認証を管理するためのオブジェクトです。

次に、/authエンドポイントにアクセスすることで、ユーザーをOAuth認証画面にリダイレクトします。access_type: 'offline'prompt: 'consent'を設定することで、リフレッシュトークンを取得できるようになります。これは、一度認証すれば、ユーザーがオフラインでも継続してAPIを利用するために不可欠です。

ユーザーが認証を許可すると、Googleから/oauth2callbackエンドポイントにcodeが返されます。このcodeを使ってoAuth2Client.getToken()を呼び出すことで、トークンを取得できます。

メール送信リクエストの部分は後のsend.jsで説明します。

server.js

// OAuth クライアント作成
const oAuth2Client = new google.auth.OAuth2(
  クライアントID,
  クライアントシークレット,
  クライアントID作成時に定義したリダイレクトURL,
);

// サーバー起動
const PORT = ポート番号;
app.listen(PORT, () => {
  console.log(`サーバー起動 http://localhost:${PORT}`);
});

// OAuth認証画面に遷移(トークン取得URL)
app.get('/auth', (_, res) => {
  const url = oAuth2Client.generateAuthUrl({
    access_type: 'offline', 
    scope: ['https://mail.google.com/'],
    prompt: 'consent',
  });
  res.redirect(url);
});

// 認証後のコールバック(トークンを取得)
app.get('/oauth2callback', async (req, res) => {
  const code = req.query.code;
  try {
    const { tokens } = await oAuth2Client.getToken(code);
    db.put(tokens); // データベースに格納 ( 疑似コード )
    res.send('トークン取得完了!');
  } catch (err) {
    console.error('Error retrieving tokens:', err);
    res.status(500).send('トークン取得失敗');
  }
});

// メール送信パス
app.post('/send', async (req, res) => {
  try {
    const { toEmail, subject, text } = req.body;
    await gmailSend(toEmail, subject, text);
    console.log('メール成功');
    return res.status(200).json({ success: true });
  } catch (err) {
    console.error('メール送信エラー:', err);
    return res.status(500).json({ success: false, error: err.message });
  }
});

これでserver.jsの設定が終わりました。実際にサーバーを起動しましょう。

ターミナルで以下のコマンドを実行します。

node server.js

起動したら、以下のURLにアクセスして認証を行い、トークンを取得してください。

http://localhost:{ポート番号}/auth

Fig. 16 OAuth認証画面

トークンの分類
  • アクセストークン
    • デフォルトでは発行から1時間有効です
  • リフレッシュトークン
    • 6ヶ月間使用されないと自動的に無効になります
    • Gmail のスコープがある場合、ユーザーがパスワードを変更すると無効になります

備考: セキュリティを保つため、有効期限が長い リフレッシュトークン は厳重に保管し、API 呼び出しには直接使用しません。API 呼び出しには、有効期限が短い アクセストークン を使用します。
oAuth2Client.setCredentials({ アクセストークン, リフレッシュトークン}) を使って両方設定している場合、アクセストークンが期限切れになったときに自動でリフレッシュトークンを使って更新されます。

send.js

このファイルでは、Googleの公式ライブラリgoogleapisを使用してGmail APIを呼び出し、メール送信を行います。

最後に、/sendエンドポイントでメール送信リクエストを受け付けます。

send.js

// OAuth クライアント作成
const oAuth2Client = new google.auth.OAuth2(
  クライアントID,
  クライアントシークレット,
  クライアントID作成て定義したリダイレクトURL,
);

// トークンを設定
const tokens = db.get(); // 疑似コード
oAuth2Client.setCredentials(tokens);

/**
 * Gmail APIを使ってメールを送信する
 * @param {string} toEmail - 送信先のメールアドレス
 * @param {string} subject - 件名
 * @param {string} text - 本文
 */
export async function gmailSend(toEmail, subject, text) {
  const gmail = google.gmail({ version: 'v1', auth: oAuth2Client });
  const rawMessage = Buffer.from(
    `To: ${toEmail}\r\n` +
    `Subject: ${subject}\r\n` +
    `Content-Type: text/html; charset="UTF-8"\r\n\r\n` +
    text
  )
    .toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');

  return await gmail.users.messages.send({
    userId: 'me',
    requestBody: { raw: rawMessage },
  });
}

これで、実際送信すると。。。

Fig. 17 メール内容

無事に送信できました!!!

まとめ

前回の投稿からもう2年ぶりになりますので、皆さんに気に入っていただければ嬉しいです。
まだまだ勉強が必要なことも多いですが、一緒に進めていけたらと思います。
では!

参考文献

JavaScript クイックスタート  |  Gmail  |  Google for Developers

Buffer | Node.js v22.18.0 Documentation