I have a Custom User class that extends the User(Spring Security's) class and Custome UserDetailsService class. This service queries the database using Hibernate service method to fetch user details. If there is no records found in the database for that userId, instead of throwing a UsernamNotFoundException, I want to create a dummy Custom user object and pass the authentication with read-only attributes. But I can't get it working because, I am not sure how to retrieve the password value entered by user on the login page. I need to pass it to the custom user constructor to get it authenticated properly..
So, to sum it up, is there anyway to retrieve password entered by the user on login page inside the loadUserByUserName() method? Thanks in advance
I am doing something in a similar vein a current project. I have just started getting into Spring Security over the past 2 weeks, but I've really dug into it during that time (attached source, went through it in the debugger).
I have a Custom User class that extends org.springframework.security.core.userdetails.User and a custom class that implements org.springframework.security.core.userdetails.UserDetailsService interface.
As you know, the signature of the loadUserByUsername method in UserDetailsService interface specifies that a class implementing UserDetails interface is going to be returned.
Spring Security is going to take the class that implements UserDetails and check the username and password provided by login form / basic authentication / digest authentication / (whatever authentication scheme you selected) against the Username and Password in UserDetails.
I have not found a way that you can get at the credentials provided by the end user via authentication scheme. If you want, I could try looking into it when I'm back at work tomorrow (I'm at home and writing this from memory.
I am running Spring 3.0.6 RELEASE and Spring Security 3.0.6 RELEASE.
I ran the code in my debugger. You will not be able to get at the Authentication object from the custom UserDetailsService.
However, I believe you may be able to create your own AuthenticationProvider that gets at it: http://static.springsource.org/spring-security/site/docs/3.0.x/reference/core-services.html
Please reference this code snippet from Spring Security's org.springframework.security.authentication.ProviderManager, which loops over the AuthenticationProvider(s):
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
logger.debug("Authentication attempt using " + provider.getClass().getName());
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
} catch (AccountStatusException e) {
// SEC-546: Avoid polling additional providers if auth failure is due to invalid account status
eventPublisher.publishAuthenticationFailure(e, authentication);
throw e;
} catch (AuthenticationException e) {
lastException = e;
}
}
As you can see, it loops over each AuthenticationProvider and passes in the Credentials. Hope that helps!
Philip
We are able to do something similar to what you're asking by extending AbstractUserDetailsAuthenticationProvider. There's an method retrieveUser(String _userName, UsernamePasswordAuthenticationToken _authToken) that you can override and put in your own custom logic. The return object is a UserDetails. So at this point you can create your own custom UserDetails and return it back to the framework (note: you can set your read-only attributes in this method as well).
At this point Spring Security will not have tried to authenticate using the password. They leave that to the additionalAuthenticationChecks(UserDetails _userDetails, UsernamePasswordAuthenticationToken _authToken) method that you can also override. Since this is where you would do your password validation it's ok to just skip the validation and let the method return. At this point your anonymous user will be validated.
Finally add this into your security.xml
<authentication-manager alias="authenticationManager">
<authentication-provider ref="appUserSecurityService" />
</authentication-manager>
I hope this helps!
Related
I need help of experts!
I write ASP.NET MVC 4 Intranet application. I using Windows Authentication, the domain name get through User.Identity.Name. I have a database with the configured data context, where more complete information about the user: Last name, First name, E-mail, etc. As well as a list of user access groups.
Needed to make sure that a user open a program, has received the required access from the database, his name brought up in the upper right corner of the page.
Now I have realized that with the use of OWIN Asp.Net Identity. I created a base controller that inherits the other controllers, it ordered CurrentUser method for the user and his SignIn:
protected ApplicationUser CurrentUser
{
get
{
var curUser = AppUserManager.FindByName(User.Identity.Name);
if (curUser != null)
SignInManager.SignIn(curUser, true, true);
else
curUser = new ApplicationUser();
return curUser;
}
}
protected ApplicationSignInManager SignInManager
{
get
{
return HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
}
I understand that these operations are unnecessary, when you refresh the page every time it is necessary to drag into the database, users receive and make SignIn, which is unnecessary.
I'm sure you can realize all without using Asp.Net Identity. For example by expanding IPrincipal User, adding him to the field name, which are needed when displaying pages and adding once Roles from the database and save all in Cookies.
Please, help me! And sorry for my bad english...
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
I have a couple of systems which uses external authentication, google authentication.
I'm just keeping the login information in a session variable and keep track of the user that way (no membership provider).
I would like to have the user identity in the HttpContext.Current.User object.
Should I assign the user manually on an event in Global.asax.cs, or could I have the user automatically identified during the session?
You could write a custom Authorize attribute which will take care of assigning the HttpContext.Current.User property from the session:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var user = httpContext.Session["username"] as string;
if (string.IsNullOrEmpty(user))
{
// we don't have any username inside the session => unauthorized access
return false;
}
// we have a username inside the session => assign the User property
// so that it could be accessed from anywhere
var identity = new GenericIdentity(user);
httpContext.User = new GenericPrincipal(identity, null);
return true;
}
}
Then simply decorate your controllers/actions that require authentication with this custom attribute.
Use a membership provider, it will give you exactly what you want. Even creating your own provider isn't too difficult, just implement the abstract class MembershipProvider and plug into config, or use some of the out-of-the-box providers.
Don't roll your own solution for something critical like security, it will have gaping security holes. Storing authentication info in the session is a really bad idea. It leaves it open to session hijacking, session replay attacks etc.
If you really want to go down the route of custom authentication. Then have a look at the code I posted here. It will show you how you can take control of the authentication cookie, and use this to create your own HttpContext.Current.User instance.
I'm securing an ASP.NET MVC 2 application, and I have a user who is in the role "Foo".
This is true:
User.IsInRole("Foo")
But yet, when I attempt to lock down a controller action like the following, the user is denied:
[Authorize(Roles = "Foo")]
public ActionResult PrivatePage()
{
return View();
}
If IsInRole reports true, why would the Authorize attribute not allow the user in?
It could be caused if you are storing persistent cookies for your forms authentication cookie. In that scenario IsInRole may check against the cookie without verifying up to date login.
For future people with a similar problem - it could depend on how you are actually setting up your roles on the current user.
I had a similar issue where the roles were being pulled out of the cookie in an override of OnActionExecuting in a base controller. Turns out this was executing after the [Authorize] attribute, so the roles weren't actually set up when the attribute was checking for them. The call to User.IsInRole, being in the View, was executing after OnActionExecuting, so it saw the roles fine.
So User.IsInRole returned what I expected, but the [Authorize] attribute did not.
I was able to resolve this by moving the code for getting the roles into a more sensible place, that executes before the Authorize attribute - for example, in Global.asax.cs:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// do stuff in here
}
Or even better, in your own custom attribute - see https://stackoverflow.com/a/5314736/206297.
They should both return true. Have you tried using SQL Profiler to check the queries run against the DB?
So I know the best practice would be to run my Flex app over ssl along with implementing other forms of security however that isn't an option at this point (for monetary reasons and the app simply doesn't need that much security otherwise my sponsors would pay for it). However, I would like to implement some form of security and I'm wondering whether it's even worth it when I don't have ssl to protect the transactions.
So my setup is that I have a ASP.Net server side with a Flex UI. Right now the UI is the only thing that protects access to the sever: the server doesn't do any sort of verification during each request, it just assumes the person is allowed to do it. Obviously, anybody could write a program to generate posts (even if I could use SSL it would be like swiss cheese). Like I said before, security isn't a big deal, this is an internal app and it's nothing critical, however I do believe in doing things right. Would keeping the user info in session be a viable option and then verifying that the given user has permission, etc. Perhaps some sort of token system?
What would your preferred method of protecting this setup be?
...and no, I won't give you the url :)
ASP.NET Session itself is token based security and yes you can easily implement that by doing
[WebMethod(true)]
and yes, any web method requires login to be done first, it should call User.IsAuthenticated, that verifies the session token.
You can easily implement form authentication (let web.config empty, you can use FormsAuthentication in code).
for example,
[WebMethod(true)]
public string DoLogin(
string username,
string password)
{
//.. do your verification
FormsAuthentication.SetAuthCookie(username,false);
return "Login Sucessful";
}
[WebMethod(true)]
public string ChangePassword(
string oldPass,
string newPass)
{
// verify user is logged on or not..
if(!User.IsAuthenticated)
return "Please Login";
// The code below is secure, only
// authenticated user will go through below
// change pass...
return "Password Changed Successfully.";
}
We developed many Flex+ASP.NET sites, we did exactly same thing, but instead of return "string" we usually return a class like following...
public class WSResult<T>{
public bool Successful;
public string Message;
public T Result;
public T[] Results;
}
The convention is simple, if method was successful then you return Success = true, and depending upon whether you want to return an array of items or just single item, you can return either Results or Result. In case if there has been any error or unathorized access you can set Successful=false and set Message as detailed string. As per following example.
[WebMethod(true)]
public WSResult<BusinessUser> DoLogin(
string username,
string password)
{
try{
BusinessUser user = BusinessUser.GetByUsername(username);
if(user==null)
throw new Exception("User not found");
if(user.Password != password)
throw new Exception("Password did not match");
return new WSResult<BusinessUser>{ Result=user };
}catch(Exception ex)
{
// this will even catch any DAL exceptions or any system error as well
// Log Exception... somewhere for tracking...
return new WSResult<BusinessUser>{ Successful=false, Message = ex.Message };
}
}
Unfortunately, I know diddly squat about flex, but I think I can help anyway. I think you have two reasonably good options.
First though, we need to clarify something... Are you saying the server doesn't do any authorization? Does it at least have the ability to authenticate a user? Do you have any control over the server code? If not, I don't think the following suggestions will help. I'm not sure how you're supposed to secure a server with just client side code. Maybe there is a way, but I can't think of it.
1) Use HTTP digest authentication. This requires that the server is configured to understand it and that there is support in the flex api for adding the appropriate auth header to the HTTP request. The server authenticates the user by his password and can check what operations can be performed by said user against some authorization mechanism.
2) Follow the guidelines in this article to implement the authentication scheme that many atom publishing endpoints use. The flex api will have to provide some support for this, maybe there is an existing third party lib though. If you can get access to the HTTP headers you should be able to implement the rest.
Good luck.
How are you commuicating with the server SOAP. REST etc?
If it is SOAP have a look at the answer to this question
General Password Security && Implementation in Actionscript 3
and here's a link how to add the header to the SOAP message
How to add a "flat" message header to a flex web service call?
Hope this helps
Jon