【C#】.Net CoreでAWS Beanstalk/App RunnerにてCognito認証を使う

Sponsored Links
Sponsored Links

Beanstalk / App Runnerとは

.Net CoreのウェブアプリケーションをAWSにホストするサービスとしてApp Runner / Beanstalkがある。
App Runnerは、Visual StudioからAWS Toolkitでデプロイするだけで、Load Balancerの設定など一通りの設定が自動で完了する。
BeanstalkもAWS Toolkitでデプロイすれば諸々の設定を行ってくれるが、もう少し設定する(できる)ことが増える。
ウェブアプリケーションにアクセスするときに一番最初に気がつく点は、Beanstalkはhttpがデフォルトに対し、App Runnerはhttpsでアクセスを行う。(Cognitoを使用して認証を行うときは、ここは重要。なぜならCognitoは、戻りURLとしてhttpsしか受け付けてくれない。)

Load Balancerから先の事

BeanstalkもApp RunnerもLoad Balancerが最初のアクセスポイントとなり、Load Balancerとウェブサーバ間の処理はhttpで行なわれる。(おそらくこの部分は、変更できないのではないかと思う。)
Beanstalk / App Runnerでホストされている.Net Coreのウェブアプリがホストされているウェブサーバには、httpでアクセスされることとなる。
Load Balancerにhttpでアクセスしても、httpsでアクセスしても、.Net的には、httpでアクセスされていると認識され、httpの処理となる。よって、Cognitoに接続する際に渡されるredirect urlもhttpとなってしまう。
※Visual Studioでローカル環境でデバッグする環境はhttps://localhost:xxxxのようなLoad Balancerが登場しない環境では、ウェブサーバにhttpsでアクセスし、ウェブサーバからCognitoへの接続時にもredirect urlはhttpsとして渡されるため、ローカルではうまくいくが、AWSにデプロイするとうまくいかないことがわかる。
簡単な図を書くとこのような流れとなる。(絵はBeanstalkだがApp Runnerも同様)

Cognitoにhttpsのredirect urlを渡す

Load Balancerから先をhttpsに設定できれば、そのままCognitoにhttpsのredirect urlが渡るが、それができないため、.Netの方で、強制的にredirect urlがhttpであれば、httpsにする設定を行う。
絵の中にはしれっと書いてある Cookieもその設定を行う必要がある。(おそらく認証時に発行されるTokenはCookieの中に保存される)
同じサイト内であっても、httpのページとhttpsのページでは、Cookieを共有することができない。そのため、Cookieを常にhttpsのページとして使用するように設定する。
上記絵の中では、Cookieがhttpsのサイトとして処理され、redirect urlがhttpsと強制的に変更する。

最後に

上記のよう.Net側の変更を行うことでCognitoでの認証が可能となる。App Runnerでホストされている場合は、ここでおしまいだが、Beanstalkでホストされている場合は、Load BalancerのListenerの設定やInbound/Outboundルールの設定が少しだが、必要となる。
以下、設定周りのスクリーンショット。

設定内容

Cognito

Cognitoの設定はこちらを参照できる。.Net CoreのApp Settingsの設定も後半に登場する。

Cognitoにきたら、Manage User Pools > Create user poolをクリックする。
Pool名を入力し、Review defaultsをクリックする。
下の方のApp Clientsをクリックする。
Add an app clientをクリックする。
Generate client secretのチェックを外す(この設定は後から変更できないため、チェックを外すのを忘れると、最初からやり直しになってしまう)
ここの設定は後からでも変更できるが、チェックがついている箇所を合わせる。
Create app clientをクリックし、app clientを作成する。
App client名を入力し、Return to pool detailsをクリックする。
Create poolをクリックし、poolを作成を完了する。
App client settingをクリックする。
Select allをクリックし、Cognito User Poolがチェックされる。
後で、Coolback URLを入力するので戻ってくるが、赤枠のチェックをつけ、Save changesをクリックする。
Domain nameをクリックする。
Cognito用のドメイン名を入力し、Save changesで保存する。

Visual StudioプロジェクトのApp Settingsの設定(上記Cognitoサイトで作成された情報を使用する)

下記AppSettings.jsonの内容となる。これらの<>の中を埋めていく。

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Authentication": {
    "Cognito": {
      "ClientId": "<app client id from AWS Cognito>",
      "IncludeErrorDetails": true,
      "MetadataAddress": "https://cognito-idp.<your region>.amazonaws.com/<your-pool id>/.well-known/openid-configuration",
      "RequireHttpsMetadata": false,
      "ResponseType": "code",
      "SaveToken": true,
      "TokenValidationParameters": {
        "ValidateIssuer": true
      },
      "AppSignOutUrl": "",
      "CognitoDomain": "https://<custom domain name>.auth.us-east-1.amazoncognito.com"
    }
  }
}

AWS Toolkitからデプロイ

App Runnerを使用する際は、こちらをクリックする。(まだPreviewだがデプロイに問題はない)
Beanstalkを使用する際は、こちらをクリックする。
{
  "DetailedErrors": true,
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Authentication": {
    "Cognito": {
      "ClientId": "75gkrda7e6nnn85s99ssdhs5o5",
      "IncludeErrorDetails": true,
      "MetadataAddress": https://cognito-idp.us-east-1.amazonaws.com/us-east-1_PeCdkl5kq/.well-known/openid-configuration,
      "RequireHttpsMetadata": false,
      "ResponseType": "code",
      "SaveToken": true,
      "TokenValidationParameters": {
        "ValidateIssuer": true
      },
      "AppSignOutUrl": "",
      "CognitoDomain": https://test-demo-domain-101.auth.us-east-1.amazoncognito.com
    }
  }
}

Beanstalkへデプロイ

Application名を入力し、使用可能かチェックする。問題なければ、Nextをクリックする。
デフォルトでは、Single instance environmentにチェックが入っているため、チェックを外し、Load Balancer typeがApplicationになっていることを確認する。これら以外の設定は、デフォルトで進む。

Load Balancerの設定

Load BalancerのListenerに443を追加する。
ProtocolでHttpsを選択しport:443を入力する。Forward設定ではhttpで設定されているものを選択する。
事前にCertificateをACM (Amazon Certificate Manager)に設定しておく必要がある。証明書を選択し、保存する。
80番ポートに来たものは、443へredirectする設定と変更する。
もとの設定は削除し、Redirect https:443を追加する。
Inbound Rulesにhttpsを追加する。
Outbound Rulesにhttpsを追加する。

Cognitoの設定(App client settings > Callback URLs)

デプロイが完了するとURLが決まるので、httpのURLをそのまま貼り付けhttpsに変換し、最後に、/signin-oidcをつけて保存する。

Visual Studioプロジェクト Program.csの変更(追加)

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always;
    options.NonceCookie.SecurePolicy = CookieSecurePolicy.Always;
    options.ResponseType = builder.Configuration["Authentication:Cognito:ResponseType"];
    options.MetadataAddress = builder.Configuration["Authentication:Cognito:MetadataAddress"];
    options.ClientId = builder.Configuration["Authentication:Cognito:ClientId"];
    options.Events = new OpenIdConnectEvents()
    {
        //OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut
        OnRedirectToIdentityProvider = (context) =>
        {
            // force https for the redirect url.
            if (context.ProtocolMessage.RedirectUri.StartsWith([http://]http://))
            {
                context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace([http://]http://, [https://]https://);
            }
            return Task.FromResult(0);
        }
    };
});
// Add services to the container.
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
少々見にくいが、追加部分の説明。
最後に認証させたいクラスに[Authorize]属性を追加して、完了。
IT
Sponsored Links
Sponsored Links
Sponsored Links
ようさんチョットでぶ
Copied title and URL
Bitnami