Im new on spring security and I had some research on authentication ,I saw two options there are some guys posted.First one Jdbc authentication or In memory authentication ,and there are also loadUserByName(UserDetailService).
what is difference between them ,and also what is use case of loadUserByName (UserDetailService)
This is the official reference https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#jc-authentication
For In Memory Authentication, you have a set of username-password pair hard-coded in your xml/java config class.
In jdbc authentication, you can have a direct database contact to fetch users and authorities, provided you have configured a datasource
You can define custom authentication by exposing a custom UserDetailsService as a bean. You can do whatever functionality to return an instance of UserDetails in loadUserByUsername(). This method is called implicitly to authenticate a user, when creating an authentication.
Related
I am using SpringBoot 2.0.5 and Spring Security OAuth to implement an OAuth 2.0 server and a set of client microservices.
In the AuthServer:
I have implemented the UserDetailsService so I can provide my custom enriched principal.
For the userInfoUri controller endpoint, I return user (my principal) and authorities as a map.
In the Client:
I have implemented PrincipalExtractor to extract and create my custom principal.
For each of the methods I require the principal, I use the following notation:
public List<Message> listMessages(#AuthenticationPrincipal MyPrincipal user)
This works (and I hope it's the right way) but now I'm having an issue to secure methods using scopes.
For example, if I want to have a controller method which is only accessible by another server (using client_credentials), I mark the method with the following annotation:
#PreAuthorize("#oauth2.hasScope('trust')")
But this results in an access error as I think the scope is not being transferred. I have added the scope to the userInfoUri endpoint but am unsure what I need to do on the client side so the scope is picked up.
Any pointers or example code would be very much appreciated.
In this example: https://www.baeldung.com/spring-security-cas-sso
there is this piece of code:
#Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider provider = new CasAuthenticationProvider();
provider.setServiceProperties(serviceProperties());
provider.setTicketValidator(ticketValidator());
provider.setUserDetailsService(
s -> new User("casuser", "Mellon", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
provider.setKey("CAS_PROVIDER_LOCALHOST_9000");
return provider;
}
I don't understand this part:
provider.setUserDetailsService(
s -> new User("casuser", "Mellon", true, true, true, true,
AuthorityUtils.createAuthorityList("ROLE_ADMIN")));
what are we supposed to put here ? Am I supposed to create my own UserDetailsService (if yes, how ?) ? I was expected some 'default cas user detail service'...
how does this code work? creating a user to provide a UserDetailsService ?
This is how Spring security works on high level.
User tries to authenticate via some type of UI (part of CAS for example). The UI will pass username/password to Spring. Spring will eventually call UserDetailService.loadUserByUsername and pass the username to it, and if user exists the UserDetailService will return non null UserDetails. In case of null UserDetails or non null one with different password Spring will fail authentication.
CAS is just an authentication server, it leaves open how user is stored. You can choose to use LDAP or database. That choice is based on different implementation of UserDetailService. Look at javadoc again. It has list of default implementations you can use.
See part 5 of your linked tutorial. It shows how you can change both CAS and Spring Boot app to use database as user storage. The key here is that in order for back end to work with CAS server against users stored in database both need to be configured appropriately in order to look up user against database. CAS is configured via application.properties and Spring boot via UserDetailService.
Now to your questions in the comment:
why should the client bother about how cas server store the users ?
Client should not bother with UserDetailService. It is only used by back end service that is secured by CAS.
Just to be sure that I get it tight: if I just need to know 'is that
user connected?' then CAS is enough and I will never use
UserDetailService. But if I need some information about the user
(name, telephone etc..) then I call the UserDetailService to load it
(from db, ldap or whatever).
Yes and no. You dont need to store password in UserDetails but you need to be able to return UserDetails for successful CAS authenticated user. See this part from your linked tutorial:
Note again that the principal in the database that the server uses
must be the same as that of the client applications.
I want to implement the login/logout (authentication/authorization) system of my Spring 4 MVC application with Spring Security.
Currently I use a very simple hand-made implementation which basically does nothing more than comparing the entered username and MD5 hashed password with the database values by looking up the user by the username using a custom service method and comparing the encrypted passwords.
If the passwords match, the username of the logged in member is saved in the session and a ControllerAdvice looks up the Member object for the user using the username in the session prior to each request. The checkLogin method returns true is username and password match:
#Service("loginService")
#Transactional
public class LoginServiceImpl implements LoginService {
private MemberDao dao;
//more methods
#Override
public boolean checkLogin(String username, String password) {
String hashedPassword = getPasswordHash(password);
return dao.checkLogin(username, hashedPassword);
}
}
This does work but is not a very elegant solution, does not handle different roles and is probably not very secure. Besides I want to become familiar with Spring Security.
Reading the official tutorial for Spring Security (http://docs.spring.io/spring-security/site/docs/4.0.4.RELEASE/reference/htmlsingle/#tech-userdetailsservice) the way to go to authenticate against the Login service method does not become clear to me.
The tutorial discusses authentication direct against the database but I cannot find anything about using a Service method to perform the authentication and in my layered architecture, the database is hidden behind the Servoce and Dao (Hibernate) layers.
Also most examples in the tutorial use XML based instead of Java based configuration which I use for my application.
After having search a lot with search engines, I still have not found a tutorial which implements Spring Security in a Spring MVC application using a familiar layered structure using a Service and Dao layer.
Do I need to bypass Service and DAO/Hibernate layers and authenticate directory against the database? Or write a custom authentication-provider implementing UserDetailsService as described in this post?
Spring Security 3 database authentication with Hibernate
And is configuring Spring Security possible with Java based configuration only? I am a bit lost with this issue so I hope for some hints...
I have a spring project that uses spring-oauth2 and spring-security for authentication using an LDAP auth provider.
In controllers I can access the current principal's UserDetails using the #AuthenticationPrincipal annotation.
However, when I hit the endpoint with a client_credential token the #AuthenticationPrincipal is a String which is the OAuth client id. I understand that there's no notion of user when you authenticate with client_credentials, but I would like to have my Principal be a richer datatype. How does spring decide to set my principal as a String and can I override that behavior?
From the Oauth2 specs
The client credentials (or other forms of client authentication) can
be used as an authorization grant when the authorization scope is
limited to the protected resources under the control of the client,
or to protected resources previously arranged with the authorization
server. Client credentials are used as an authorization grant
typically when the client is acting on its own behalf (the client is
also the resource owner) or is requesting access to protected
resources based on an authorization previously arranged with the
authorization server.
because client can also be a resource owner, therefore spring will create authentication based on your client information.
I assume that you have setup org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter which is used to create authentication for the client.
You can create your own custom org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService or create your own org.springframework.security.authentication.AuthenticationProvider to override how the authentication object is created, but I prefer to use org.springframework.security.oauth2.provider.token.TokenEnhancer to add additional information to the token generated.
I'm going to implement a custom authorization based on ([User<-->Role<-->Right]) model and Rights should be compared to controller and method name (e.g. "controller|method").
I used customizing UserDetails and AuthenticationProvider to adjust granted authority (here), but as checked source codes and docs about how customizing the compare of authority I found there is a filter SecurityContextHolderAwareRequestWrapper) that implements isGranted and isUserInRole to compare authority, while the documents say using AccessDecisionManager voters to customize (As I understood). Which one should be used ? Where I have controller and method(action) name to compare authority with them ?
I got confused about Spring security a little. Is there any other resource than official docs that illustrate how it works, I mean sequence of actions and methods and how customize them.
There are several approaches:
Role based, where you assign each user a role and check the role before proceeding
Using Spring security expressions
There is also a new spring acl components which lets you perform acl control on class level and are stored in a database.
My personal usage so far has been 1 and 2, where you only assign roles to users.
But option 3 allows you to create finer grained security model, without having to rebuild your webapp when chaning the security model
Role Based
A role based security mechanism can be realised implementing the UserDetailsService interface and configuring spring security to use this class.
To learn on how to such a project can be realized, take a look at the following tutorials:
Form based login with in memory user database Link
Form based login with custom userdetails service Link
In short spring security performs the following behind the scenes:
Upon authentication (e.g. submitting a login form) an Authentication Object is created which holds the login credentials. For example the UsernamePasswordAuthenticationFilter creates an UsernamePasswordAuthenticationToken
The authentication object is passed to an AuthenticationManager, which can be thought of as the controller in the authentication process. The default implementation is the ProviderManager
The AuthenticationManager performs authentication via an AuthenticationProvider. The default implementation used is the DaoAuthenticationProvider.
The DaoAuthenticationProvider performs authentication by retrieving the UserDetails from a UserDetailsService. The UserDetails can be thought of as a data Object which contains the user credentials, but also the Authorities/Roles of the user! The DaoAuthenticationProvider retrieves the credentials via its loadUserByUsername method
and then compare it to the supplied UsernamePasswordAuthenticationToken.
UserDetailsService collects the user credentials, the authorities and builds an UserDetails object out of it. For example you can retrieve a password hash and authorities out of a database. When configuring the website url-patterns you can refer to the authorities in the access attribute. Furthermore, you can retrieve the Authentication object in your controller classes via the SecurityContextHolder.getContext().getAuthentication().
Furthemore to get a better understanding of the inner workings of these classes you can read the javadocs:
UserDetails - how the user credentials are stored and accessed
AuthenticationManager.authenticate(..) - contract on how AuthenticationExceptions are handled
UserDetailsService.loadUserByUsername(..)- contact on how username lookup failures are handled, e.g. user does not exist
Spel
Instead of checking authorities, SPEL enables you also to check other properties of a user.
You can use these in the URL patterns, but also annotate methods with #Preauthorize.
This way securing the business layer is less intrusive.
ACL Based
The ACL based model was introduced in spring security 3.0, but hasn't been well documented.
Their suggestion is to look at the Contacts XML example, since this one uses their new acl component.
Last this book contains great examples on how to further customize your security wishes.