プロキシとゲートウェイの背後に Web アプリをデプロイする

ASP.NET Core WebアプリをMicrosoft.Identity.Webを使用してリバースプロキシ、ロードバランサー、またはAzureゲートウェイの背後にデプロイするとき、認証コールバックを成功させるには、redirect URIを適切に処理する必要があります。

リダイレクト URI は、次の理由でプロキシ シナリオで複雑になります。

  • Microsoft Entra IDは、サインイン後にユーザーを構成済みのリダイレクト URI にリダイレクトします
  • プロキシは要求コンテキストを変更します -スキーム (HTTP/HTTPS)、ホスト、ポート、パス
  • Redirect URI は、Microsoft Entra IDに登録されているもの正確に一致する必要があります
  • CallbackPath はプロキシ経由で動作する必要があります

一般的なプロキシ シナリオを特定する

次のシナリオは、さまざまなプロキシ アーキテクチャがリダイレクト URI の構築にどのように影響するかを示しています。

Azure Application Gateway

ユース ケース: リージョン負荷分散、WAF、SSL 終了

リダイレクト URI への影響:

  • ゲートウェイ URL: https://gateway.contoso.com/myapp
  • バックエンド URL: http://backend.internal/
  • Microsoft Entra ID リダイレクト: https://gateway.contoso.com/myapp/signin-oidc

Azure Front Door

ユース ケース: グローバル分散、CDN、複数のリージョン

リダイレクト URI への影響:

  • フロントドア URL: https://myapp.azurefd.net
  • バックエンド URL: https://app-eastus.azurewebsites.nethttps://app-westus.azurewebsites.net
  • Microsoft Entra ID リダイレクト: https://myapp.azurefd.net/signin-oidc

オンプレミスのリバース プロキシ

ユース ケース: 企業ネットワーク、既存のインフラストラクチャ

リダイレクト URI への影響:

  • プロキシ URL: https://apps.corp.com/myapp
  • バックエンド URL: http://appserver:5000/
  • Microsoft Entra ID リダイレクト: https://apps.corp.com/myapp/signin-oidc

Kubernetes イングレス

ユース ケース: コンテナー オーケストレーション、マイクロサービス

リダイレクト URI への影響:

  • イングレス URL: https://apps.k8s.com/webapp
  • サービス URL: http://webapp-service.default.svc.cluster.local
  • Microsoft Entra ID リダイレクト: https://apps.k8s.com/webapp/signin-oidc

転送されたヘッダーを構成する

転送されたヘッダーは、プロキシのデプロイに不可欠です。 これを使用しないと、バックエンド アプリによって正しくないリダイレクト URI が作成されます。

転送されたヘッダーが重要な理由

Web アプリ には、次の適切な要求コンテキストが必要 です。

  1. Microsoft Entra IDの絶対リダイレクト URI を構築する
  2. 受信認証応答を検証する
  3. 正しいサインアウト URI を生成する
  4. HTTPS 要件の適用を処理する

転送ヘッダー用のミドルウェアが使用されていない場合:

User visits: https://gateway.contoso.com/myapp
Backend sees: http://localhost:5000/
Redirect URI built: http://localhost:5000/signin-oidc  Wrong!
Microsoft Entra ID redirects to: https://gateway.contoso.com/myapp/signin-oidc
Backend doesn't recognize it: Error!

転送されたヘッダー ミドルウェアの場合:

User visits: https://gateway.contoso.com/myapp
Backend sees forwarded headers: X-Forwarded-Proto: https, X-Forwarded-Host: gateway.contoso.com
Redirect URI built: https://gateway.contoso.com/myapp/signin-oidc  Correct!
Microsoft Entra ID redirects to: https://gateway.contoso.com/myapp/signin-oidc
Backend recognizes it: Success!

基本的な転送ヘッダーを設定する

認証の前に、 Program.cs で転送されたヘッダー ミドルウェアを構成します。

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

// CRITICAL: Configure forwarded headers BEFORE authentication
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;

    // Accept headers from any source (proxy/gateway)
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();

    // Standard header names
    options.ForwardedForHeaderName = "X-Forwarded-For";
    options.ForwardedProtoHeaderName = "X-Forwarded-Proto";
    options.ForwardedHostHeaderName = "X-Forwarded-Host";
});

// Authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddRazorPages();

var app = builder.Build();

// CRITICAL: Use forwarded headers BEFORE authentication
app.UseForwardedHeaders();

// Only enforce HTTPS if you're sure the proxy forwards the scheme correctly
if (!app.Environment.IsDevelopment())
{
    app.UseHttpsRedirection();
}

app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

appsettings.jsonに認証設定を追加します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "CallbackPath": "/signin-oidc"
  }
}

Microsoft Entra アプリの登録で、ゲートウェイ URL をリダイレクト URI として登録します。

https://gateway.contoso.com/myapp/signin-oidc

パスベースのルーティングを処理する

プロキシが要求にパス プレフィックスを追加する場合は、パスベースのルーティングを使用します。

問題: プロキシがパス プレフィックスを追加する

シナリオ:

  • プロキシ URL: https://apps.contoso.com/webapp1
  • バックエンド URL: http://backend:5000/
  • バックエンドは / についてのみ認識しており、/webapp1 については認識していません。

UsePathBaseを設定して、そのパス プレフィックスについてアプリに通知します。

var app = builder.Build();

// Tell the app it's hosted at a path prefix
app.UsePathBase("/webapp1");

app.UseForwardedHeaders();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

しくみ:

  • HttpContext.Request.Path は、ルーティングの /webapp1 プレフィックスを削除します
  • HttpContext.Request.PathBase/webapp1を含む
  • リンクの生成にパス ベースが自動的に含まれる
  • リダイレクト URI にパス ベースが自動的に含まれる

Microsoft Entra アプリ登録時に完全なパスを登録します。

https://apps.contoso.com/webapp1/signin-oidc

解決策 2: プロキシがパスを書き換える

一部のプロキシでは、転送前にパス プレフィックスが削除されます。 パスを書き換えて元のヘッダーを転送するようにプロキシを構成します。

NGINX の構成:

location /webapp1/ {
    proxy_pass http://backend:5000/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Original-URL $request_uri;
}

プロキシがプレフィックスを削除する場合、アプリケーションで PathBase は必要ありません。

// No PathBase needed if proxy strips the prefix
app.UseForwardedHeaders();

Microsoft Entra アプリの登録にプロキシに接続する URL を登録します。

https://apps.contoso.com/webapp1/signin-oidc

ソリューション 3: 動的 PathBase のカスタム ミドルウェア

パス ベースが環境によって異なる場合は、構成から読み取るか、要求ヘッダーから検出します。

// Read path base from configuration or headers
var pathBase = builder.Configuration["PathBase"];
if (!string.IsNullOrEmpty(pathBase))
{
    app.UsePathBase(pathBase);
}

// Or detect from X-Forwarded-Prefix header
app.Use((context, next) =>
{
    var forwardedPrefix = context.Request.Headers["X-Forwarded-Prefix"].ToString();
    if (!string.IsNullOrEmpty(forwardedPrefix))
    {
        context.Request.PathBase = forwardedPrefix;
    }
    return next();
});

app.UseForwardedHeaders();

SSL/TLS 終了の処理

プロキシが SSL/TLS を終了すると、ヘッダー転送を構成しない限り、バックエンドは HTTP 要求を受信し、正しくないリダイレクト URI を作成します。

問題: プロキシが HTTPS を終了する

シナリオ:

  • ユーザーが HTTPS 経由でプロキシに接続する
  • プロキシが HTTP 経由でバックエンドに接続する
  • バックエンドが HTTP リダイレクト URI をビルドする (間違っています!)

解決策: X-Forwarded-Proto ヘッダー

バックエンドが元のスキームを認識できるように、 X-Forwarded-Proto ヘッダーを送信するようにプロキシを構成します。

プロキシ構成 (NGINX):

location / {
    proxy_pass http://backend:5000;
    proxy_set_header X-Forwarded-Proto $scheme;  # Critical!
    proxy_set_header X-Forwarded-Host $host;
}

転送された proto ヘッダーを読み取り、要求スキームを設定するようにアプリを構成します。

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

var app = builder.Build();

app.UseForwardedHeaders(); // Reads X-Forwarded-Proto and sets Request.Scheme = "https"

// HTTPS redirection becomes safe
app.UseHttpsRedirection(); // Won't create infinite redirect loop

app.UseAuthentication();

一般的な間違い: HTTPS リダイレクト ループ

問題:

// Without UseForwardedHeaders()
app.UseHttpsRedirection(); // Sees Request.Scheme = "http", redirects to HTTPS
// User gets infinite redirect loop!

Solution:

// WITH UseForwardedHeaders()
app.UseForwardedHeaders(); // Sets Request.Scheme = "https" from X-Forwarded-Proto
app.UseHttpsRedirection(); // Sees HTTPS, no redirect needed 

カスタム ドメインを構成する

Azure Front Door付きのカスタム ドメインを使用して、バックエンド サービスへのトラフィックのルーティング中にブランド化された URL をユーザーに提示します。

シナリオ: Azure Front Doorを介したカスタム ドメイン

アーキテクチャ:

  • カスタム ドメイン: https://myapp.contoso.com
  • Front Door: https://myapp.azurefd.net (バックエンドのオリジン)
  • Azure Web アプリ: https://myapp-backend.azurewebsites.net

Front Door の構成:

  1. Front Door にカスタム ドメイン myapp.contoso.com を追加する
  2. SSL 証明書の構成 (Front Door マネージドまたはカスタム)
  3. バックエンド プールを myapp-backend.azurewebsites.net
  4. HTTPS のみを有効にする

Front Door から転送されたヘッダーを受け入れるようにアプリを構成します。

// No special configuration needed if headers are forwarded correctly
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

Microsoft Entra アプリの登録に、サインインとサインアウトの両方のコールバック URI を登録します。

https://myapp.contoso.com/signin-oidc
https://myapp.contoso.com/signout-callback-oidc

次の診断エンドポイントを使用して、アプリによって生成されるリダイレクト URI を確認します。

// In a controller or page
public IActionResult TestRedirectUri()
{
    var request = HttpContext.Request;
    var scheme = request.Scheme; // Should be "https"
    var host = request.Host.Value; // Should be "myapp.contoso.com"
    var pathBase = request.PathBase.Value; // Should be "" or your path base
    var path = "/signin-oidc";

    var redirectUri = $"{scheme}://{host}{pathBase}{path}";
    // Expected: https://myapp.contoso.com/signin-oidc

    return Content($"Redirect URI would be: {redirectUri}");
}

複数のリダイレクト URI を登録する

アプリが複数の環境で異なるゲートウェイの背後で実行されている場合は、それぞれにリダイレクト URI を登録します。

問題: 同じアプリ、複数のゲートウェイ

シナリオ:

  • 生産: https://app.contoso.com (フロントドア)
  • ステージング: https://app-staging.azurewebsites.net (ダイレクト)
  • 開発: https://localhost:5001 (ローカル)

解決策: すべてのリダイレクト URI を登録する

すべての環境固有のリダイレクト URI を、Microsoft Entra アプリの登録に追加します。

https://app.contoso.com/signin-oidc
https://app-staging.azurewebsites.net/signin-oidc
https://localhost:5001/signin-oidc

アプリケーション コードでは、環境固有の変更は必要ありません。

var app = builder.Build();

app.UseForwardedHeaders(); // Handles proxy scenarios
app.UseAuthentication(); // Builds correct redirect URI based on request context

しくみ:

  • アプリケーションが受信要求に基づいてリダイレクト URI を動的に構築する
  • HttpContext.Request.SchemeHost、および URI を決定PathBase
  • Microsoft Entra IDに登録されている限り、認証は成功します

Azure Application Gateway を構成する

このセクションでは、パスベースのルーティングを使用してAzure Application Gatewayの背後に Web アプリをデプロイするための完全な構成例を示します。

パスベースのルーティングを使用した完全な例

Application Gateway の設定:

バックエンド プール:

  • ターゲット: backend.azurewebsites.net または IP アドレス

HTTP 設定:

  • プロトコル: HTTPS (推奨) または HTTP
  • ポート: 443 または 80
  • バックエンド パスをオーバーライドする: いいえ
  • カスタム プローブ: はい

ヘルスプローブ:

  • プロトコル: HTTPS または HTTP
  • ホスト: 空白のままにします (バックエンド プールのホスト名を使用)
  • パス: /health (匿名エンドポイントである必要があります)
  • 間隔: 30 秒

ルーティング規則:

  • 名前: webapp-rule
  • リスナー: ポート 443 の HTTPS リスナー
  • バックエンド プール: あなたのバックエンド プール
  • HTTP 設定: あなたのHTTP設定

転送されたヘッダー、認証、正常性プローブを処理するようにアプリケーションを構成します。

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// Forwarded headers for Application Gateway
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

// Authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));

// Health checks (for Application Gateway probe)
builder.Services.AddHealthChecks();

builder.Services.AddRazorPages();

var app = builder.Build();

// Health endpoint BEFORE authentication (critical for gateway probes)
app.MapHealthChecks("/health").AllowAnonymous();

// Middleware order
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

appsettings.jsonに認証設定を追加します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "CallbackPath": "/signin-oidc"
  }
}

Microsoft Entra アプリの登録にゲートウェイに接続するリダイレクト URI を登録します。

https://gateway.contoso.com/signin-oidc
https://gateway.contoso.com/signout-callback-oidc

Azure Front Doorの構成

このセクションでは、一貫した認証を使用して、Azure Front Doorの背後に複数リージョンの Web アプリをデプロイする方法について説明します。

複数リージョンの Web アプリのデプロイ

シナリオ:

  • Front Door: https://app.azurefd.net (グローバル エンドポイント)
  • 米国東部: https://app-eastus.azurewebsites.net
  • 米国西部: https://app-westus.azurewebsites.net
  • 最も近いリージョンにルーティングされたユーザー

Front Door の構成:

配信元グループ:

  • 名前: webapp-origins
  • ヘルスプローブ: /health
  • 負荷分散: レイテンシーベース

起源:

  1. app-eastus.azurewebsites.net (優先順位 1)
  2. app-westus.azurewebsites.net (優先順位 1)

ルート:

  • パス: /*
  • 転送プロトコル: HTTPS のみ
  • 配信元グループ: webapp-origins

同じアプリケーション コードを両方のリージョンにデプロイします。

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// Forwarded headers for Front Door
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddHealthChecks();
builder.Services.AddRazorPages();

var app = builder.Build();

// Health check for Front Door probe
app.MapHealthChecks("/health").AllowAnonymous();

app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();

app.Run();

どちらのリージョンも、同じ Microsoft Entra アプリ登録同じリダイレクト URIと共有します。

https://app.azurefd.net/signin-oidc
https://app.azurefd.net/signout-callback-oidc

動作する理由:

  • Front Door URL はリージョン間で一貫しています
  • 転送されたヘッダーにより、バックエンドが正しいリダイレクト URI をビルドすることを確認する
  • トークンの取得はリージョン バックエンドで行われます
  • 分散トークン キャッシュ (Redis) は、リージョン間でトークンを共有します

一般的な問題のトラブルシューティング

このセクションでは、プロキシデプロイでの最も一般的な認証エラーとその解決方法について説明します。

問題: "リダイレクト URI の不一致" エラー

症状:

AADSTS50011: The redirect URI 'http://localhost:5000/signin-oidc'
specified in the request does not match the redirect URIs configured
for the application 'your-app-id'.

考えられる原因:

  1. 転送されたヘッダー ミドルウェアが見つかりません

    // Fix: Add BEFORE authentication
    app.UseForwardedHeaders();
    app.UseAuthentication();
    
  2. Microsoft Entra ID に誤って登録されたリダイレクト URI

    • Azure ポータルで登録済みのURIを確認する。
    • 運用環境で HTTPS (HTTP ではなく) を確認する
    • ホストが一致していることを確認する (標準以外の場合はポートを含む)
    • パスに PathBase が含まれていることを確認します (該当する場合)
  3. プロキシがヘッダーを転送しない

    • プロキシの構成を確認する
    • X-Forwarded-ProtoX-Forwarded-Hostが設定されていることを確認する
    • curl を使用してテストする: curl -H "X-Forwarded-Proto: https" -H "X-Forwarded-Host: gateway.com" http://backend:5000/
  4. PathBase が構成されていません

    // If proxy adds /myapp prefix, add this:
    app.UsePathBase("/myapp");
    

次の診断ミドルウェアを追加して、アプリがビルドするリダイレクト URI をログに記録します。

// Add this middleware to log the redirect URI being built
app.Use(async (context, next) =>
{
    var logger = context.RequestServices.GetRequiredService<ILogger<Program>>();
    logger.LogInformation(
        "Request: Scheme={Scheme}, Host={Host}, PathBase={PathBase}, Path={Path}",
        context.Request.Scheme,
        context.Request.Host,
        context.Request.PathBase,
        context.Request.Path);

    await next();
});

問題: 認証はローカルで機能しますが、プロキシの背後には機能しません

症状:

  • サインインはlocalhost:5001で動作します。
  • サインインが失敗する gateway.contoso.com
  • エラー: リダイレクト URI の不一致または関連付けの失敗

ソリューションのチェックリスト:

  1. 転送されたヘッダーを最初に構成して使用する
app.UseForwardedHeaders(); // Must be first!
  1. プロキシで必要なヘッダーが転送される
  • X-Forwarded-Proto: https
  • X-Forwarded-Host: gateway.contoso.com
  • 省略可能: パス ベースのX-Forwarded-Prefix
  1. Microsoft Entra ID に登録されたリダイレクトURI
  • https://gateway.contoso.com/signin-oidc
  1. 必要に応じて PathBase を構成する
app.UsePathBase("/myapp"); // If proxy adds prefix
  1. HTTPS が正しく適用される
app.UseForwardedHeaders(); // Reads X-Forwarded-Proto first
app.UseHttpsRedirection(); // Then enforces HTTPS

問題: Sign-Out が失敗するか、間違った URL にリダイレクトされる

症状:

  • サインインが正常に動作します
  • サインアウトにより、間違った URL (localhost、http://、間違ったホスト) にリダイレクトされる

転送された要求コンテキストを使用して PostLogoutRedirectUri を設定します。

// Ensure PostLogoutRedirectUri uses correct base URL
builder.Services.Configure<OpenIdConnectOptions>(
    OpenIdConnectDefaults.AuthenticationScheme,
    options =>
    {
        options.Events.OnRedirectToIdentityProviderForSignOut = context =>
        {
            // Build correct post-logout redirect URI
            var request = context.HttpContext.Request;
            var postLogoutUri = $"{request.Scheme}://{request.Host}{request.PathBase}/signout-callback-oidc";

            context.ProtocolMessage.PostLogoutRedirectUri = postLogoutUri;
            return Task.CompletedTask;
        };
    });

Microsoft Entra アプリの登録にサインアウト コールバック URI を登録します。

https://gateway.contoso.com/signout-callback-oidc

問題: 無限リダイレクト ループ

症状:

  • ブラウザーがアプリとMicrosoft Entra IDの間でリダイレクトを続ける
  • ログインが完了しない

考えられる原因:

  1. 転送されたヘッダーの前の HTTPS リダイレクト

    // WRONG ORDER:
    app.UseHttpsRedirection(); // Sees HTTP, redirects to HTTPS
    app.UseForwardedHeaders(); // Too late!
    
    // CORRECT ORDER:
    app.UseForwardedHeaders(); // Sets scheme to HTTPS
    app.UseHttpsRedirection(); // Sees HTTPS, no redirect
    
  2. プロキシと互換性のない Cookie 設定

    builder.Services.Configure<CookiePolicyOptions>(options =>
    {
        options.MinimumSameSitePolicy = SameSiteMode.None; // For cross-site scenarios
        options.Secure = CookieSecurePolicy.Always; // Requires HTTPS
    });
    
  3. Cookie ドメインの不一致

    // If subdomain issues, may need to set cookie domain
    builder.Services.ConfigureApplicationCookie(options =>
    {
        options.Cookie.Domain = ".contoso.com"; // Allows cookies across subdomains
    });
    

ベスト プラクティスに従う

一般的な落とし穴を避けるために、これらのプラクティスをすべてのプロキシデプロイに適用します。

1. 常に転送ヘッダー ミドルウェアを使用する

// For ANY deployment behind proxy/gateway/load balancer
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

var app = builder.Build();
app.UseForwardedHeaders(); // FIRST middleware!

2. すべてのリダイレクト URI を登録する

Microsoft Entra アプリの登録ですべての環境のリダイレクト URI を登録します。

Production:  https://app.contoso.com/signin-oidc
Staging:     https://app-staging.azurewebsites.net/signin-oidc
Development: https://localhost:5001/signin-oidc

3. リダイレクト URI の生成をテストする

開発専用診断エンドポイントを追加して、リダイレクト URI を確認します。

// Add diagnostics endpoint (development only!)
if (app.Environment.IsDevelopment())
{
    app.MapGet("/debug/redirect-uri", (HttpContext context) =>
    {
        var redirectUri = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.PathBase}/signin-oidc";
        return Results.Ok(new { redirectUri });
    }).AllowAnonymous();
}

4. ゲートウェイ プローブの正常性エンドポイント

ゲートウェイ プローブがサインインを必要としないように、認証ミドルウェアの前に正常性エンドポイントをマップします。

// Must be BEFORE authentication middleware
app.MapHealthChecks("/health").AllowAnonymous();

app.UseAuthentication(); // Health endpoint bypasses this

5. マルチリージョンの分散トークン キャッシュ

Redis などの分散キャッシュを使用して、リージョン間でトークンを共有します。

// Use Redis for token cache across regions
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration["Redis:ConnectionString"];
    options.InstanceName = "TokenCache_";
});

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

6. トラブルシューティング用のログ記録を構成する

Microsoft.Identity.Webのデバッグ ログおよび転送されたヘッダーを有効にして問題を診断します。

builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging"));

// In appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.Identity.Web": "Debug",
      "Microsoft.AspNetCore.HttpOverrides": "Debug"
    }
  }
}

完全な例を確認する

このエンド ツー エンドの例では、Microsoft Graph統合を使用して、Azure Application Gatewayの背後に Web アプリをデプロイします。

アプリケーション コード

次の Program.cs では、転送されたヘッダー、Microsoft Graphによる認証、正常性チェックが構成されます。

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;

var builder = WebApplication.CreateBuilder(args);

// Forwarded headers for Application Gateway
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

// Authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph()
    .AddInMemoryTokenCaches();

// Health checks
builder.Services.AddHealthChecks();

// Add Microsoft Identity UI for sign-in/sign-out
builder.Services.AddRazorPages()
    .AddMicrosoftIdentityUI();

var app = builder.Build();

// Health endpoint (before authentication)
app.MapHealthChecks("/health").AllowAnonymous();

// Middleware order is critical
app.UseForwardedHeaders();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();

app.Run();

認証とログ記録の構成を appsettings.jsonに追加します。

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "CallbackPath": "/signin-oidc",
    "SignedOutCallbackPath": "/signout-callback-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.Identity.Web": "Information",
      "Microsoft.AspNetCore.HttpOverrides": "Debug"
    }
  }
}

Microsoft Entra アプリの登録に次の URI を登録します。

リダイレクト URI:

https://gateway.contoso.com/signin-oidc
https://gateway.contoso.com/signout-callback-oidc

フロント チャネル ログアウト URL:

https://gateway.contoso.com/signout-oidc

Application Gateway の構成

次の Application Gateway リソースを構成します。

バックエンド プール:

  • 名前: webapp-backend
  • ターゲット: webapp.azurewebsites.net または IP アドレス

HTTP 設定:

  • 名前: webapp-https-settings
  • プロトコル:HTTPS
  • ポート: 443
  • バックエンド パスをオーバーライドする: いいえ
  • バックエンド ターゲットからホスト名を選択する: はい
  • カスタム プローブ: はい → webapp-health-probe

ヘルスプローブ:

  • 名前: webapp-health-probe
  • プロトコル:HTTPS
  • バックエンド HTTP 設定からホスト名を選択する: はい
  • パス: /health
  • 間隔: 30 秒
  • 異常しきい値: 3

リスナー:

  • 名前: webapp-listener
  • フロントエンド IP: パブリック
  • プロトコル:HTTPS
  • ポート: 443
  • SSL 証明書: あなたの証明書

ルーティング規則:

  • 名前: webapp-rule
  • ルールの種類: 基本
  • リスナー: webapp-listener
  • バックエンド ターゲット: webapp-backend
  • HTTP 設定: webapp-https-settings