Hi im trying to make facebook's login in a grails app, the problem I have is that when the user is logged in facebook, spring security core doesn't recognize him, how can I set the user's principal manually?
I can look for the user object but i don't know how to set it in order to get a true user when i call getAuthenticatedUser() (now it returns a null object)
Thanks in advance,
Regards
Cannot say anything regarding facebook, but Spring Security has a SecurityContextHolder that can be used to manipulate the authentication (and therefore the principal) like this:
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
....
def securityContext = SCH.context
def principal = <whatever you use as principal>
def credentials = <...>
securityContext.authentication = new PreAuthenticatedAuthenticationToken(principal, credentials)
Maybe you'll need to use a different implementation of the Authentication interface as the one used in the example.
Related
How can I set up default roles in jhipster ? (using angularjs and spring).
I explain myself
in the registration page I want to specify the role for the registred user. let's say by a checkbox or a list. (for exemple human and animal )
How can I do that in the angular controller and in spring ?
What I can do now ?
I added the roles I need in the database and in angular and I can specify the roles for the new registred users , only through the Admin's users management page.
There is some work to do, to achieve that, so I will paste just the right parts with some small samples..
In general you must extend the API to become aware of a role selection, so this information can be provided explicitly. Then you change your angularJS frontend as you need.
for the backend
a registration happens by POSTing a ManagedUserVM to /api/account/register, so the first thing is to tell AccountResource.registerAccount(...) to pass a set of of strings (your roles) as additional parameter to userService.createUser
#Timed
public ResponseEntity registerAccount(#Valid #RequestBody ManagedUserVM managedUserVM) {
HttpHeaders textPlainHeaders = new HttpHeaders();
///...
User user = userService
.createUser(managedUserVM.getLogin(),
managedUserVM.getPassword(),
managedUserVM.getFirstName(),
managedUserVM.getLastName(),
managedUserVM.getEmail().toLowerCase(),
managedUserVM.getImageUrl(),
managedUserVM.getLangKey(),
//add authorities here
managedUserVM.getAuthorities()
);
mailService.sendActivationEmail(user);
//...
}
Then in UserService.createUser, you apply the set and add them to the user before saving it, by adding the Set<String> authorities to its parameters and
if (authorities != null) {
Set<Authority> authorities = new HashSet<>();
authorities.forEach(
authority -> authorities.add(authorityRepository.findOne(authority))
);
user.setAuthorities(authorities);
}
and this should be sufficient to pass authorities to /api/register/ and save them. You should be aware of users forbid to register themselves with ADMIN roles, but the security consideration is up to you and not part my answer.
apply to frontend
Knowing your API now can process also authorities, you could just pass them.
You just add some checkbox or selectbox with ng-model="vm.registerAccount.authorities" to src/main/webapp/app/account/register/register.html (if angularJS1) or
[(ngModel)]="registerAccount.authorities" tosrc/main/webapp/app/account/register/register.component.html` (if angular2).
AFAIK this should lead automatically to the angular services passing these authorities/roles to the API.
I hope my brief answer helps you to find the proper places! Feel free to ask in comments if you stuck
I am developing an ordering web application and I am new to learning Grails. I used the Spring Security plugin. I haved configured and override the login and register, what I want is to get the currently logged in user to apply an order. Is there a way to do this without using the static belongsTo? Because using this always shows me a dropdown box where I can choose between the users and admins. Am I doing the right approach in getting the logged in user to order?
The simplest way to retrieve the currently authenticated principal is via a static call to the SecurityContextHolder:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
String currentUserName = authentication.getName();
return currentUserName;
}
OR
Inject SpringSecurityService bean,
like this into controller
def springSecurityService
and then call
def currentPrincipal = springSecurityService.principal
print "The details of current logged in user is" + currentPrincipal
For more details follow this link
http://www.baeldung.com/get-user-in-spring-security
How to get the current logged in user object from spring security?
I'm developing an app based on Grails and Vaadin 7. I managed to make them work with SpringSecurity for authentication and authorization, but I had to develop my own Service that calls the Spring Security authentication manager to make it work with Vaadin:
class SecurityService {
static transactional = true
def springSecurityService
def authenticationManager
void signIn(String username, String password) {
try {
def authentication = new UsernamePasswordAuthenticationToken(username, password)
SCH.context.authentication = authenticationManager.authenticate(authentication)
} catch (BadCredentialsException e) {
throw new SecurityException("Invalid username/password")
}
}
}
The problem is that now I need to implement a remember me authentication and I don't know from where to start.
How do I make the authenticationManager know that I want it to use remeberMeAuthentication? I can get a boolean value from a checkbox on the login View, but what do I do with it next?
Since your question is specific to the handling of checkbox value (remember me flag) coming from login page, the answer is that you have to call loginSuccess or loginFail method of RememberMeServices. The loginSuccess adds auto-login cookie in the response and loginFail removes that cookie.
But I guess above answer won't help you much unless you are sure that you have RememberMeServices configured in your app. Maybe following steps that configure RememberMeServices will help you do whole thing your way (or help you understand the out of the box functionality):
(1) Create a class (call it myRememberMeServices) that implements RememberMeServices and LogoutHandler.
(2) In autoLogin method, create an authentication object (UsernamePasswordAuthenticationToken) after parsing the cookie value.
(3) In loginFail method, cancel the cookie.
(4) In loginSuccess method, create an auto-login cookie. Add value that you would use in autoLogin method. Usually cookie value is encrypted.
(5) In logout method , cancel the cookie.
(6) Inject myRememberMeServices in following four places and call appropriate method:
(a) At the time of successful login (if checkbox value is set),
(b) At the time of failed login,
(c) On logout, and
(d) In filter that does autologin
It is worth noting that RememberMeAuthenticationFilter takes authenticationManager and RememberMeServices in its constructor.
Answer to your other question is that the authenticationManager doesn't need to know anything about remember me. It is the filter (or any class handling auto login) that needs to know about authenticationManager and RememberMeServices. (In other words, ask RememberMeServices for a token and pass it to authenticationManager to do auto login).
Spring Security's architecture is based on servlet filters. The sign-in mechanism you have implemented above is normally done by the UsernamePasswordAuthenticationFilter. Another filter called RememberMeAuthenticationFilter takes the responsibility for the remember-me functionality. The authenticationManager is not aware at all whether the remember-me feature is used by the application or not.
If you want to integrate Spring Security with another web-framework, first try to find out how the filters of the two frameworks can play together.
I've got two grails applications using spring security:
Core
Module (user and role tables mapping to Core db tables)
I want to have a single sign on functionality using "remember me". The problem is that the cookies are stored in different paths "/Core" and "/Module" which I'm guessing is the reason why it isn't working.
Does anyone know how to change the cookie path to be "/"?
Notes:
Do I need to make a change in Spring Security or the Tomcat server configuration (using intellij)
I want to avoid setting up a CAS server if possible
I'm looking into plugins as an alternative
Thanks any help would be greatly appreciated
When the remember-me filter creates the remember-me cookie, it sets the cookie path to the context path obtained from the request object (see related source code here). If you want to customize this behavior, you'll need to override the setCookie() and cancelCookie() methods of the remember-me service implementation your application uses (either TokenBasedRememberMeServices or PersistentTokenBasedRememberMeServices) in a subclass, and configure the RememberMeAuthenticationFilter to use your custom implementation.
Here's how I impltemented it.
create a new service with extends TokenBasedRememberMeServices
override setCookie and cancelCookie method to set cookie path.
Add cookiePath variable and add method to setCookepath()
Update resources.groovy
rememberMeServices(YourTokenBasedRememberMeServices) {
userDetailsService = ref("userDetailsService")
key = conf.rememberMe.key
cookieName = conf.rememberMe.cookieName
alwaysRemember = conf.rememberMe.alwaysRemember
tokenValiditySeconds = conf.rememberMe.tokenValiditySeconds
cookiePath = some config variable
}
I am simply trying to allow a user access to a method if they are authenticated, but nothing I am doing seems to work. Is there a way to just check if the user has been authenticated? The following still denies the user even when authenticated... Is there a built in role for an authenticated user?
#RequestMapping("/secure")
#PreAuthorize("hasRole('IS_AUTHENTICATED_FULLY')")
public String secure(ModelMap map){
return("secure");
}
IS_AUTHENTICATED_FULLY is not a role - it is a pre-defined credential (aka 'magic' string) recognized by the AuthenticatedVoter to indicate that you have logged in. This voter also supports anonymous and remember-me login.
Roles are processed by the RoleVoter which recognizes any sting starting with "ROLE_" (prefix is configurable). Thus hasRole('IS_AUTHENTICATED_FULLY') doesn't work because it's not a role. #RolesAllowed("IS_AUTHENTICATED_FULLY") wouldn't work for the same reason.
When using Spring expression language, the correct expression is:
#PreAuthorize("isAuthenticated()")
Alternatively, you can use:
#Secured("IS_AUTHENTICATED_FULLY")
No custom classes are required - both voters are enabled by default.
hasRole('ROLE_USER') is the traditional name for any user who is authenticated. You would typically use ROLE_ANONYMOUS for parts where you don't care if the person is authenticated or not.
(Added later:)
I think you will need to implement a custom AccessDecisionVoter that will always vote ACCESS_GRANTED whenever the parameter authentication has isAuthenticated() true, and the CONFIG_ATTRIBUTE is ROLE_USER or similar.
There is further discussion of this in this forum discussion, giving details of a web.xml and other config.
In your custom UserDetailService implementation just add the Role "IS_AUTHENTICATED_FULLY" to the User object before it's returned.
This is what I have ended up using:
#PreAuthorize("isAuthenticated()")
this should work:
#PreAuthorize("isFullyAuthenticated()")