Proper way to dependency inject authenticated user to my repository class - asp.net-mvc-3

I am using a service layer with repository pattern. The controller has a dependency on the service layer, and the service layer has a dependency on the repository.
I have to pass logged in user information to the repository layer for authorization purposes and am trying to determine the best approach for injecting the user information into the repository considering that I seem to have an extensive injection chain:
controller -> service(s) -> repositories -> logged in user info.
I guess the easy approach would be to pass the user information to the service methods that get called(i.e. FindById(int primaryKey, User currentUser), etc.)
But this seems very limiting and problematic down the road as opposed to injecting the User information.
What is the recommended approach to this problem?
I am a little confused about how the person in the article seems to be implementing the ICurrentUserFetcher. I assume that is would provide the extra properties that are not available from the IIdentity, but the article does not make this very clear.
class GenericRepository<T>: IRepository<T> {
private readonly ICurrentUserFetcher currentUserFetcher;
public GenericRepository<T>(Func<IIdentity> currentUserFetcher) {
this.currentUserFetcher = currentUserFetcher;
}
public void Update(T entity) {
var currentUser = currentUserFetcher();
...
}
}
var repo = new GenericRepository<Person>(() => HttpContext.Current.User.Identity);

Assign the user information to the current principal after the login. Google about IPrincipal and IIdentity. Those two classes are the built in way in .NET to handle the currently logged in user.
To access the user simply use Thread.CurrentPrincipal.Identity. I would however not use that property in the repository, but only in the service class. The reason to tha this that the repository should not be in charge of telling which user to fetch information for.
To assign the user on every request you have to use the PostAuthenticate event in global.asax.

Related

Spring: Why is it bad to return a whole OAuth2User in an endpoint?

I'm building an OAuth2 authenticated app using Spring Boot, following this tutorial: https://spring.io/guides/tutorials/spring-boot-oauth2/
At one point, the endpoint /user sends back the currently logged in user.
The guide warns by saying:
"It’s not a great idea to return a whole OAuth2User in an endpoint since it might contain information you would rather not reveal to a browser client."
But it doesn't give any more information - what type of information should I not be revealing to a browser client?
Thanks!
In Spring Security 5.x, the OAuth2User is a specific OAuth2AuthenticatedPrincipal (very similar to a UserDetails but without any notion of a password). Even without a password, exposing it can (and often will) leak sensitive information, implementation details of your authentication scheme, etc. You can expose it if you choose, but the warning in the guide is suggesting that care should be taken so as not to expose anything considered sensitive, and you should consider alternatives before exposing it directly.
For example, you might consider creating a CustomUser class that is populated from claims on the OAuth2User using a custom OAuth2UserService (various examples in the advanced configuration section of the docs). You can also take various steps to decouple the representation of an oauth2 user in Spring Security from the representation of a user in your application (e.g. by using #AuthenticationPrincipal to resolve your own custom user or access claims). If the application itself does not need a custom user, you can simply map claims of the OAuth2User to a response in your custom endpoint, as demonstrated in the guide.
Finally, you can combine all of these techniques to make your /user endpoint a "one liner" again, as in:
#Target({ElementType.PARAMETER, ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#AuthenticationPrincipal(expression = "customUser")
public #interface CurrentUser {}
#GetMapping("/user")
public CustomUser user(#CurrentUser CustomUser customUser) {
return customUser;
}

Custom RoleProvider in a MultiTenant MVC App

I need to develop a custom RoleProvider for a MultiTenant web app.
At the DB level, we have a table that relates Users with Roles with Tenants.
My problem is that RoleProvider gets user roles just passing the User as parameter, and we need to take the Tenant into account.
In RoleProvider implementation we have:
public override string[] GetRolesForUser(string username)
{
//Code to retrieve roles from repo
}
As the roles are for a user in an specific Tenant, we need:
public override string[] GetRolesForUser(string username, int tenantId)
{
//Code to retrieve roles from repo
}
The current tenant is stored in the ControllerBase class (the one that all controllers inhereted from).
The Membership and Role Providers are in a separate project, so I don't see a way to use the current Tenant. I think I could create my custom RoleProvider in the web app project.
Any idea on how to implement the RoleProvider interface taking the Tenant as part of the input ?
Well, just to inform you what I did in my case:
As our routes are in the form of http://[tenantName].[domain]/[App]/[Area] we ended up getting the [tenantName] from the Request, since it is unique, and with the Tenant and the UserName that came as a parameter I can do my select on our UsersInTenants' table.
The very same can be done using cookies as a way to pass aditional information.
So you can access the request, with the cookies, but for what I research the Session is not yet initialized in most cases.
Hope it helps!

Spring Security user account registration, creation and management

I've been looking into using Spring Security for the authentication/authorization of my web application (this will be JDBC based).
However, a core component seems to be left out from my perspective. How do I register/create new users? Is there an out of the box API for that?
Do i need to write user registration and management from scratch?
Things i need to do include:
- Registering a new user
- Resetting passwords
- Emailing a user to activate their account
- Emailing a user to reset their account.
Thank you in advance.
I use Spring Security on my project. The framework does not have an API for user creation or registration as you asked. For Spring Security to be generic and usable across multiple frameworks, it can only take you so far before you have to write custom code. You can't really get a more specific answer about a framework or tool to use because at this point you will just use the frameworks you are already using anyway.
If you've set it up to use users and roles in your database, from your data access layer you would create a record in the user table or update a password (preferably stored as a hash) in that record. And as Aravind said, Spring does provide email support.
If you really want to see one way to do it: I'm using Spring MVC, JSP, and Hibernate. I use Spring's form tags in a JSP to bind a new user form to a Person object, and my controller method passes that Person object to my Dao to persist it.
The controller method signature looks like this...
#RequestMapping(value = "/newUser", method = RequestMethod.POST)
public ModelAndView createNewUser(final #Valid #ModelAttribute Person user,
final BindingResult result,
final SessionStatus status,
final #RequestParam(value = "unencodedPassword", required = true) String password) {
...
user.getRoles().add(new Role(user, Role.APPLICATION_ROLE.ROLE_USER));
userDao.createNewUser(user);
...
}
and my PersonDao would use Hibernate to persist the user like so
#Transactional
public void createNewUser(Person user)
{
Session session = sessionFactory.getCurrentSession();
session.save(user);
session.flush();
}
Have a look at my answer here.
"I have implemented a JAVA project for this use case. It is open
source, based on Spring-Security. A release version is on
Maven-Central, so you do not need to compile it, but instead you can
fetch it as maven-dependency to your project!"
<dependency>
<groupId>com.ohadr</groupId>
<artifactId>authentication-flows</artifactId>
<version>1.5.0-RELEASE</version>
</dependency>
As far as I know, Spring Security does not have built in support for new user creation and registration. You will have to manage this yourself. However it does have emailing support. Check here for more on this.

use existing domain classes with Spring Security plugin

I'm trying to convert a Stripes web app to Grails. The Stripes app uses Spring Security, but I would like the Grails app to use the Spring Security Grails plugin.
The app already has User and Role (Java) classes that I need to reuse, i.e. I cannot use the Grails domain classes that the s2-quickstart script generates.
The Spring Security plugin docs describe how to use an existing User domain class. The steps seem to be:
define a UserDetails implementation that reads from the existing User domain class
define a custom UserDetailsService implementation that returns instances of (1)
register an instance of (2) as a Spring bean named userDetailsService.
However the docs don't provide any information about how to use an existing Role class and the class that represents the many-to-many relationship between User and Role.
What other steps are necessary to use existing Role, User, and UserRole classes with the Grails Spring Security plugin? Is there any reason for me to run the s2-quickstart script if I don't want to generate any domain classes?
Follow-Up Questions to Burt's Answer
In the end, what you need is a new GrailsUser
Presumably GrailsUser here refers to the custom UserDetails implementation? In my case I'll probably just implement the interface directly. Does something like this seem reasonable?
class UserAdapter implements UserDetails {
private String password
private Collection<GrantedAuthority> springRoles
UserAdapter(User user) {
this.password = user.password
Collection<Role> roles = // load legacy Role objects
this.springRoles = roles.collect { new GrantedAuthorityImpl(it.authority) }
}
// If using password hashing, presumably this is the hashed password?
String getPassword() {
password
}
///////// other UserDetails methods omitted
Collection<GrantedAuthority> getAuthorities() {
springRoles
}
}
I'm not storing the whole User object within UserAdapter because of your warning about storing a potentially large object in the HTTP session.
what you need is.....and a List of GrantedAuthority instances (and the id if it's a GrailsUser)
If I use my own UserDetails implementation as above, then presumably I can ignore this comment about providing an id?
Finally, if I follow the approach outlined above, should I set these properties in Config.groovy and do I need to run the s2-quickstart script (or any others)?
Keep in mind that Spring Security doesn't care where the data comes from, it just needs a UserDetails instance when authenticating with the DAO auth provider and it can come from anywhere. It's convenient to use domain classes and database tables, but it's just one approach. Do what works for your data. In the end, what you need is a new GrailsUser (or some other impl) instance with the username and password set, the 3 booleans set, and a List of GrantedAuthority instances (and the id if it's a GrailsUser).
The simplest thing to do when you have legacy user and role data is to create a custom UserDetailsService. Use GORM, raw SQL queries, whatever you need to get the required data.
Another option is to write your own AuthenticationProvider like Glen did here: http://blogs.bytecode.com.au/glen/2010/01/15/hacking-custom-authentication-providers-with-grails-spring-security.html - although that's a larger solution that also involves a custom filter which you wouldn't need. The DAO provider uses a UserDetailsService but it's fine to create your own that combines the functionality into one class.
It's not a good idea to reuse your User domain class as the UserDetails though. Even if you implement the interface, you'd be storing a disconnected potentially large (if there are attached collections) object in the HTTP session. The POJO/POGO implementations (Spring Security's User class, the plugin's GrailsUser class, etc.) are very small and just a few Strings and booleans.
within the config.groovy file you have to specify your domain classes to use:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'your.package.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'your.package.UserRole'
grails.plugins.springsecurity.authority.className = 'your.package.Role'
i thinks it's not neccessary to implement your own userDetail service, because spring security uses
SpringSecurityUtils.securityConfig.userLookup
method to determine the domain class you configured before. your domain classes must provide the required fields and relations.

MVC3 Action Filter Using Database (EF 4.1 DBContext, Ninject)

I'm trying to setup an 'Authorization' Filter on an Action, creating my own ActionFilterAttribute where I do a database lookup to determine if a user has access to a certain resource.
On my class inheriting from ActionFilterAttribute, I have created an Injected(Ninject) property to hold the service that I am using for the database access. I have a parameterless constructor so that I can use this as an attribute on my actions. In the 'OnActionExecuting' Method, I am able to gain access to the Injected property (it's not null), but the base DBCotext that it is using is closed.
This working fine, up until the RTM of MVC3, where the Release Notes stated:
Breaking Changes:
In previous versions of ASP.NET MVC, action filters are create per
request except in a few cases. This
behavior was never a guaranteed
behavior but merely an implementation
detail and the contract for filters
was to consider them stateless. In
ASP.NET MVC 3, filters are cached more
aggressively. Therefore, any custom
action filters which improperly store
instance state might be broken.
The first time I use this filter, it works as expected, but if I refresh the page or another user access this filter, I get the error:
The operation cannot be completed
because the DbContext has been
disposed.
which is what I guess I should expect given the breaking changes notes.
My question is this, what would be the preferred/recommended way of accomplishing what I need to do? Should this be in an ActionFilterAttribute, or should this 'authorization' be done somewhere else?
I'd do authentication in Application_AuthenticateRequest and authorization in your attribute using Thread.CurrentPrincipal, but your method should work too. You just need to count with fact that DbContext will be different for each request but your attribute won't. Something like this should do the trick (I'm assuming you are using DependencyResolver):
public class MyMightyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var context = (DbContext)DependencyResolver.Current.GetService(typeof(DbContext))
// authenticate, authorize, whatever
base.OnActionExecuting(filterContext);
}
}
I have been battling with this for a while and finally solved my problem. So here is my solution in the hope it may help someone else.
The setup:
1. I have an MVC3 project, a custom action filter that accesses the db using EF5 via a business service.
2. I use Unity and unity.MVC to resolve my dependencies on a per request basis.
3. I use property injection into my custom Action filter, as it has a parameterless constructor.
The result.
Dependency injection works correctly for all the services used by actions, my EF DbContext is correctly disposed of at the end of each request.
The Problem
Although my property dependency is resolved in my custom action filter, it contains a stale instance of my DbContext (e.g. it seems to have been cached from the previous request)
As mentioned in previous posts, MVC3 is more aggressive with filter caching and the state of a filter cannot be relied on. So the suggestion was to resolve the dependency in the OnActionExecuting method. So I removed my injected property and did just that called resolve on my unity container. However I still got a stale version of the DbContext. Any changes in the DB were correctly queried in my main actions, but the custom action filter didn’t pick them up.
The solution.
Unity.MVC Manages per-request lifetime by using child containers and disposing these at the end of each request. By resolving my dependency’s in the action filter from my unity container I was resolving from the parent container which is not disposed of on each request.
So rather than
IoC.Instance.CurrentContainer.Resolve<IService>();
I used this to obtain an instance of the child container rather than parent.
var childContainer = HttpContext.Current.Items["perRequestContainer"] as IUnityContainer;
var service = childContainer.Resolve<IServcie>();
I'm sure there must be a clean way to achive the same result, so please add suggestions.
Ok slight refinement to allow my unit test to inject a mock of the service.
1. remove the dependency resolve from the the OnActionexecuting and add two constructors.
public MyCustomActionfilter() : this(((IUnityContainer)HttpContext.Current.Items["perRequestContainer"].Resolve<IService>())
and
public MyCustomActionfilter(IService service)
{
this.service = service;
}
Now the constructor resolves your service and stores it as a private readonly. This can now be consumed in your OnActionExecutng function. Unit tests can now call the second constructor and inject a mock.

Resources