Technology Goal:
- Client-Side: Blazor WebAssembly
- Backend: .NET Core 3.1 WebApi on Lambda (AWS) via ApiGateway (/{proxy+})
- Authentication: AWS Cognito
Backend:
- I have a .NET Core Lambda function that is accessed via AWS ApiGateway (RestApi) by having the ApiGateway /{proxy+} => Lambda. This deploys and works fine. I have configured the WebApi to use AWS Cognito as it's authentication method (code from Startup..cs:ConfigureServices below).
- I can successfully use the [Authorize] attribute on my routes and when I access an route with [Authorize] in my browser directly, I get sent to the Cognito signing page, I can login and I'm sent back to my Api and the call executes. Works great.
Startup.cs:ConfigureServices
RegionEndpoint region = Configuration.GetAWSOptions().Region;
string CognitoMetadataAddress = $"https://cognito-idp.{region.SystemName}.amazonaws.com/{AppConfig.CognitoPoolId}/.well-known/openid-configuration";
//
// Ref: https://criticalhittech.com/2019/02/19/asp-net-core-with-aws-lambda-and-cognito/
//
services.Configure<OpenIdConnectOptions>(options =>
{
options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;
options.ClientId = AppConfig.CognitoClientId;
options.MetadataAddress = CognitoMetadataAddress;
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true
};
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.ClientId = AppConfig.CognitoClientId;
options.MetadataAddress = CognitoMetadataAddress;
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true
};
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut,
OnAuthenticationFailed = OnAuthenticationFailed,
OnUserInformationReceived = OnUserInformationReceived
};
});
Client-Side:
- I have a basic Blazor project going using WebAssembly (so I can eventually just throw the compiled static output up on AWS S3 and have it hosted there).
- I have configured the project to use Cognito as it's authentication source (see Program.cs:Main code below) and it works "ok" (it has the dumb Cognito X-Frame-Options issue of course, but it works).
Program.cs:Main
string CognitoPoolId = "ca-central-1_<REMOVED>";
string region = CognitoPoolId.Substring(0, CognitoPoolId.IndexOf('_', StringComparison.InvariantCultureIgnoreCase));
string CognitoAuthority = $"https://cognito-idp.{region}.amazonaws.com/{CognitoPoolId}";
string CognitoMetadataAddress = $"https://cognito-idp.{region}.amazonaws.com/{CognitoPoolId}/.well-known/openid-configuration";
builder.Services.AddOidcAuthentication(options =>
{
options.ProviderOptions.Authority = CognitoAuthority;
options.ProviderOptions.MetadataUrl = CognitoMetadataAddress;
options.ProviderOptions.ClientId = "<REMOVED>";
options.ProviderOptions.RedirectUri = $"{builder.HostEnvironment.BaseAddress.TrimEnd('/')}/authentication/login-callback";
options.ProviderOptions.ResponseType = "code";
});
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
Problem In my Blazor app, I want to call my back-end API (which requires Authentication) and use the authorization that the Blazor app already has since both the client and backend are using the same Cognito user pool. i.e.
- Load up Blazor app
- Complete Login
- Make Http call to my Backend <-- use the login session from #2
HttpResponseMessage response = await Http.SendAsync(requestMessage);
How do I configure the HttpClient instance to send along the authorization the Blazor app has via authenticating with Cognito so that it can call the protected Apis?