Get session in ASP boilerplate service layer - asp.net

I am currently use AspNetBoilerplate to implement my services in service layer...
So I can access session in MVC controller like:
Token token = HttpContext.Session["Token"] as Token;
After login Token session be initiated....
I can access thta everywhere in MVC controllers but in ApplicationServiceBase it is null like:
public class AuditAppService : ApplicationServiceBase, IAuditAppService
{
public GetUserActions_Box GetUserActions()
{
var token = HttpContext.Current.Session.GetToken();
return GetUserActions_Box.Empty;
}
}
HttpContext.Current.Session is null why?
that app services are implemented in separate library which is added in main web application.
I followed the documentation and crossed This, I think AbpSession is not my solution which mean by it we can access some basics info about session that initiated by AbpBoilerPlate authentication system not ours.

use IAbpSession .
you can use claims to add your custom values to the AbpSession.
previously answered here about how to extend AbpSession
Extend ClaimsAbpSession
read AbpSession https://aspnetboilerplate.com/Pages/Documents/Abp-Session

Related

Get authenticated user from Middleware class in Blazor app

I have a server sided Blazor app. Every user must be authenticated when he wants to visit a page. For this the user is redirected to an "identity server" login page. When the user logs in with the correct credentials, he is then redirected back to the Blazor app.
I have setup my Blazor app with CascadingAuthenticationState, so that I can access the User object and its claims inside my Blazor pages.
This goes something like this inside a component:
[CascadingParameter]
private Task<AuthenticationState> AuthenticationStateTask { get; set; }
...
...
var authState = await AuthenticationStateTask;
var claims = authState.User.Claims; // Works fine.
When I do it like this I have access to the users claims.
So far so good.
But I also have a middleware class where I need to access the user claims.
public async Task InvokeAsync(HttpContext context)
{
if (context?.User?.Claims != null && context.User.Claims.Any())
{
Console.WriteLine("aaa");
}
// Call the next delegate/middleware in the pipeline
await _next(context);
}
But for some reason the User claims are always empty.
Why is the User.Claims object from inside my Blazor component filled with all the claims, but are they empty when I access them through the HttpContext object?
The order of registering Middleware is critical. This is something I've been personally running into a lot lately in my own projects as well - And yet, there are no warnings if you configure them out-of-order.
Quote from Microsoft docs on Middleware order:
The order that middleware components are added in the Startup.Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is critical for security, performance, and functionality.
It seems you are calling your Middleware before the .NET Core authentication middleware, and therefor your User object is null - or lacks claims.
Place your app.UseMiddleware<T> after app.UseAuthentication() and app.UseAuthorization().

ASP.NET Web API get user identity in controller constructor

Is good idea to get user identity in ASP.NET Web API controller constructor, for example:
public PagesController(PageValidator pageValidator, PageMapper pageMapper, PagesManager pagesManager, UsersManager usersManager)
:base(usersManager)
{
_pageValidator = pageValidator;
_pageMapper = pageMapper;
_pagesManager = pagesManager;
if (User.Identity.IsAuthenticated)
_pagesManager.UserId = usersManager.GetByEmail(User.Identity.Name).Id;
}
Is always User.Identity was correct populated before this call raise?
This has bitten me a few times. Depending on where/how you are performing your authentication, you need to be careful where you access your identity, particularly in controller constructors.
For example, whilst the controller action is invoked AFTER an IAuthenticationFilter is instantiated, the controller's constructor is called before AuthenticateAsync; meaning any authentication you do in AuthenticateAsync will not be available in your controller's constructor (like in your example).
I typically don't rely on things being available during controller construction (unless handled by DI). Instead access the identity as you need it in your controller actions.
If you are looking at making identity lookup easier (i.e. pulling in your user object based on the User.Identity.Name property) create a base controller class that has a property or method that does it for you, then have your controllers inherit from that...
public User AuthenticatedUser
{
get
{
if (User.Identity.IsAuthenticated)
{
return usersManager.GetByEmail(User.Identity.Name);
}
return null;
}
}
EDIT
See here for a detailed breakdown of the Web.API lifecycle, showing controller creation occurring prior to authentication.
Yes. You can use this property in Controller in any place. ASP.NET has request pipeline: (http://www.dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle).
As you can see Authorization is early stage step in request pipeline.
Controller creation is the latest stage.

Spring Social Facebook

I am developing with Spring Social and Thymeleaf from the quick start example, but I realised that it only supports one Facebook object per controller. This means the sample can't provide support for multiple users and I am guessing it has to do with the #Scope of the variable. Its runs in a Spring boot container and I wonder how I can configure this so that each session has its own Facebook object.
As you suggested, the Facebook object should be configured with request scope. If you're using the configuration support and/or Spring Boot, then it will be request scoped. Therefore, even though the controller is injected once with a Facebook instance, that instance is really a proxy that will delegate to a real FacebookTemplate instance that is created at request time for the authenticated user.
I can only assume that you're referring to the getting started guide example at http://spring.io/guides/gs/accessing-facebook/. In that case, it's using the most simple Spring Boot autoconfiguration possible for Spring Social, which includes a basic (yet not intended for production) implementation of UserIdSource which always returns "anonymous" as the user ID. Therefore, after you create the first Facebook connection, the second browser tries to find a connection for "anonymous", finds it, and gives you an authorized Facebook object.
This may seem peculiar, but it is an example app intended to get you started...and it does that. All you need to do to get a real UserIdSource is to add Spring Security to the project. That will tell Spring Social autoconfiguration to configure a UserIdSource that fetches the current user ID from the security context. This reflects a more real-world use of Spring Social, albeit obviously more involved and beyond the scope of the getting started guide.
But you can look at https://github.com/spring-projects/spring-social-samples/tree/master/spring-social-showcase-boot for a more complete example of Spring Social within Spring Boot.
Spring Boot autoconfigures a lot of things behind the scenes. It does autoconfigure the Facebook, LinkedIn and Twitter properties and sets up the connection factories for social providers.
However, the implementation of UserIdSource always returns “anonymous” as the user ID. Once the first Facebook connection is established the second browser will try to find a connection for “anonymous” which it finds and gives you an authorised Facebook object.
#Configuration
#EnableSocial
#ConditionalOnWebApplication
#ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
return "anonymous";
}
};
}
}
Solution
The solution is to override the “anonymous” as the UserId for each new user/session. So for each session, we can simply return a SessionID, however, it may not be unique enough to identify users, especially if it’s being cached or stored somewhere in a connection database.
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.currentRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
}
return uuid;
}
The solution for above problem has been talked about in detail over here

Implementing Authorization in a Self Hosted SignalR Server accessed from Web

I'm looking for some guidance on how to implement authorization security for SignalR on a back end service running in a self-hosted (non-IIS) environment, that is called from a Web application. The backend app is basically a monitor that fires SignalR events back to the HTML based client. This all works fine (amazingly well actually).
However, we need to restrict access to the server for authenticated users from the Web site. So basically if a user is authenticated on the Web site, we need to somehow pick up the crendentials (user name is enough) and validation state in the backend app to decide whether to allow the connection as to avoid unauthorized access.
Can anybody point at some strategies or patterns on how to accomplish this sort of auth forwarding?
I am having similar issues here, as in my web app I use a simple cookie authentication system which uses an AoP style approach to check for any controllers with an attribute, then will get the current context (be it from the static HttpContext.Current or from the target invocation object depending on the type of interceptor) and then verify the cookie exists, it contains right data, then finally verify the token with the db or cache etc.
Anyway this approach can also be used for Signalr, although its a bit more long winded and you are using dependency injection. You would basically wrap the hub calls with the desired attribute, then set up your DI/IoC configuration to intercept these calls, then either get the hub instance within your interceptor and get the cookie (or your custom authentication mechanism) from the request, verify it is all valid or not, and if not then throw a new HttpException("403", "Not authenticated"); which should kick the user out and return back before it even hits your hub method, this way you can put the logic in one place (your interceptor, or a class the interceptor consumes) then just wrap any method that needs to use this authentication using your attribute.
I use Ninject and the interception extension, but most major DI frameworks these days have some form of IoC plugin/extensions, such as Autofac, Windsor, Spring etc.
If you were not happy going down the route of introducing DI and/or AOP to your current project, then maybe you could just create a custom hub instance which contains your authentication logic and then just use that in your hubs, so ok you will still be manually calling some authentication logic from within each hub method you want to protect, but its less code, so something like:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
It is not perfect but would work (I think), also I am sure I once read somewhere that Hubs are newly instantiated for each request, and if this is indeed true, you could possibly just put this logic in your constructor if you want to apply the authentication to every action within the hub.
Hope that helps, or gives you ideas... would be interested in knowing how you did solve it in the end.
SignalR does not provide any additional features for authentication. Instead, it is designed to work with the authentication mechanism of your application.
Hubs
You should do authentication as you normally would and then use the Authorize attribute provided by SignalR to enforce the results of the authentication on the Hubs.
The Authorize attribute can be applied to an entire Hub or particular methods in the Hub. Some examples:
[Authorize] – only authenticated users
[Authorize(Roles = "Admin,Manager")] – only authenticated users in the specified .NET roles
[Authorize(Users = "user1,user2")] – only authenticated users with the specified user names
You can also require all Hubs to require authentication by adding the following method in the Application_Start method:
GlobalHost.HubPipeline.RequireAuthentication();
Persistent Connections
You can use the user object in the request to see if the user is authenticated:
request.User.IsAuthenticated

Loading the initial state on a silverlight application based on asp.net session

I'm writing a silverlight application that resembles a shopping cart system.
This app can only be launched from the asp.net website after the user is logged in to the site.
Upon first load, the app will send a request to the backend through WCF service to retreive all the existing items in the shopping cart.
Therefore the silverlight app needs to know who the current user is, to find which shopping cart to load.
I found there are a couple of ways so far, but not happy with any of them:
using wcf aspnet compat. silverlight can ask who the current user is by asking the wcf service.
pass parameters from the page to xaml by using xaml.InitParameters and pass in the minimum amount of information to identify a user in a serialized format.
pass parameters through query string to xaml (apparently this is also possible)
Can anyone share the best practice to achieve this?
Thanks
We use the first solution in our projects. You haven't to invent any type of serialization format or so in this case. A disadvantage of this approach - extra async logic at startup.
The example of service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class UserInfoService : IUserInfoService
{
public UserInfo GetUserInfo()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
return null;
var userInfo = new UserInfo
{
Login = HttpContext.Current.User.Identity.Name,
Fullname = ...,
};
return userInfo;
}
}
Sending userid via initParams or query string is not good idea I think. Such things should be more hidden.
The real important thing is to verify user on server on each service call because anyone can call your services in similar way as your app.
HTH

Resources