Microsoft Entra ID 経由の Google サインインでプロフィール情報(氏名・写真)が取得できない原因と解決策

Microsoft Entra ID 経由で Google サインインを実装したのに、トークンのクレームから氏名やアイコン写真(プロフィール画像)が取れない――この現象は“設定ミス”というより、Entra が担う役割を理解すると納得できる挙動です。原因の切り分けと、確実にプロフィール情報を取得する実装パターンを整理します。

目次

起きていること:アプリが見ているのは「Google のトークン」ではなく「Entra のトークン」

Microsoft Entra ID に Google を外部 ID プロバイダーとして追加してサインインさせる場合、アプリが最終的に受け取るのは Entra が発行したトークン(Entra ID トークン) です。ここが最重要ポイントです。

外部プロバイダー連携は、しばしば「Google でログイン=Google のプロフィールがそのまま返ってくる」と誤解されがちですが、Entra が間に入る構成では次のような“役割分担”になります。

登場人物役割アプリが受け取る主な成果物期待しがちな誤解
Google外部 ID プロバイダー(本人確認の元)(Entra に対して)Google の認証結果・トークン「Google のクレームがアプリへ素通しされる」
Microsoft Entra IDブローカー/認証基盤(アプリに対する発行者)Entra が発行したトークン「外部プロバイダーの情報がトークンに全部入る」
あなたのアプリリライングパーティ(トークンの利用者)Entra トークンのクレーム「name/picture が必ず入る」

つまり、アプリがクレームを覗いても Google の氏名・写真が見つからないのは、珍しいことではありません。Entra がアプリに対して“保証できる範囲”の属性(最小限の識別情報、構成によってはメール)に寄せて発行するためです。

症状の典型:氏名・写真が取れない/空になる/期待するクレーム名が存在しない

「プロフィール情報が取れない」と一口に言っても、現場では次のような形で現れます。

  • Entra の ID トークン(JWT)に name / given_name / family_name / picture が存在しない
  • 存在しても空文字、または期待と違う(例:表示名がメールアドレスのローカル部になる)
  • メールアドレスは取れるが、写真 URL だけがどうしても取れない
  • Google 側ではプロフィール写真を設定しているのに、アプリには来ない
  • 「Google の sub(Google 固有 ID)」を期待したが、Entra 側のユーザー識別子しか出てこない

この症状は、Entra が“Google のアカウント情報をそのままアプリに渡す設計”ではなく、Entra のディレクトリ上のユーザー表現として正規化し、必要最小限のクレームでアプリに渡す設計に寄っていることが背景にあります。

まず確認すべき:あなたがデコードしている JWT の発行者(iss)はどこか

トラブルシューティングで最初にやるべきは、トークンの中身を「どこの発行者のトークンなのか」で整理することです。JWT をデコードし、iss(issuer)を確認します。

確認項目見る場所意味判断の目安
iss(issuer)JWT クレームそのトークンを“発行した主体”Entra のドメインなら「Entra トークン」。Google なら「Google トークン」
aud(audience)JWT クレーム想定される受け手(クライアント)あなたのアプリ(クライアント ID)か
scp / rolesJWT クレーム権限(API 呼び出しの可否)プロフィール取得の権限とは別概念。過信しない
idp / tfp など(構成により)JWT クレーム外部 IDP やポリシーの痕跡「Google 経由でログインした」事実確認に有用

もし iss が Entra 側の値であれば、あなたが現在扱っているのは Google の ID トークンではなく、Entra の ID トークンです。その時点で「Google の picture クレームが入っていない」は自然な結論になります。

結論:Entra のトークンだけで Google のプロフィール情報を“完結”させようとすると詰まりやすい

ここからが本題です。あなたが欲しいのは「Google のプロフィール情報(氏名・写真など)」であり、しかし手元にあるのは「Entra のトークン」。このギャップを埋めるには、方針を明確にする必要があります。

実務で現実的な落としどころは、大きく次の 3 パターンです。

解決パターン何をするか向いているケース注意点
Google のトークンで Google に取りに行くGoogle のアクセストークン/ID トークンを取得し、UserInfo などでプロフィール取得写真が必要、Google の最新プロフィールを反映したい、将来 Google API も呼ぶEntra だけのログインより実装が増える(同意・スコープ・トークン管理)
アプリ側でプロフィールを持つ初回ログイン後に氏名・写真を入力/アップロードしてもらい、以後はアプリ DB を参照写真は UI 用途だけ、認証方式が複数(Google/Apple/メール等)で統一したいユーザー入力の UX が必要。同期はしない(割り切る)
Entra の属性マッピングで“取れる範囲”だけ取るdisplayName/email 等、Entra が扱える範囲のクレームを整える氏名やメールが取れればよい(写真までは不要)写真は難しいことが多い。取れる属性は構成・仕様で変わる

以降では、最も“確実にプロフィール情報を得る”方向として、Google のトークンを使って Google から取得するパターンを中心に解説し、その上で「Entra を使い続けるための現実的な設計」も整理します。

最優先で押さえる:プロフィール取得の最短ルートは UserInfo エンドポイント

Google のプロフィール属性(氏名、写真 URL など)をアプリで取りたいなら、OpenID Connect の基本に立ち返るのが最短です。代表的なのが次の UserInfo エンドポイントです。

Google OpenID Connect UserInfo
https://openidconnect.googleapis.com/v1/userinfo

ここへ Google のアクセストークンを付けて呼び出すと、ユーザーの基本プロフィール(name, picture など)を JSON で取得できます。重要なのは、Entra のアクセストークンではなく Google のアクセストークンで呼ぶことです。

UserInfo で返りやすい属性の例

返ってくる項目は状況やスコープにより変動しますが、基本的には次のようなフィールドが出ることが多いです(例)。

フィールド意味用途例注意点
subGoogle 側の安定識別子アプリ内の連携キー(Google アカウントとの紐付け)メールより安定。メール変更に強い
name表示名(フルネーム)UI 表示本人が変更できる。本人確認用途に使わない
given_name / family_name名/姓宛名、フォーム初期値文化圏で構造が合わないことがある
pictureプロフィール写真 URLアイコン表示URL は変わり得る。外部 URL 参照の設計が必要
emailメールアドレス連絡先、ログイン補助表示一意キーにしない(変更され得る)
email_verifiedメール検証済みか登録フローの分岐“アプリ側での到達確認”とは別物

curl での呼び出し例

サーバーサイド(推奨)で、Google のアクセストークンを使って呼びます。

curl -H "Authorization: Bearer GOOGLE_ACCESS_TOKEN" \
  https://openidconnect.googleapis.com/v1/userinfo

レスポンス例(概形):

{
  "sub": "109876543210123456789",
  "name": "Taro Yamada",
  "given_name": "Taro",
  "family_name": "Yamada",
  "picture": "https://lh3.googleusercontent.com/a/....",
  "email": "[email protected]",
  "email_verified": true,
  "locale": "ja"
}

Entra のトークンに picture が入らない問題は、UserInfo を使うと「必要な情報を、必要な発行者(Google)から直接取る」構造になるため、根本的に解消しやすくなります。

ここが落とし穴:Entra 経由ログインだけだと「Google のアクセストークン」を手元に持っていない

ただし、UserInfo を叩くためには Google のアクセストークンが必要です。ところが Entra を認証の入り口にしていると、アプリが持っているのは Entra のトークンだけで、Google のアクセストークンがアプリに渡ってこない構成が一般的です。

この点を見落とすと、「UserInfo を呼べばいいのは分かった。でも Google のトークンがない」という状態になります。ここから先は、設計として次のどちらかを選びます。

  • 設計A:認証(Entra)とプロフィール取得(Google OAuth)を分ける(二段階の連携)
  • 設計B:Entra 側の仕組み(構成)で Google トークンを受け渡せるようにする(可能なら)
  • 設計C:Google からの取得を諦め、アプリ側プロフィールへ寄せる

どれが正解かは、あなたの要件(写真が必須か、Google API を呼ぶ予定があるか、同意画面を許容できるか)で決まります。

設計A:サインインは Entra、プロフィールは「追加の Google OAuth」で取得する(現場で強い)

最も分かりやすく、将来拡張にも強いのがこの構成です。

流れ

  1. ユーザーは Entra を経由して Google でサインイン(あなたのアプリは Entra トークンを受け取る)
  2. アプリは「プロフィール同期/Google 連携」の導線を表示(初回ログイン直後が分かりやすい)
  3. ユーザーに Google OAuth 同意を行ってもらい、Google のアクセストークンを取得
  4. バックエンドが UserInfo を呼び、氏名・写真 URL を取得して保存

「同じ Google でログインしたのに、なぜもう一度 Google の同意が必要なのか」と思われがちですが、目的が違います。

フェーズ目的必要なものユーザー体験
Entra 経由サインインアプリにログインさせる(本人確認)Entra が発行するトークン「ログイン」
Google OAuth 連携Google の情報を読む(プロフィールやAPI)Google アクセストークン(必要スコープ)「連携・許可」

実務では、ログインはできたがプロフィールが空だと違和感が出るため、初回ログイン時に次のような分岐を作ると自然です。

  • 写真や氏名が必須:初回ログイン直後に「プロフィールを同期する」フローへ誘導
  • 必須ではない:まずは最低限で利用開始し、設定画面から同期できるようにする

Google OAuth のスコープは最小限から始める

プロフィール取得だけが目的なら、スコープはむやみに増やさず、まずは OIDC の基本スコープ(openId / profile / email)に寄せるのが無難です。

スコープ狙い取得できる可能性がある情報設計メモ
openidOpenID Connect としての認証sub 等の識別子UserInfo を使う前提の土台
profile基本プロフィールname, picture など“写真が欲しい”なら基本的に必要
emailメール情報email, email_verified登録・通知に必要なら

「写真だけほしいのに、なぜ profile が必要?」となりがちですが、Google の基本プロフィールは profile にまとまっていることが多いため、まずは profile を付けた設計を検討します。

実装のポイント:アクセストークンは“できるだけサーバー側で扱う”

UserInfo を呼ぶための Google アクセストークンは、扱いを間違えると漏えいやすい重要情報です。特に SPA(フロントエンドのみ)で完結させる場合は保管場所が課題になります。

おすすめの原則は次の通りです。

  • アクセストークンは可能ならバックエンドで受け取り、バックエンドから UserInfo を呼ぶ
  • フロントに渡すのは「取得したプロフィール情報(表示名、写真URL等)」のみにする
  • 必要なスコープを最小化し、後から増やす(ユーザー同意も段階的に)

設計B:Entra 側で“外部 IDP のトークン”を受け渡せるか検討する(できる場合だけ)

環境によっては、Entra(特に B2C/External ID のカスタム構成)で外部 IDP から受け取った情報やトークンを、アプリに返すクレームとして出力できるケースがあります。ただし、これは常に可能な一般解ではなく、製品・設定・セキュリティ要件に左右されます。

ここでは「検討観点」を整理します。実装に踏み込む前に、次の質問に答えられるかが重要です。

確認したいこと理由YES の場合NO の場合
外部 IDP(Google)のアクセストークンをアプリへ渡せる設計かUserInfo を呼ぶには Google トークンが必要Entra トークンに埋める/バックエンドに渡すなど検討設計A(追加 OAuth)か設計C(アプリ側プロフィール)へ
トークン受け渡しがセキュリティ/監査上許容されるか外部トークンは漏えい時の影響が大きいバックエンド限定、短期利用、保管しない等の対策が必要外部トークンを扱わない設計に寄せる
ユーザー同意とスコープ指定を制御できるかprofile/email の同意が必要になる同意画面の文言・導線も含めて設計アプリ側入力で完結させる

もし「外部トークンを受け渡す」方針にするなら、次のような運用ルールをセットで決めると事故を減らせます。

  • 外部アクセストークンをフロントへ配布しない(原則バックエンド限定)
  • 外部アクセストークンを永続保存しない(必要なら暗号化と期限、失効導線)
  • プロフィール取得後はトークンを破棄し、表示用データだけ保持する

「写真が欲しいだけ」なら、外部トークン受け渡しはオーバーキルになることも多いため、次の設計Cも現実解として強いです。

設計C:プロフィールはアプリのマスタに寄せる(いちばんトラブルが少ない)

Google の氏名・写真を“自動で”取りたい気持ちは分かりますが、運用を始めると「取得できないユーザーが一定数出る」「同意を嫌がる」「写真 URL が変わって表示が壊れる」などの現実に当たります。

そこで、認証とは切り離して、プロフィールはアプリ側のユーザーマスタを正にする設計は非常に安定します。

初回ログイン後の登録画面を用意する

おすすめの UX は「初回ログイン直後に 30 秒で終わるプロフィール登録」です。外部ログインの種類が増えても壊れません。

項目初期値の入れ方ユーザーが編集できるか備考
表示名取れる場合は Entra クレームを初期値にできる名寄せや本人確認とは切り離す
プロフィール写真未設定(デフォルトアイコン)できるアップロード/アバター選択にすると安定
メール取れる場合は初期値に要件次第通知先として検証プロセスを別で持つと堅い

この設計にしておくと、「Entra から返るクレームの差分」や「Google 側の仕様変更」「写真 URL の寿命」などの外部要因に振り回されにくくなります。特に B2B/B2C をまたぐサービスや、Apple/LINE 等も並行サポートする予定がある場合は、アプリ側プロフィールマスタ化が効きます。

それでも “Entra トークンだけで” 取れる可能性がある情報と、期待値の置き方

ここまで「Entra のトークンでは Google プロフィールが取れない」と強めに書きましたが、実際には Entra 側の設定やマッピング次第で、氏名やメールなど一部は取れるケースがあります。ただし、写真(picture)まで期待すると詰まりやすい、というのが実務上の感触です。

期待値を整理するため、Entra トークンに入ってきやすい情報と、入りにくい情報を分けて考えます。

カテゴリEntra トークンで入りやすい入りにくい/保証しづらい理由
識別子ユーザー ID(Entra 内部の識別)Google の sub をそのままEntra が自分の世界のユーザーとして発行するため
連絡先メール(設定や同意が整っていれば)複数メール、補助メール最小限に寄せられる
表示系表示名(取れても簡易)写真(picture)写真は URL 管理やプライバシーが絡みやすい

「アプリの UI にアイコンを出したい」という要件は多い一方で、写真は本人が変更しやすく、URL が変わりやすく、外部参照の可用性にも左右されます。ここは仕様上の“保証が弱い領域”として捉え、アプリ側での保管・アップロード・デフォルト表示を用意しておくと運用が安定します。

実装例:Google UserInfo を呼ぶ(Node.js / C# のイメージ)

ここでは「Google アクセストークンが手元にある」前提で、UserInfo を呼んでプロフィールを取得する例を示します。アクセストークンの取得は、あなたのアプリ構成に合わせて(設計AまたはB)行ってください。

Node.js(fetch)

async function fetchGoogleUserInfo(googleAccessToken) {
  const res = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
    headers: {
      Authorization: `Bearer ${googleAccessToken}`,
    },
  });

if (!res.ok) {
const body = await res.text();
throw new Error(`UserInfo failed: ${res.status} ${body}`);
}

const userInfo = await res.json();

// 例:必要な情報だけ取り出す
return {
googleSub: userInfo.sub,
name: userInfo.name ?? null,
pictureUrl: userInfo.picture ?? null,
email: userInfo.email ?? null,
emailVerified: userInfo.email_verified ?? null,
};
}

C#(HttpClient)

using System.Net.Http.Headers;
using System.Text.Json;

public async Task FetchGoogleUserInfoAsync(string googleAccessToken)
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", googleAccessToken);


var res = await http.GetAsync("https://openidconnect.googleapis.com/v1/userinfo");
var body = await res.Content.ReadAsStringAsync();

if (!res.IsSuccessStatusCode)
    throw new Exception($"UserInfo failed: {(int)res.StatusCode} {body}");

using var doc = JsonDocument.Parse(body);
var root = doc.RootElement;

return new GoogleUserInfo
{
    Sub = root.TryGetProperty("sub", out var sub) ? sub.GetString() : null,
    Name = root.TryGetProperty("name", out var name) ? name.GetString() : null,
    Picture = root.TryGetProperty("picture", out var pic) ? pic.GetString() : null,
    Email = root.TryGetProperty("email", out var email) ? email.GetString() : null
};


}

public class GoogleUserInfo
{
public string? Sub { get; set; }
public string? Name { get; set; }
public string? Picture { get; set; }
public string? Email { get; set; }
}

ここで得られた picture URL は、単純に DB に保存して UI に出すだけでも動きますが、長期運用を考えると次の方針が安全です。

  • picture URL はキャッシュとして扱い、取れなければデフォルトアイコンにフォールバック
  • 「同期」ボタンで再取得できるようにする(URL の変化に対応)
  • 外部 URL をそのまま使うのが怖いなら、画像をダウンロードして自社ストレージに保管(利用規約・プライバシー配慮が前提)

よくあるハマりどころと解決の指針

「Entra のトークンに picture を入れたい」と考え続けてしまう

まず、Entra が発行するトークンは Entra の裁量でクレームが決まります。外部プロバイダーのクレームをそのまま期待すると、検証に時間を溶かしやすいです。

指針:写真など外部プロフィール属性が本当に必要なら、Google から直接取る(UserInfo)か、アプリ側プロフィールに寄せる。

スコープが足りず、UserInfo が期待通り返らない

UserInfo はアクセストークンの権限に依存します。openId だけで行けると思い込むと、name/picture が出ないことがあります。

指針:profile/email を必要に応じて付け、同意画面でユーザーが許可したことを確認する。必要最小限から始める。

メールアドレスを一意キーにしてしまう

Google のメールはユーザーが変えられます(転送やエイリアス、変更、管理ポリシー)。メールを主キーにすると、将来の名寄せで苦労します。

指針:Google の sub、または Entra 側の不変 ID を“内部キー”として持ち、メールは属性として扱う。

写真 URL の扱いが雑で、表示が壊れる/混在コンテンツになる

外部 URL は、期限・リダイレクト・参照元制限などで突然表示できなくなる可能性があります。

指針:デフォルトアイコンを用意し、写真は“あると嬉しい”扱いにする。必要なら自社保管に切り替える。

セキュリティとプライバシーの要点(短くても必ず押さえる)

プロフィール情報の取得は UI の話に見えて、実はセキュリティとプライバシーが密接です。特にアクセストークンを扱う設計では、最低限次を守ると事故が減ります。

観点推奨避けたい
トークンの保管バックエンドで短期利用し破棄フロントの永続領域(localStorage 等)に長期保存
スコープ最小限(openid/profile/email)から将来のために過剰な権限を最初から要求
表示名・写真の扱い表示用途に限定し、本人確認に使わない「名前が一致するから本人」などの誤った判定
ユーザーへの説明何を取得し、何に使うかを UI で明示同意の意味が分からない導線

プロフィールはあくまで“表示用の便利情報”として設計し、認可・本人確認の根拠にしないことが重要です。認証の根拠はトークンの検証(署名、iss、aud、exp など)に寄せ、表示情報は別レイヤーで取り扱うのが堅牢です。

まとめ:設計の主語を「どの発行者の情報を、どのトークンで取りに行くか」に戻す

Entra ID 経由で Google サインインしているとき、アプリが見ているのは Entra のトークンです。そこに Google の氏名や写真が十分に入らないのは、設計として自然です。

Google のプロフィール(氏名・アイコン写真など)を確実に扱いたいなら、次のどれかに寄せると解決が早く、運用も安定します。

  • Google のトークンを取得し、UserInfo(https://openidconnect.googleapis.com/v1/userinfo)で取る
  • 写真まで含めたプロフィールはアプリ側で管理し、初回ログインで登録してもらう
  • Entra のクレームは“取れる範囲”に留め、過度な期待を置かない

「Entra のトークンに Google の情報が入っていない」という現象を“バグ”として追いかけるより、必要なプロフィール情報を正しい発行者(Google)から、正しい手段(Google トークン+API)で取得する設計へ切り替えるのが、最短ルートになります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次