Angular 6 Signalr with MVC 5 - asp.net-mvc-5

I am using angular 6 with my current project which is in mvc 5 , all other things are working perfect, the only problem i am facing in implementing SignalR, this is my signalr.service.ts code:
export class SignalRService {
dataReceived = new EventEmitter<myData>();
connectionEstablished = new EventEmitter<Boolean>();
private connectionIsEstablished = false;
private _hubConnection: HubConnection;
constructor() {
this.createConnection();
this.registerOnServerEvents();
this.startConnection();
}
private createConnection() {
this._hubConnection = new HubConnectionBuilder()
.withUrl(window.location.href+'testHub')
.build();
}
private startConnection(): void {
this._hubConnection
.start()
.then(() => {
this.connectionIsEstablished = true;
console.log('Hub connection started');
this.connectionEstablished.emit(true);
})
.catch(err => {
console.log('Error while establishing connection, retrying...');
//setTimeout(this.startConnection(), 5000);
});
}
private registerOnServerEvents(): void {
this._hubConnection.on('sendProgressTrackerAlert', (data: any) => {
this.dataReceived.emit(data);
});
}
}
But it is giving me this error:
Utils.js:148 Error: Failed to complete negotiation with the server: Error: Not Found
push../node_modules/#aspnet/signalr/dist/esm/Utils.js.ConsoleLogger.log
# Utils.js:148 14:55:10.842 Utils.js:148 Error: Failed to start the
connection: Error: Not Found
Btw; angular 6 Signalr is possible with MVC5? because as per my knowledge and search i have found that angular 6 signalr can be used only with Core?

if you looking to user signalR with a MVc5 solution, then you'll need to use the jQuery.signalR module with your angular client instead of the #aspnet.SignalR.

Related

Stripe Node SDK does not send requests from Client-Side

dI am currently trying to implement a stripe integration for our client-side to start checkout processes, manage subscriptions, etc... Altough the documentation seems pretty straight forward i have followed the steps for implementing the node SDK, but it does not work for whatever reason.
After calling a method (e.g list all customers) i dont see any request going out in the network tab, there is also no error it just seems that it does nothing at all. I have already tried using a different apiVersion, nothing changed.
This is what the shell class looks like:
import { StripeConfig } from 'shared/src/sharedConfigs/configs/stripeConfig';
import Stripe from 'stripe';
export class StripeShell {
private readonly publishableKey: string;
private readonly secretKey: string;
private readonly apiVersion: string;
private stripeApi: Stripe;
public constructor(config: StripeConfig) {
this.publishableKey = config.publishableKey;
this.secretKey = config.secretKey;
this.apiVersion = config.apiVersion;
this.stripeApi = new Stripe(this.secretKey, {
// #ts-ignore
apiVersion: '2020-08-01',
});
}
public getCustomer(customerId: string): Promise<Stripe.Customer | Stripe.DeletedCustomer> {
return this.stripeApi.customers.retrieve(customerId);
}
public listCustomers(): Promise<Stripe.ApiList<Stripe.Customer>> {
return this.stripeApi.customers.list();
}
public getSubscription(subscriptionId: string): Promise<Stripe.Subscription> {
return this.stripeApi.subscriptions.retrieve(subscriptionId);
}
public getInvoice(invoiceId: string): Promise<Stripe.Invoice> {
return this.stripeApi.invoices.retrieve(invoiceId);
}
}
And this is how i tried testing it:
const test = () => {
shell.stripe.listCustomers().then((res) => {
console.log(res);
}).catch(err => console.error(err));
};
I am using React as frontend Framework and Typescript.
I already tried requiring stripe instead of importing, also tried different apiVersions, also tried using curl which works fine, double checked the secret/publishable key and tried both.

Get Token request returned http error: 400 and server response

I have a asp.net core 3.1 web api which adds messages to Azure Queue. In this case I am using an account to login into the VS2019 and debug the code in my local development environment. The same account is also added to the access policy for the storage account with the role : Storage Queue Data Contributor
Here I am trying to remove the dependency of using connectionstring and queue name to connect to the Azure Queue service from the asp.net core web api. All works fine in the case where I am providing connectionstring and queue name. But when I am trying to go with the route of Managed Service Identity in context to my local development environment it is throwing error.
Here goes the code for the asp.net core web api:
TestAPIController.cs:
[HttpPost]
public async Task Post([FromBody]WeatherForecast data)
{
var message = JsonSerializer.Serialize(data);
await _queueClient.SendMessageAsync(message, null, TimeSpan.FromSeconds(-1));
}
Startup.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//services.AddHostedService<WeatherDataService>();
services.AddAzureClients(builder =>
{
builder.AddClient<QueueClient, QueueClientOptions>((options, _, _) =>
{
options.MessageEncoding = QueueMessageEncoding.Base64;
var credential = new DefaultAzureCredential();
var queueUri = new Uri("<AzureQueueURL>");
return new QueueClient(queueUri, credential, options);
});
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo{Title = "queue_storage", Version = "v1"});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "queue_storage v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
On executing the above code I found the below error:
Azure.Identity.AuthenticationFailedException: Azure CLI authentication failed due to an unknown error. ERROR: The command failed with an unexpected error. Here is the traceback:
ERROR: Get Token request returned http error: 400 and server response: {"error":"invalid_grant","error_description":"AADSTS700082: The refresh token has expired due to inactivity.áThe token was issued on 2021-04-23T15:29:05.0816332Z and was inactive for 90.00:00:00.\r\nTrace ID: cbd16614-192a-409b-82a8-348597e81900\r\nCorrelation ID: 85b72955-22a3-4b1c-b05c-d7054ce6a6c6\r\nTimestamp: 2022-05-08 11:22:40Z","error_codes":[700082],"timestamp":"2022-05-08 11:22:40Z","trace_id":"cbd16614-192a-409b-82a8-348597e81900","correlation_id":"85b72955-22a3-4b1c-b05c-d7054ce6a6c6","error_uri":"https://login.microsoftonline.com/error?code=700082"}
I referred to the this article :https://www.rahulpnath.com/blog/getting-started-with-azure-queue-storage/ for my POC.
Can anyone provide their guidance to fix this issue

Azure Functions Dependency Tracking for SQL Server and Service Bus Into Application Insights

Previously I have Azure Web App (.net core) and It successfully track the SQL Server and Service Bus dependency into Application Insights. It is not working some how with Azure Functions.
Environment
dotnet 6
dotnet-isolated mode
log level default set to "Information".
Azure Environment using Consumption plan for Azure Functions.
Application Insights key is configured.
I have Azure API management at front and backend is Azure Function and that call SQL Server and Service Bus.
Api Management Service to Azure function dependency successfully resolved but Azure Function to other component is not working.
I know I am posting my own answer. Also there are chance that in future there may be some good solution or it get integrated the way it is in in-process mode.
By then follow steps.
Add Package
Microsoft.ApplicationInsights.WorkerService
In program.cs in configuring host.
services.AddApplicationInsightsTelemetryWorkerService();
More info at
https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service
The only way I've managed to solve this issue so far was by setting up custom Middleware
.ConfigureFunctionsWorkerDefaults(config =>
{
config.UseMiddleware<AiContextMiddleware>();
})
In the IServiceCollection you need to setup simply
.AddApplicationInsightsTelemetryWorkerService()
public class AiContextMiddleware : IFunctionsWorkerMiddleware
{
private readonly TelemetryClient _client;
private readonly string _hostname;
public AiContextMiddleware(TelemetryClient client)
{
_client = client;
_hostname = Environment.GetEnvironmentVariable("AI_CLOUD_ROLE_NAME");
}
public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
{
var operationId = ExtractOperationId(context.TraceContext.TraceParent);
// Let's create and start RequestTelemetry.
var requestTelemetry = new RequestTelemetry
{
Name = context.FunctionDefinition.Name,
Id = context.InvocationId,
Properties =
{
{ "ai.cloud.role", _hostname},
{ "AzureFunctions_FunctionName", context.FunctionDefinition.Name },
{ "AzureFunctions_InvocationId", context.InvocationId },
{ "AzureFunctions_OperationId", operationId }
},
Context =
{
Operation =
{
Id = operationId,
ParentId = context.InvocationId,
Name = context.FunctionDefinition.Name
},
GlobalProperties =
{
{ "ai.cloud.role", _hostname},
{ "AzureFunctions_FunctionName", context.FunctionDefinition.Name },
{ "AzureFunctions_InvocationId", context.InvocationId },
{ "AzureFunctions_OperationId", operationId }
}
}
};
var operation = _client.StartOperation(requestTelemetry);
try
{
await next(context);
}
catch (Exception e)
{
requestTelemetry.Success = false;
_client.TrackException(e);
throw;
}
finally
{
_client.StopOperation(operation);
}
}
private static string ExtractOperationId(string traceParent)
=> string.IsNullOrEmpty(traceParent) ? string.Empty : traceParent.Split("-")[1];
}
It's definitely not a perfect solution as you then get two starting logs, but as end result, you get all logs traces + dependencies correlated to an operation.
I've solved this issue in the first place like that, now I'm revisiting whether there are any better ways to solve this.
Let me know too whether you managed to solve this issue on your side.

Loopback 4 authentication metadata options undefined

I have created a simple jwt auth application the same way its displayed here: https://github.com/raymondfeng/loopback4-example-auth0
The authentication part is working properly but the authorization does not work as expected.
I decorated my controller with following function and added a scope.
#authenticate({strategy: 'auth0-jwt', options: {scopes: ['greet']}})
In my authentication strategy I´m checking the scope via the AuthenticationMetadata class.
import {AuthenticationBindings, AuthenticationMetadata, AuthenticationStrategy} from '#loopback/authentication';
import {inject} from '#loopback/core';
import {ExpressRequestHandler, Request, Response, RestBindings} from '#loopback/rest';
import {UserProfile} from '#loopback/security';
import {JWT_SERVICE} from './types';
const jwtAuthz = require('express-jwt-authz');
export class JWTAuthenticationStrategy implements AuthenticationStrategy {
name = 'auth0-jwt';
constructor(
#inject(RestBindings.Http.RESPONSE)
private response: Response,
#inject(AuthenticationBindings.METADATA)
private metadata: AuthenticationMetadata,
#inject(JWT_SERVICE)
private jwtCheck: ExpressRequestHandler,
) {}
async authenticate(request: Request): Promise<UserProfile | undefined> {
return new Promise<UserProfile | undefined>((resolve, reject) => {
this.jwtCheck(request, this.response, (err: unknown) => {
if (err) {
console.error(err);
reject(err);
return;
}
console.log(this.metadata.options);
// If the `#authenticate` requires `scopes` check
if (this.metadata.options?.scopes) {
jwtAuthz(this.metadata.options!.scopes, {failWithError: true})(request, this.response, (err2?: Error) => {
if (err2) {
console.error(err2);
reject(err2);
return;
}
// eslint-disable-next-line #typescript-eslint/no-explicit-any
resolve((request as any).user);
});
} else {
// eslint-disable-next-line #typescript-eslint/no-explicit-any
resolve((request as any).user);
}
});
});
}
}
When trying to access
this.metadata.options
I´m always getting an undefined back.
How can I achieve to get the options and the scope out of metadata?
Thanks
For Loopback Authorization your class needs to implement the Provider<Authorizer> interface. In that interface it defines the 2 functions you need to implement
#injectable({scope: BindingScope.TRANSIENT})
class AuthorizationService implements Provider<Authorizer>{
value (): Authorizer {
return this.authorize.bind(this);
}
async authorize (
context: AuthorizationContext,
metadata: AuthorizationMetadata,
) {
// TODO implement authorization
}
}
The authorization metadata will be injected by loopback into that function automatically after you bind it with an AuthorizationTags.Authorizer
If you are having problems implementing Authentication then read my step by step guide on how we implemented Loopback Authentication using Firebase. That should be able to help you with the core ideas to get Authentication running.

No sign-out authentication handler is registered for the scheme 'Identity.TwoFactorUserId'

ASP.NET Core 2.2 web app using code migrated from full fat MVC app.
My AccountController contains this simple code for its Logout route.
await this.SignInManager.SignOutAsync();
return this.RedirectToAction(nameof(Landing.HomeController.Index), "Home");
But this gives.
No sign-out authentication handler is registered for the scheme 'Identity.TwoFactorUserId'.
Pretty confusing given that I've never mentioned 2FA in my code, and Google login is working.
serviceCollection
.AddIdentityCore<MyUser>(identityOptions =>
{
identityOptions.SignIn.RequireConfirmedEmail = false;
})
.AddUserStore<MyUserStore>()
.AddSignInManager<SignInManager<MyUser>>();
serviceCollection.AddAuthentication(IdentityConstants.ApplicationScheme)
.AddCookie(IdentityConstants.ApplicationScheme, options =>
{
options.SlidingExpiration = true;
})
.AddGoogle(googleOptions =>
{
this.Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
As a complement to #Luke's answer:
The reason why SignInManager::SignOutAsync() throws is this method will also sign out the TwoFactorUserIdScheme behind the scenes:
public virtual async Task SignOutAsync()
{
await Context.SignOutAsync(IdentityConstants.ApplicationScheme);
await Context.SignOutAsync(IdentityConstants.ExternalScheme);
await Context.SignOutAsync(IdentityConstants.TwoFactorUserIdScheme);
}
(See source code)
Typically, these tree authentication schemes are registered automatically by AddIdentity<TUser, TRole>():
public static IdentityBuilder AddIdentity<TUser, TRole>(
this IServiceCollection services,
Action<IdentityOptions> setupAction)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
...
.AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
{
o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
});
... // other services
}
(See source code )
However, you added the Identity services by AddIdentityCore<>() instead of the AddIdentity<>().
Because the AddIdentityCore<>() doesn't register a TwoFactorUserIdScheme scheme (see source code) automatically, there's no associated CookieAuthenticationHandler for TwoFactorUserIdScheme. As a result, it throws.
How to solve
In order to work with SignInManager.SignOutAsync(), according to above description, we need ensure a <scheme>-<handler> map has been registed for TwoFactorUserIdScheme .
So I change your code as below, now it works fine for me:
serviceCollection.AddAuthentication(IdentityConstants.ApplicationScheme)
.AddCookie(IdentityConstants.ApplicationScheme, options =>
{
options.SlidingExpiration = true;
})
.AddCookie(IdentityConstants.TwoFactorUserIdScheme, o =>
{
o.Cookie.Name = IdentityConstants.TwoFactorUserIdScheme;
o.ExpireTimeSpan = TimeSpan.FromMinutes(5);
})
.AddGoogle(googleOptions =>
{
this.Configuration.Bind("OAuth2:Providers:Google", googleOptions);
googleOptions.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub", "string");
})
.AddExternalCookie();
Also you can create your own SignInManager<MyUser> and override sign out as you need
public class CustomSignInManager : SignInManager<MyUser>
{
public override async Task SignOutAsync()
{
await Context.SignOutAsync(IdentityConstants.ApplicationScheme);
await Context.SignOutAsync(GoogleDefaults.AuthenticationScheme);
}
}
Then change AddSignInManager<SignInManager<MyUser>>() to AddSignInManager<CustomSignInManager>() in your Startup class
serviceCollection
.AddIdentityCore<MyUser>(identityOptions =>
{
identityOptions.SignIn.RequireConfirmedEmail = false;
})
.AddUserStore<MyUserStore>()
.AddSignInManager<CustomSignInManager>();
Do not use the SignOutAsync method on a SignInManager<T> you've injected into the controller. Instead, use the method on the HttpContext which takes a scheme argument. I don't know why.
Below code works for me , use the same AuthenticationScheme that you use while "AddAuthentication" in startup.cs
[HttpGet("signout")]
[AllowAnonymous]
public async Task signout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var prop = new AuthenticationProperties
{
RedirectUri = "/logout-complete"
};
// after signout this will redirect to your provided target
await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme, prop);
}
[HttpGet("logout-complete")]
[AllowAnonymous]
public string logoutComplete()
{
return "logout-complete";
}
I agree with itminus reply, We would get an error because in .net core 3.0 if we use AddIdentityCore<>() instead of AddIdentity<>() we would get an error. But when upgrading to .net 7.0 if we again use AddIdentityCore<>() instead of AddIdentity<>() we would get the same error for Identity.TwoFactorRememberMeScheme as well that I am faced with after upgrading. For SignInManager we require Identity.TwoFactorRememberMeScheme as well otherwise we get an error.
The solution which I applied in mine .net 7.0 project is:
Instead of adding every scheme and handler by yourself, we can just use
services.AddAuthentication().AddIdentityCookies();
This will add all the schemes handlers for you and at the time of signout we need to should use below:
await HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme);
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
await HttpContext.SignOutAsync(IdentityConstants.TwoFactorUserIdScheme);

Resources