はじめに
HttpClient を使って http で Authorization ヘッダー付きのリクエストを送信し、https にリダイレクトされると、https のリクエストには Authorization ヘッダーが付かない。
以下、実験コード。
Web API
HTTP リクエストのヘッダーをログに出力している。リダイレクト前のリクエストヘッダーを確認するために、ログを出力するミドルウェアも挟んでいる。
using System.Text; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace HttpsRedirectSample { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.Use(next => context => { LogRequestHeaders(context); return next(context); }); app.UseHttpsRedirection(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { LogRequestHeaders(context); await context.Response.WriteAsync("Hello World!"); }); }); } static void LogRequestHeaders(HttpContext context) { var sb = new StringBuilder(); foreach (var h in context.Request.Headers) { sb.AppendLine($"{h.Key}:{h.Value}"); } var logger = context.RequestServices .GetService<ILoggerFactory>() .CreateLogger("RequestHeaders"); logger.LogInformation(sb.ToString()); } } }
Client
適当な値の Authorization ヘッダーを付けて http にリクエストを送信する。
using System; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; namespace ClientSample { class Program { static async Task Main(string[] args) { var httpClient = new HttpClient() { BaseAddress = new Uri("http://localhost:5000"), }; httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "Test"); var response = await httpClient.GetAsync("/"); Console.WriteLine(await response.Content.ReadAsStringAsync()); Console.ReadLine(); } } }
実行結果
リダイレクト前にはあった Authorization ヘッダーが、リダイレクト後には含まれていないことを確認できた。
おわりに
IdetityServer4 ホストと、IdetityServer4 が発行するアクセストークンを使って呼び出す Web API を Azure App Service にデプロイしたところ、アクセストークンを付けて Web API を呼び出しているのに 401 が返ってきていた。
IdetityServer4 と Web API 両方ローカルだと上手くいく。IdetityServer4 だけ Azure 上でも上手くいく。両方 Azure 上だとダメ。
検証とはいえアクセストークンの署名に開発用キーを使っているからか?それとも ASP.NET Core の JwtBearer か IdetityServer4 のバグか?と疑ってライブラリのソースコードを調べていたが、原因は Azure 上の Web API を呼び出すときの URL を https ではなく http にしていたからだったとさ。自分のコードが悪かった。
こんな凡ミスに1日半費やしてしまった。自戒を込めてブログに残しておく。