Amazon Cognito User Poolsのアプリ統合で、OpenID ConnectっぽいエンドポイントとログインUIが利用できる。 ASP.NET Core Authentication のOpenID Connectスキームは、ASP.NET Core メタパッケージに含まれているビルトインの機能。 Webサイトでajaxを使ったAPIアクセスではなくでブラウジングコンテキストでUser PoolsのIDにログインする。
services .AddAuthentication(options => { options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.ClientId = "client id"; options.ClientSecret = "client secret"; options.MetadataAddress = "https://cognito-idp.{Region}.amazonaws.com/{Pool ID}/.well-known/openid-configuration"; options.Scope.Clear(); options.Scope.Add("openid"); options.ResponseType = "code"; // Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectPostConfigureOptions options.Backchannel = new HttpClient(options.BackchannelHttpHandler ?? new HttpClientHandler()); options.Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OpenIdConnect handler"); options.Backchannel.Timeout = options.BackchannelTimeout; options.Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB var byteArray = System.Text.Encoding.ASCII.GetBytes(options.ClientId + ":" + options.ClientSecret); options.Backchannel.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); options.ProtocolValidator.RequireNonce = false; options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(options.MetadataAddress, new AmazonUserPools_OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever(options.Backchannel) { RequireHttps = options.RequireHttpsMetadata }); options.Events.OnRedirectToIdentityProviderForSignOut = (context) => { context.ProtocolMessage.SetParameter("logout_uri", context.ProtocolMessage.PostLogoutRedirectUri); context.ProtocolMessage.SetParameter("post_logout_redirect_uri", null); context.ProtocolMessage.SetParameter("client_id", context.Options.ClientId); return Task.CompletedTask; }; });
public sealed class AmazonUserPools_OpenIdConnectConfigurationRetriever : IConfigurationRetriever<OpenIdConnectConfiguration> { Task<OpenIdConnectConfiguration> IConfigurationRetriever<OpenIdConnectConfiguration>.GetConfigurationAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { return GetAsync(address, retriever, cancel); } static async Task<OpenIdConnectConfiguration> GetAsync(string address, IDocumentRetriever retriever, CancellationToken cancel) { var configuration = await OpenIdConnectConfigurationRetriever.GetAsync(address, retriever, cancel); var app_url = "https://<domain_prefix>.auth.<region>.amazoncognito.com"; configuration.TokenEndpoint = app_url = "/oauth2/token"; configuration.AuthorizationEndpoint = app_url + "/login"; configuration.EndSessionEndpoint = app_url + "/logout"; return configuration; } }
OpenID Provider Configuration
.well-known/openid-configuration で得られる情報が足りないので、IConfigurationRetrieverの実装で取得したOpenIdConnectConfigurationに不足するプロパティの値を設定した。
Backchannel HttpClient
エンドポイントへのアクセスはベーシック認証。Authorization ヘッダーでClient Secretを渡す必要がある。OpenIDConnectionOptionsのBackchannelのHttpClientで設定する。Backchannelは既定ではOpenIdConnectPostConfigureOptionsで構築される。既定のHttpClientにヘッダーを追加することはできなかったので、同じように作ってヘッダーを追加したHttpClientのインスタンスをOptionsに設定した。
おまけ
Razor PagesのPageModelではメソッドレベルのAuthorizeAttributeは効かない。