Rebus Azure Pub Sub pattern - rebus

I'm exploring the Rebus library. I implemented the Pub/Sub successfully in Microsoft.NET.Sdk.Worker project with FileSystem transport. But I'm struggling to make it work with AzureServiceBus. I have below configuration in Program.cs:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) => {
services.AddLogging();
services.AddRebus(
(config, provider) => {
config
.Logging(l => l.Console())
.Routing(r => r.TypeBased().MapAssemblyOf<CreateNewReportMessage>(busConfig.MainQueue))
//.Transport(x => x.UseFileSystem(busConfig.FileSystemTransportBaseDirectory, busConfig.MainQueue))
//.Subscriptions(x => x.UseJsonFile(Path.Combine(busConfig.FileSystemTransportBaseDirectory, "rebus_subscriptions.json")))
.Transport(x => x.UseAzureServiceBus(busConfig.AzureSBConnectionString, busConfig.MainQueue).AutomaticallyRenewPeekLock());
return config;
},
onCreated: async bus => {
await bus.Subscribe<CreateNewReportMessage>();
}
);
services.AutoRegisterHandlersFromAssemblyOf<Program>();
})
.Build();
await host.RunAsync();
I'm getting below 400 Bad request error. The app is published as Azure WebJob.
INFO] [DBG] Rebus.AzureServiceBus.AzureServiceBusTransport (Thread #1): Registering subscription for topic "MyServiceBus/MyServiceBus.Messages.CreateNewReportMessage"
INFO] Successfully created bus instance RebusBus Rebus 1 (isDefaultBus: True)
INFO] Application started. Press Ctrl+C to shut down.
INFO] fail: Microsoft.Extensions.Hosting.Internal.Host[9]
INFO] BackgroundService failed
INFO] ---> Azure.RequestFailedException: The specified HTTP verb (GET) is not valid. To know more visit https://aka.ms/sbResourceMgrExceptions. . TrackingId:1808
INFO] Status: 400 (Bad Request)
INFO] --- End of inner exception stack trace ---
INFO] at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.ThrowIfRequestFailedAsync(Request request, Response response)
INFO] at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.SendHttpRequestAsync(Request request, CancellationToken cancellationToken)
INFO] at Azure.Messaging.ServiceBus.Administration.HttpRequestAndResponse.GetEntityAsync(String entityPath, String query, Boolean enrich, CancellationToken can
INFO] at Azure.Messaging.ServiceBus.Administration.ServiceBusAdministrationClient.TopicExistsAsync(String name, CancellationToken cancellationToken)
INFO] at Rebus.AzureServiceBus.AzureServiceBusTransport.EnsureTopicExists(String normalizedTopic)
INFO] at Rebus.AzureServiceBus.AzureServiceBusTransport.<>c__DisplayClass25_0.<<RegisterSubscriber>b__0>d.MoveNext()
INFO] --- End of stack trace from previous location ---
INFO] at Rebus.Internals.ExceptionIgnorant.Execute(Func`1 function, CancellationToken cancellationToken)
INFO] at Rebus.Internals.ExceptionIgnorant.Execute(Func`1 function, CancellationToken cancellationToken)
INFO] at Rebus.AzureServiceBus.AzureServiceBusTransport.RegisterSubscriber(String topic, String subscriberAddress)
INFO] at Rebus.Bus.RebusBus.InnerSubscribe(String topic)

Related

Receiving a timeout error when trying to use Heroku Data Redis with Stackexchange.Redis

Receiving the following error when trying to retrieve data from Heroku Data Redis on a .Net Core app hosted on Heroku using Docker, the cache works locally but I'm getting this error message when deployed to Heroku:
StackExchange.Redis.RedisTimeoutException: The timeout was reached before the message could be written to the output buffer, and it was not sent, command=HMGET, timeout: 60000, inst: 0, qu: 1, qs: 0, aw: False, bw: CheckingForTimeout, serverEndpoint: [amazon aws host:port], mc: 1/1/0, mgr: 10 of 10 available, clientName: d3d51ae0-3bd0-4434-8767-2028ec9f6c41(SE.Redis-v2.6.66.47313), IOCP: (Busy=0,Free=1000,Min=10,Max=1000), WORKER: (Busy=0,Free=32767,Min=10,Max=32767), POOL: (Threads=5,QueuedItems=0,CompletedItems=986), v: 2.6.66.47313 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
Stack Trace:
2023-01-30T16:49:20.014624+00:00 app[web.1]: Stack Trace:
2023-01-30T16:49:20.014625+00:00 app[web.1]:
2023-01-30T16:49:20.014625+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisExtensions.HashMemberGetAsync(IDatabase cache, String key, String[] members)
2023-01-30T16:49:20.014626+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache.GetAndRefreshAsync(String key, Boolean getData, CancellationToken token)
2023-01-30T16:49:20.014626+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache.GetAsync(String key, CancellationToken token)
2023-01-30T16:49:20.014626+00:00 app[web.1]: at SudokuCollective.Cache.CacheService.GetByUserNameWithCacheAsync(IUsersRepository`1 repo, IDistributedCache cache, String cacheKey, DateTime expiration, ICacheKeys keys, String username, String license, IResult result) in /src/SudokuCollective.Api/SudokuCollective.Cache/CacheService.cs:line 1029
2023-01-30T16:49:20.014627+00:00 app[web.1]: at SudokuCollective.Data.Services.AuthenticateService.AuthenticateAsync(ILoginRequest request) in /src/SudokuCollective.Api/SudokuCollective.Data/Services/AuthenticateService.cs:line 89
2023-01-30T16:49:20.014627+00:00 app[web.1]: at SudokuCollective.Api.Controllers.V1.LoginController.PostAsync(LoginRequest request) in /src/SudokuCollective.Api/SudokuCollective.Api/Controllers/V1/LoginController.cs:line 80, License: , AppId: 0, RequestorId: 0
2023-01-30T16:49:20.014638+00:00 app[web.1]: StackExchange.Redis.RedisTimeoutException: The timeout was reached before the message could be written to the output buffer, and it was not sent, command=HMGET, timeout: 60000, inst: 0, qu: 0, qs: 0, aw: False, bw: CheckingForTimeout, serverEndpoint: ec2-3-221-27-134.compute-1.amazonaws.com:19570, mc: 1/1/0, mgr: 10 of 10 available, clientName: d3d51ae0-3bd0-4434-8767-2028ec9f6c41(SE.Redis-v2.6.66.47313), IOCP: (Busy=0,Free=1000,Min=10,Max=1000), WORKER: (Busy=1,Free=32766,Min=10,Max=32767), POOL: (Threads=5,QueuedItems=0,CompletedItems=1277), v: 2.6.66.47313 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
2023-01-30T16:49:20.014638+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisExtensions.HashMemberGetAsync(IDatabase cache, String key, String[] members)
2023-01-30T16:49:20.014640+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache.GetAndRefreshAsync(String key, Boolean getData, CancellationToken token)
2023-01-30T16:49:20.014642+00:00 app[web.1]: at Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache.GetAsync(String key, CancellationToken token)
2023-01-30T16:49:20.014643+00:00 app[web.1]: at SudokuCollective.Cache.CacheService.GetByUserNameWithCacheAsync(IUsersRepository`1 repo, IDistributedCache cache, String cacheKey, DateTime expiration, ICacheKeys keys, String username, String license, IResult result) in /src/SudokuCollective.Api/SudokuCollective.Cache/CacheService.cs:line 1029
2023-01-30T16:49:20.014644+00:00 app[web.1]: at SudokuCollective.Data.Services.AuthenticateService.AuthenticateAsync(ILoginRequest request) in /src/SudokuCollective.Api/SudokuCollective.Data/Services/AuthenticateService.cs:line 89
2023-01-30T16:49:20.014655+00:00 app[web.1]: at SudokuCollective.Api.Controllers.V1.LoginController.PostAsync(LoginRequest request) in /src/SudokuCollective.Api/SudokuCollective.Api/Controllers/V1/LoginController.cs:line 80
The cache is configured as follows in the Startup.cs file:
string cacheConnectionString = "";
ConfigurationOptions options;
if (!_environment.IsStaging())
{
cacheConnectionString = Configuration.GetConnectionString("CacheConnection");
options = ConfigurationOptions.Parse(Configuration.GetConnectionString("CacheConnection"));
}
else
{
options = GetHerokuRedisConfigurationOptions();
cacheConnectionString = options.ToString();
}
services.AddStackExchangeRedisCache(redisOptions => {
redisOptions.Configuration = cacheConnectionString;
redisOptions.ConfigurationOptions = options;
});
The GetHerokuRedisConfigurationOptions method configures the options as follows:
private static ConfigurationOptions GetHerokuRedisConfigurationOptions()
{
// Get the connection string from the ENV variables
var redisUrlString = Environment.GetEnvironmentVariable("REDIS_URL");
// parse the connection string
var redisUri = new Uri(redisUrlString);
var userInfo = redisUri.UserInfo.Split(':');
var config = new ConfigurationOptions
{
EndPoints = { { redisUri.Host, redisUri.Port } },
Password = userInfo[1],
AbortOnConnectFail = false,
ConnectRetry = 3,
ConnectTimeout = 60000,
SyncTimeout = 60000,
AsyncTimeout = 60000,
Ssl = true,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12,
};
// Add the tls certificate
config.CertificateSelection += delegate
{
var cert = new X509Certificate2("[path to pfx file]");
return cert;
};
return config;
}
I suspected this could be a timeout issue so in the GetHerokuRedisConfigurationOptions method I set the timeouts to 60000 milliseconds but the issue persists. How can I register the IDistributedCache service so it can successfully retrieve data without the above timeout?
I was able to solve the issue. I believe docker wasn't saving the pfx certificate because I was getting authorization errors connecting to the ssl connection for Heroku Data Redis. I wasn't able to review the file system that Docker produced on Heroku but I logged information confirming the pfx file wasn't found. I think this is a security feature in Docker as you would want to limit dissemination of such files.
In either case, since it is a self signed certificate you just need to disable peer verification. You can review the Heroku documentation as to how you do this for supported languages, in this case since we're running .Net Core through docker this is how I configured it:
In Startup.cs:
ConfigurationOptions options;
string cacheConnectionString = "";
if (!_environment.IsStaging())
{
options = ConfigurationOptions.Parse(Configuration.GetConnectionString("CacheConnection"));
cacheConnectionString = Configuration.GetConnectionString("CacheConnection");
}
else
{
options = GetHerokuRedisConfigurationOptions();
cacheConnectionString = options.ToString();
}
services.AddSingleton<Lazy<IConnectionMultiplexer>>(sp =>
new Lazy<IConnectionMultiplexer>(() =>
{
return ConnectionMultiplexer.Connect(options);
}));
services.AddStackExchangeRedisCache(redisOptions => {
redisOptions.InstanceName = "SudokuCollective";
redisOptions.Configuration = cacheConnectionString;
redisOptions.ConfigurationOptions = options;
redisOptions.ConnectionMultiplexerFactory = () =>
{
var serviceProvider = services.BuildServiceProvider();
Lazy<IConnectionMultiplexer> connection = serviceProvider.GetService<Lazy<IConnectionMultiplexer>>();
return Task.FromResult(connection.Value);
};
});
Then within Startup.cs I define a static method to initialize Heroku Redis configuration options:
private static ConfigurationOptions GetHerokuRedisConfigurationOptions()
{
// Get the connection string from the ENV variables
var redisUrlString = Environment.GetEnvironmentVariable("REDIS_URL");
// parse the connection string
var redisUri = new Uri(redisUrlString);
var userInfo = redisUri.UserInfo.Split(':');
var config = new ConfigurationOptions
{
EndPoints = { { redisUri.Host, redisUri.Port } },
Password = userInfo[1],
AbortOnConnectFail = true,
ConnectRetry = 3,
Ssl = true,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12,
};
// Disable peer certificate verification
config.CertificateValidation += delegate { return true; };
return config;
}
I believe that this line:
config.CertificateValidation += delegate { return true; };
Is the equivalent of the following Java documentation provided by Heroku:
#Configuration
class AppConfig {
#Bean
public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer() {
return clientConfigurationBuilder -> {
if (clientConfigurationBuilder.build().isUseSsl()) {
clientConfigurationBuilder.useSsl().disablePeerVerification();
}
};
}
}
It basically disables certification verification. It now runs as expected.

Prisma on production - User 'xxx' has exceeded the 'max_user_connections' resource

I'm having an issue when I upload my Next.js app in production (in Vercel). When I run the app in development, it works fine. Only 1 connection is created. But when I use the app in production, instantly reaches the max users connections (5).
I don't know what to share exactly, but this is my client.js:
import { PrismaClient } from "./generators/app";
export const prisma =
global.prisma ||
new PrismaClient();
if (process.env.NODE_ENV !== 'production') global.prisma = prisma;
And this is how I import it from api files:
import { prisma } from "../../../prisma/client";
I've tried both guides:
https://www.prisma.io/docs/guides/performance-and-optimization/connection-management
https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices
This is the error:
2022-10-27T20:58:32.492Z 07594f4a-727a-4e98-a4aa-264d060dc08b ERROR PrismaClientInitializationError:
Invalid `prisma.user.findUnique()` invocation:
Error querying the database: Server error: `ERROR 42000 (1226): User 'xxx' has exceeded the 'max_user_connections' resource (current value: 5)'
at RequestHandler.handleRequestError (/var/task/.next/server/chunks/7738.js:31215:19)
at RequestHandler.request (/var/task/.next/server/chunks/7738.js:31188:18)
at async PrismaClient._request (/var/task/.next/server/chunks/7738.js:32176:24)
at async havePermission (/var/task/.next/server/chunks/3433.js:49:40)
at async getServerData (/var/task/.next/server/pages/api/app/user/get/[column].js:181:34)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:366:9)
at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:469:9)
at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:719:37)
at async Router.execute (/var/task/node_modules/next/dist/server/router.js:247:36)
at async NextNodeServer.run (/var/task/node_modules/next/dist/server/base-server.js:346:29) {
clientVersion: '4.3.1',
errorCode: undefined
}
2022-10-27T20:58:32.501Z 07594f4a-727a-4e98-a4aa-260d060dc08b ERROR PrismaClientInitializationError:
Invalid `prisma.user.findUnique()` invocation:
Error querying the database: Server error: `ERROR 42000 (1226): User 'xxx' has exceeded the 'max_user_connections' resource (current value: 5)'
at RequestHandler.handleRequestError (/var/task/.next/server/chunks/7738.js:31215:19)
at RequestHandler.request (/var/task/.next/server/chunks/7738.js:31188:18)
at async PrismaClient._request (/var/task/.next/server/chunks/7738.js:32176:24)
at async havePermission (/var/task/.next/server/chunks/3433.js:49:40)
at async getServerData (/var/task/.next/server/pages/api/app/user/get/[column].js:181:34)
at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:366:9)
at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:469:9)
at async Object.fn (/var/task/node_modules/next/dist/server/next-server.js:719:37)
at async Router.execute (/var/task/node_modules/next/dist/server/router.js:247:36)
at async NextNodeServer.run (/var/task/node_modules/next/dist/server/base-server.js:346:29) {
clientVersion: '4.3.1',
errorCode: undefined
}
RequestId: 07594f4a-727a-4e98-a4aa-264d060dc08b Error: Runtime exited with error: exit status 1
Runtime.ExitError
After that it tries every second to make a GET request to the api with 500 response.
Vercel by default creates like 5 new connections to the database (maybe for the CDNs or something like that) and you need a larger connection limit.

Can't connect RabbitMQ to my app from docker [duplicate]

This question already has an answer here:
Connecting to rabbitmq docker container from service in another container
(1 answer)
Closed last year.
I am currently stuck with this problem for about a week and really can't find an appropriate solution. The problem is that when I try to connect to dockerized RabbitMQ it gives me the same error every time:
wordofthedayapp-wordofthedayapp-1 | [40m[1m[33mwarn[39m[22m[49m: MassTransit[0]
wordofthedayapp-wordofthedayapp-1 | Connection Failed: rabbitmq://localhost/
wordofthedayapp-wordofthedayapp-1 | RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were
reachable
wordofthedayapp-wordofthedayapp-1 | ---> System.AggregateException: One or more errors occurred. (Connection failed)
wordofthedayapp-wordofthedayapp-1 | ---> RabbitMQ.Client.Exceptions.ConnectFailureException: Connection failed
wordofthedayapp-wordofthedayapp-1 | ---> System.TimeoutException: The operation has timed out.
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.TaskExtensions.TimeoutAfter(Task task, TimeSpan timeout)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail(ITcpClient socket, AmqpTcpEndpo
int endpoint, TimeSpan timeout)
wordofthedayapp-wordofthedayapp-1 | --- End of inner exception stack trace ---
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail(ITcpClient socket, AmqpTcpEndpo
int endpoint, TimeSpan timeout)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingAddressFamily(AmqpTcpEndpoint end
point, Func`2 socketFactory, TimeSpan timeout, AddressFamily family)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingIPv4(AmqpTcpEndpoint endpoint, Fu
nc`2 socketFactory, TimeSpan timeout)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Impl.SocketFrameHandler..ctor(AmqpTcpEndpoint endpoint, Func`2 socket
Factory, TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.Framing.Impl.IProtocolExtensions.CreateFrameHandler(IProtocol protoco
l, AmqpTcpEndpoint endpoint, Func`2 socketFactory, TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.ConnectionFactory.CreateFrameHandler(AmqpTcpEndpoint endpoint)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.EndpointResolverExtensions.SelectOne[T](IEndpointResolver resolver, F
unc`2 selector)
wordofthedayapp-wordofthedayapp-1 | --- End of inner exception stack trace ---
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.EndpointResolverExtensions.SelectOne[T](IEndpointResolver resolver, F
unc`2 selector)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver
, String clientProvidedName)
wordofthedayapp-wordofthedayapp-1 | --- End of inner exception stack trace ---
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver
, String clientProvidedName)
wordofthedayapp-wordofthedayapp-1 | at RabbitMQ.Client.ConnectionFactory.CreateConnection(IList`1 hostnames, String clientPr
ovidedName)
wordofthedayapp-wordofthedayapp-1 | at MassTransit.RabbitMqTransport.Integration.ConnectionContextFactory.CreateConnection(I
Supervisor supervisor)
Here you can find my docker-compose.yml:
version: '3.9'
services:
rabbitmq:
image: rabbitmq:3.9-management
hostname: rabbitmq
volumes:
- "~/.docker-conf/rabbitmq/data/:/var/lib/rabbitmq/"
- "~/.docker-conf/rabbitmq/log/:/var/log/rabbitmq"
ports:
- 5672:5672
- 15672:15672
expose:
- 5672
- 15672
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
healthcheck:
test: [ "CMD", "rabbitmqctl", "status", "-f", "http://localhost:15672"]
interval: 5s
timeout: 20s
retries: 5
networks:
- app
ms-sql-server:
container_name: ms-sql-server
image: mcr.microsoft.com/mssql/server:2019-latest
user: root
volumes:
- "appdb:/var/opt/mssql/data"
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "Password123!"
MSSQL_PID: Express
ports:
- 1433:1433
healthcheck:
test: ["CMD" ,"ping", "-h", "localhost"]
timeout: 20s
retries: 10
networks:
- app
wordofthedayapp:
build:
dockerfile: WordOfTheDay.Api/Dockerfile
image: wordofthedayapp
environment:
DbServer: "ms-sql-server"
DbPort: "1433"
DbUser: "sa"
Password: "Password123!"
Database: "appdb"
ports:
- 5001:80
restart: on-failure
depends_on:
- rabbitmq
networks:
- app
volumes:
appdb:
networks:
app:
My appsettings string:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"WordContext": "Server=ms-sql-server;Database=master;User=sa;Password=Password123!;MultipleActiveResultSets=true;Integrated Security=false;TrustServerCertificate=true",
"RabbitMQHost": "amqp://elias:123456#localhost:5672"
}
}
This is how it works in the app using MassTransit:
public static void AddConfiguredMassTransit(this IServiceCollection services, string host)
{
services.AddMassTransit(Configuration =>
{
Configuration.UsingRabbitMq((context, config) =>
{
config.Host(host);
});
});
services.AddMassTransitHostedService();
}
services.AddConfiguredMassTransit(Configuration.GetConnectionString("RabbitMQHost"));
I hope at least anyone knows what is wrong with this code because I really tired trying to fix it and browsing internet for solution. Thank you in advance!
P.S. Important information! Everything works perfect when I test it locally without a docker, but when I try to dockerize the app this happens.
If you are testing locally, the host is likely localhost since Docker is exposing the port to the local machine. When running in a container, however, the virtual network should have a hostname of rabbitmq, which would need to be used instead of localhost when running inside a container on the same network.
Since the log shows:
Connection Failed: rabbitmq://localhost/
I'm guessing you aren't updating the host name when running inside a container.
You can determine if your application is running in a container easily:
bool IsRunningInContainer => bool.TryParse(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER"), out var inDocker) && inDocker;
Then, in your configuration:
var host = IsRunningInContainer ? "rabbitmq" : "localhost";

AWS Cognito .NET Core 3.1 integration

I'm rather new to .NET in general and I'm trying to create a simple authentication for my API using AWS Cognito. I've followed guides online but none seem to work for me. This is how I've configured my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
services.AddControllersWithViews();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.ResponseType = Configuration["Authentication:Cognito:ResponseType"];
options.MetadataAddress = Configuration["Authentication:Cognito:MetadataAddress"];
options.ClientId = Configuration["Authentication:Cognito:ClientId"];
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
I have properly filled out my configuration. When I protect a page through [Authorize] I get redirected to AWS Cognito to login and then I'm redirected to https://localhost:5001/signin-oidc?code=... where I get a blank page and an error in the console stating:
fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[52]
Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null', status code '400'.
fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[17]
Exception occurred while processing message.
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'.
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HLTB2GSVEPB1", Request id "0HLTB2GSVEPB1:00000013": An unhandled exception was thrown by the application.
System.Exception: An error was encountered while handling the remote login.
---> Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectProtocolException: Message contains error: 'invalid_client', error_description: 'error_description is null', error_uri: 'error_uri is null'.
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RedeemAuthorizationCodeAsync(OpenIdConnectMessage tokenEndpointRequest)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
I've tried to make sure that it's not wrong on the AWS side, and I've been able to see that a code and state is sent back to the application.

Enable CORS in ASP .NET Core 2.1 Web Api

I'm writting application in ASP .NET Core 2.1 Web API and React. I have my server on localhost:5000 and my client on localhost:3000. I wanted to send post request with axios but in browser console i see error:
OPTIONS https://localhost:5001/api/auth/login 0 ()
Uncaught (in promise) Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
In my Web API I try to add CORS but it doesn't seems to work. I add:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors();
services.AddMvc();
...
}
And:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors(options =>
options
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
...
app.UseMvc();
}
And this is my post request:
const response = await axios({
method: 'post',
url: 'http://localhost:5000/api/auth/login',
data: {
userName: this.state.controls.login.value,
password: this.state.controls.password.value
}
});
Server console after request:
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 OPTIONS http://localhost:5000/api/auth/login
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
Policy execution successful.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 4.253ms 204
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 POST http://localhost:5000/api/auth/login application/json;charset=UTF-8 52
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
Policy execution successful.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2.1805ms 307
info: Microsoft.AspNetCore.Server.Kestrel[32]
Connection id "0HLG4CH3JIV16", Request id "0HLG4CH3JIV16:00000002": the application completed without reading the entire request body.
When I use Postman everything is fine. I receive json with token from server.
Ok, I resolve my problem. I just didn't know that I should remove "app.UseHttpsRedirection();".

Resources