Does asp.net core rest api is thread safe? - asp.net

I use singleton manager in rest api method.
[HttpGet("GetUserData")]
public JsonResult GetUserData()
{
//Singleton class in rest api method
AuthManager manager = AuthManager.GetInstance();
}
Server will publish auth key when session(user) request login.
And Server will save this by Dictionary.
The key is authkey and value is user info which include session id.
And my rest api must be used by logged in and authorized user, so i must check first session's authorized when the session request by rest api.
So all rest api must be access that singleton auth manager class.
But if it is not thread safe, then i must use lock (And it makes me very terrible).
Does asp.net core's controller method (view method or rest api) is thread safe?

Self Answering.
No it's not thread safe to use singleton in mvc controller.
You must lock to synchronize the thread.

Using something like a DI to inject your dependencies at the constructor level would help. netcore has its own built in container or you can use something like AutoFac

Related

Deciding the lifetime of dependencies in .NET Core

I have been looking into the following code(I know it is ADAL and not MSAL, but was interested in the DI).
https://github.com/juunas11/azure-ad-on-behalf-of-sample-aspnetcore/blob/master/ApiOnBehalfSample/Startup.cs
The dependencies are registered as Singleton. Is that right?
Is there an issue in them being registered as Scoped?
What is the correct way of deciding the lifetime of the dependencies?
Update:
In the above code uses ADAL to authorize the user and get the user profile using Graph API.
There are 3 dependencies registered in the Startup.cs class,
services.AddSingleton<IGraphApiService, GraphApiService>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IAuthenticationProvider, OnBehalfOfMsGraphAuthenticationProvider>();
So I understand the httpcontextaccessor should be a singleton.
The IAuthenticationProvider (which is used to create Graph Client), should that be singleton?
Also can the IGraphAPIService which calls the Graph API endpoint and returns user profile info be scoped?
Hey here's a quick overview about Dependency Injection Service Lifetimes on .NET from Microsoft official article. Hope it helps you to decide.
Transient
Transient lifetime services are created each time they're requested from the service container. This lifetime works best for lightweight, stateless services. Register transient services with AddTransient.
In apps that process requests, transient services are disposed at the end of the request.
Scoped
For web applications, a scoped lifetime indicates that services are created once per client request (connection). Register scoped services with AddScoped.
In apps that process requests, scoped services are disposed at the end of the request.
When using Entity Framework Core, the AddDbContext extension method registers DbContext types with a scoped lifetime by default.
Singleton
Singleton lifetime services are created either:
The first time they're requested.
By the developer, when providing an implementation instance directly to the container. This approach is rarely needed.
Every subsequent request of the service implementation from the dependency injection container uses the same instance. If the app requires singleton behavior, allow the service container to manage the service's lifetime. Don't implement the singleton design pattern and provide code to dispose of the singleton. Services should never be disposed by code that resolved the service from the container. If a type or factory is registered as a singleton, the container disposes the singleton automatically.
Register singleton services with AddSingleton. Singleton services must be thread safe and are often used in stateless services.
In apps that process requests, singleton services are disposed when the ServiceProvider is disposed on application shutdown. Because memory is not released until the app is shut down, consider memory use with a singleton service.

Asp.net core authorization redirect to specified path on failure

In "old" ASP.NET I could build a custom authorize attribute and override HandleUnauthorizedRequest. I cannot seem to do this with ASP.NET Core using a custom authorization handler. The latter either "succeed" or "fails" and I would like to redirect to alternative controller actions based on the nature of the failure.
Here's the scenario. Users of my web app have a claim which indicates that they are "active" users, i.e. they have fully registered and we have validated their details etc. New users have been authenticated using the OpenIdConnect middleware but, until we have fully validated and set up their account, do not have the "active" user claim. Thus, both new users and active users have been authenticated. I want to prevent new users accessing most of the application. Every time they try to get to https://app.example.com/dashboard I want to redirect them to a https://app.example.com/newuser page, from which they can go through the set up process.
I can use an authorization policy on my controllers to check for the presence of the "active" user claim and allow access. When a new user doesn't have this claim, and fails the authorization, I want the authorization handler to have some logic which then redirects them to an area of the app which they do have access to. But I cannot see how to do this using the authorization framework in ASPNET core.
There is a somewhat clunky solution which uses the CookieMiddleware and implements a handler for the OnRedirectToAccessDenied event - see https://github.com/aspnet/Mvc/issues/4890. I also thought about implementing an action filter which runs on every request.
Am I just being stupid here? Surely, it makes sense to want to carry out some action on authorization failures which doesn't just send the user off to re-authenticate.
After some digging about and referring to the wonderful book, Pro ASP.NET Core MVC (6th Edition, Adam Freeman), the simple answer to my question is to create an Authorization Filter. This implements IAuthorizationFilter with a single method OnAuthorization(AuthorizationFilterContext context). In this method do whatever you need to do to check the request. If it fails authorization simply set the context.Result property to some IActionResult, in my case RedirectToActionResult. If the request passes authorization do nothing.
You can also use dependency injection in the filter - fantastic.
There is no mention on how to implement or code samples for IAuthorizationFilter on the Microsoft ASP.NET docs site. Thanks are to Adam Freeman.

Securing WCF service in an ASP.net financial application

I have an MVC4 ASP.net financial application with a WCF service. The current scenario isn't secure enough and I need you help with that.
The current scenario:
The user login using a login form, and I send his login details using a JSON object containing the UserID and the Password to the WCF service:
http://example.com:22559/Login
This returns a JSON object with a true or false.
If it's true, I use the ASP function
FormsAuthentication.SetAuthCookie(loginModel.UserID, loginModel.RememberMe);
to set authorization cookies to use it later.
When the user adds a new Transaction I send a JSON object containing the transaction details without the password to:
http://example.com:22559/AddTransaction
I depend here that the MVC controller will not allow the user to access the transaction page if he isn't logged in.
The problem is anyone can now sneak-out and add a transaction without entering the password!, using the URL:
http://example.com:22559/AddTransaction
What I need to do now, is to make the WCF service itself secured, but I don't know how to do that without making the user enter his username and password each time he adds a new transaction!, so, what is the proper way to do that?
Thanks in advance.
MVC 4's controllers typically use MemberShipProvider for authentication and RoleProvider for authorization. So your WCF services may share the providers.
For authentication, you don't need to do anything in WCF codes. For authorization, it is handy to decorate respective operation implementation function (not interface) with PrincipalPermissionAttribute with the Role name defined. The rest will be done in config and by runtime.
For more details, just search "membershipprovider wcf", you will find a lot articles/tutorials in MSDN, CodeProject and StackOverflow.
Please be mindful that in MVC 5 if you will be moving to MVC5, Identity 2.0 is used by default, and MembershipProvider and RoleProvider will not be their by default. Nevertheless, your WCF codes should remain unchanged, and only some elements under ServiceModel will need to adapt the new custom authentication and authorization, and the client codes should remain the same as well, no config change needed.

How does ASP.Net Web API validate OAuth 2.0 token?

I'm creating a test project with our IDP server. We have created a simple Web API sample project which return the claims of the users on its get method. We have also created the token by using OAuth Flow GrantResourceOwnerCredentials or Flow 3 in specs. Few things i didn't quite understand, need some help to get some more understanding :-
How does the Web API knows that token is coming from authorized
client and how does it get validated.
Where in Web Api code, we can override and check the OAuth incoming token and its validation. In production environment, we will have separate HA server for IDP and Web API, so do we need to specify some certificate in web config?
Can we have all the Auth mechanism available to the Web Api? like basic , OAuth etc.
How does the Web API knows that token is coming from authorized client and how does it get validated.
Normally access token is passed through HTTP Headers like Authorization. You can use handlers in web api on specific routes and check this token with your logic
Where in Web Api code, we can override and check the OAuth incoming
token and its validation. In production environment, we will have
separate HA server for IDP and Web API, so do we need to specify some
certificate in web config?
As said above. Best place is handler
public class AuthenticationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
//...
}
}
and don't forget to configure to use your authentication handler for some specific routes
public static void Register(HttpConfiguration config)
{
// ...
config.MessageHandlers.Add(new AuthenticationHandler());
// ...
}
You need certificate only if your logic needs this certificate to validate your token. The best way is to store and read it to/from windows certificate storage and configure in web.config only thumbprint of certificate you need, so no user names, or plain text password in web.config.
Can we have all the Auth mechanism available to the Web Api? like
basic , OAuth etc.
Yes, you can use basic authentcation together with OAuth, just use something to differentiate, like different HTTP Headers suitable for autorization, but it's not clear for me, why you need to support e.g. basic together with oauth, maybe it will have more sense to use only easier one - basic.
Most of information you need is gathered here http://www.asp.net/web-api/overview/security

ASP.NET Login via Custom WCF Rest Call

I'm writing an admin panel in ASP.NET for an existing set of web service calls. My goal is to use some of the existing login stuff (locking out pages if your not logged in) etc but using my login mechanism. This works by hitting an http post request with a username and password, if you're good you get a session id back, if not you get a 401. Here is the WCF for that:
[WebInvoke(UriTemplate = "/Login/", Method = "POST")]
public String Login(User user)
{
// If we are good return sessiond id
// Otherwise throw 401 etc
So to get this working in ASP.Net what is needed?
I think this:
Implement a user that overrides MembershipUser and has a session id in it.
Implement a membership provider that overrides MembershipProvider and does all the WCF calls etc.
In the Web.Config set up a custom membership provider.
Is this correct or am I missing something major?
Rather than do this yourself, you might want to take a look at the WCF Authentication Services.
Before you go down this route, be aware that the authentication services supports login and logout, but that is about it. The usual Membership methods such as CreateUser aren't available. If you need them, you'll need to create three projects:
A WCF Service Application with a single service called WCFMembershipService that wraps the core Membership Provider requirements, i.e. calling Membership.Provider.Method(). Configure the standard SQLMembershipProvider in the web.config, and
A custom membership provider to be used in the ASP.NET application that calls your WCF service from step 1, and
An ASP.NET Application with the custom membership provider configured
You will find that the Membership and Role providers are extremely easy, but the Profile provider is more challenging, because you cannot serialize the default properties that the provider requires, such as SettingsPropertyValueCollection.
In this case, you would need to convert the SettingsPropertyValueCollection into a serializable type first, and then reconstruct it at the other end. Probably a Dictionary<string, string>() would suffice.

Resources