How to check the userdetails before spring security authentication is takes place.
Here in my project during login i need to check the basic validations username/password exists , validity of username , max retry limit(5invalid entries after that block a/c) and show error based on the failure.
On correct username/password need to check whether user logging into application for first time (based on flag in db) ,if so need to display an disclaimer page[ to access the application the user should accept the disclaimer].
Here is the flow
username/pwd in form -> Submit ->check for valid credentials
--> No --> display error[update retry flag]
--> yes -->check validity-->exceed->display error
-->with in validity period-->check is first time(and disclaimer accepted) -->show app if disclaimer already accepted else show disclaimer page without logging into application
On I accept button login the user to application.
I don't think this will involve Spring security per se. In your action class just call a method that checks the DB. If they have been logged in before return to an action that redirects the user to whatever page is appropriate. If they have not, then send them to the disclaimer page.
When they submit the form for the disclaimer page, check for acceptance. If accepted, then update the DB and redirect them to the appropriate page. If not, display an error.
If I recall Spring security correctly, the acceptance page and the login page, etc. will not be secured, but other pages will be. So, like I said, I'm not sure that Spring is really involved. It is just a matter of correctly routing via your Struts actions which do all the work of looking up in the DB and routing.
Basically, spring security takes care of it - but you can override it.
This is just a simple example how i would do it:
#Autowired
private AuthenticationManager authenticationManager;
#RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login(#RequestBody AuthenticationRequest authenticationRequest, Device device) throws AuthenticationException {
// Perform the security
final Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(),
authenticationRequest.getPassword()
)
); ...
}
AutheticationRequest is just a simple object with 2 Strings inside (username, password)
Bare in mind that this method throws AuthenticationException but you can also catch it in try/catch and do some logic on failed login.
Hope it helps.
Related
I have some JSF 2 applications that are currently working with a JSF Secutiry LoginModule (auth-method = FORM). But authentication will be done now through a new way, that means I'll have to manually program the authentication interactions.
That's fine, but now I have problems setting the roles. I couldn't find where I can set the Principals, or get subject to do it, or get shared state to put "javax.security.auth.principal" and "javax.security.auth.roles" variables.
Is there a way to do it? Here is a sample of my actual Bean code.
Thanks in advance!
#ManagedBean
#ViewScoped
public class PrincipalController extends AbstractController implements ExcluirRascunhoService.Presenter {
// has get and set
#ManagedProperty(value = "#{autenticacaoController}")
private AutenticacaoController autenticacaoController;
#PostConstruct
private void init() {
try {
// a previous application redirected the user here,
// giving two parameters, including a valid and calculated HASH
// to be passed to authentication
Map<String, String> requestMap = getContext().getRequestParameterMap();
String user = (String) requestMap.get("login");
String hash = (String) requestMap.get("hash");
// this will do the authentication, communicating with a
// webservice and passing these data so the webservice can
// authenticate the data, telling me if the user is Ok
autenticacaoController.authenticate(user, hash);
// do the other things if authentication doesn't throw an exception
// I should now fill all user's Roles accordingly to my database
// I get them correctly, but how to set them into the JSF Roles?
} catch (AuthenticationException e) {
// catch and quit the page
}
}
}
You can't do it with JSF alone. Basically, JSF only provide a utility to get the user and it's role directly from the JSF interface. So, if you want to access the principal user and it's roles from your application you must first authenticate the user.
To authenticate your user you can use an third party solution like JAAS or Apache Shiro to setup the realm, roles and control the authentications of your application.
You can also roll your own authentication layer, which may not give you the possibility to use some useful JSF utilities like getting the principal user or it's roles directly from the realm (note that your custom layer will probably provide other ways to get these values), but will also provide a custom way to do the authentication required.
I have found a pretty nice tutorial about JAAS authentication layer (in portuguese) that may help you setting up a authentication layer.
Wish you good luck and feel free to ask if you have any doubts about what I've said.
I was able to integrate Spring Boot and Spring Security SAML by using the #ImportResource annotation.
Now, I'd like to go on as follows:
the user selects an IdP [DONE].
it performs the login (successful) [DONE].
the SP obtains user data (by parsing the SAMLCredential object) [DONE].
the webapp had to check if the userID (e.g email) retrieved via SAML exists in my own DB.
a) If yes, the webapp reads from the DB the role and sets related privileges.
b) If no, the webapp had to perform a redirect to a sign-up page, in order to insert the user into the system.
Make it sense perform the points 4 and 5 by using a UserDetailsService implementation or have I to setup the security context defining authentication providers, filters, etc?
You should implement org.springframework.security.saml.userdetails.SAMLUserDetailsService and plug it into the samlAuthenticationProvider bean. In case user doesn't exist you should throw UsernameNotFoundException exception, otherwise just populate and return data from your DB.
On top of that you should implement your own org.springframework.security.web.authentication.AuthenticationFailureHandler and plug it into samlWebSSOProcessingFilter bean. This implementation will be called with the UsernameNotFoundException sent as a parameter and you can then redirect the user to the correct sign-up page as a reaction to it.
I'm trying to come up with the best way to do my own authentication in our Java REST API using the Jersey framework (v2.5.1) running on Tomcat 7.
The API will be accessed through our iOS application. In the iOS application we use Facebook authentication (using the Facebook SDK), and then we use the access token in every call to the REST API.
#Provider
#Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
// Extract the access token from the HTTP header
// Look up in the database to see if we have a user with that token
// If there is a user found, proceed
// If we can't find a user, we are going to send the token to Facebook to get the user details. If the token is invalid, we throw an exception. If it is valid, we look up if we can match the Facebook details with an existing user. When we can't match, we create a new user.
}
}
This filter will be executed in every API request.
My questions:
Is this a correct workflow?
Should we contact Facebook every time to validate the token? This will cause a lot of overhead.
This filter is executed for every request. How can we exclude certain urls (some resources won't require authentication)? I was thinking of holding a set of urls in the filter class and see if the requested url matches one of the defined public urls (if so, don't do the authentication).
Thanks!
I think it might be better if you can provide this option to your user:
login / login using facebook account.
So you dont have to contact Facebook unless user choose to login using their FB account.
also, the authentication should be session based. session information can includes user, session key, valid time range, maybe source IP too. once the user has successfully logged in, a session is generated. then for every request you only have to check if the session key is still valid.
I know this has been asked already, but I am not able to get it to work.
Here is what I would like to get accomplished:
I am using Spring Security 3.2 to secure a REST-like service. No server side sessions.
I am not using basic auth, because that would mean that I need to store the user's password in a cookie on client side. Otherwise the user would need to login with each page refresh/ change. Storing a token is I guess the lesser evil.
A web client (browser, mobile app) calls a REST-like URL to login "/login" with username and password
The server authenticates the user and sends a token back to the client
The client stores the token and adds it to the http request header with each api call
The server checks the validity of the token and sends a response accordingly
I did not even look at the token generation part yet. I know it is backwards, but I wanted to get the token validation part implemented first.
I am trying to get this accomplished by using a custom filer (implementation of AbstractAuthenticationProcessingFilter), however I seem to have the wrong idea about it.
Defining it like this:
public TokenAuthenticationFilter() {
super("/");
}
will only trigger the filter for this exact URL.
I am sticking to some sample implementation, where it calls AbstractAuthenticationProcessingFilter#requiresAuthentication which does not accept wildcards.
I can of course alter that behavior, but this somehow makes me think that I am on the wrong path.
I also started implementing a custom AuthenticationProvider. Maybe that is the right thing?
Can someone give me a push into the right direction?
I think pre-auth filter is a better fit for your scenario.
Override AbstractPreAuthenticatedProcessingFilter's getPrincipal and getCredentials methods.
In case the token is not present in the header, return null from getPrincipal.
Flow:
User logs in for the first time, no header passed, so no
authentication object set in securityContext, normal authentication
process follows i.e. ExceptionTranslation filter redirtects the user
to /login page based on form-logon filter or your custom authenticationEntryPoint
After successful authentication, user requests secured url, pre-auth filter gets token from header authentication object set in
securityContext, if user have access he is allowed to access secured
url
Summary
How do you get the session of a web service client using spring web services and spring security?
Details
After submitting
<form method="POST" action="<c:url value="/j_spring_security_check" />">...</form>
I've noticed that you can:
public class MyUserDetailsService implements UserDetailsService {}
Which will allow you to override methods like loadUserByUsername(String username) therefore being able to retrieve the submitted username and do a database lookup to return a user object.
The issue I have, however, is that I'm unsure where SecurityContextHolder gets set. I'm able to get the user object by using this line of code:
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
But I'm not sure how it gets set in the first place. I would like to know the flow after submitting the above-mentioned form so that I can identify how SecurityContextHolder gets set.
The reason why I want to know this is because I want to use it as a "session" for web service client authentication instead of having the client resubmit credentials with every request.
Spring Version: 3.0.2.RELEASE
/j_spring_security_check is handled by the UsernamePasswordAuthenticationFilter which extends AbstractAuthenticationFilter. The security context is set in the latter's successfulAuthentication method.
However, web-service clients are usually stateless and would be more likely to use something like Basic authentication with a shared secret. I'm not sure there would be much benefit in rolling your own session system based on the security context contents. If you are worried about performance then you could use a cache of authentication information on the server.