Trouble logging out from a Grails application using Spring Security (CAS) - grails

I have a Grails application with Spring Security implemented (CAS). However, after I hit the logout button, I am not logged out. I have the LogoutController, with following code:
class LogoutController {
def index = {
println "IN LOGOUT CONTROLLER TRYING TO LOGOUT"
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
def accessDenied = {
}
}
And in my Config.groovy file, I have:
grails.plugins.springsecurity.logout.afterLogoutUrl = 'https://login.test.com/cas/logout'
The code for my GSP page is
<g:link controller='Logout'>Logout</g:link>
However, when I click the logout button I get redirected, but not fully logged out. Any ideas on what I am doing wrong?

Have you tried call session.invalidate() direct in the controller index method?
class LogoutController {
def index = {
println "IN LOGOUT CONTROLLER TRYING TO LOGOUT"
session.invalidate()
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl
}
}
Cheers

<g:link controller='Logout'>Logout</g:link>
def index = {
logoutProcessService.process(params)
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUr
}

Related

Grails security implementation

I made the following Controller.
I can login and logout, but how can I force the the user to log in first?
I need to start a session on login and terminate it on logout.
class UserController {
def scaffold = User
def login = {}
def authenticate = {
def user = User.findByLoginAndPassword(params.login, params.password)
if(user){
session.user = user
flash.message = "Hello ${user.name}!"
redirect(controller:"entry", action:"list")
} else {
flash.message = "Sorry, ${params.login}. Please try again."
redirect(action:"login")
}
}
def logout = {
flash.message = "Goodbye ${session.user.name}"
session.user = null
redirect(controller:"entry", action:"list")
}
}
Choice 1:
There are number of security plugins available for securing your Grail's app.
The most popular one is the "Spring Security Core Plugin" which will force user to login before accessing your secured resource.
Reference Link : http://grails.org/plugin/spring-security-core
Choice 2 :
But if you don't want to use any external plugin for you application(I would suggest to use one) you can take advantage of "Filters" in Grail's
You can create a filter for checking the session before user hits any action of your controller and if session is already expired/not created then you can redirect them to login page.
Example :
class SecurityFilterFilters {
def filters = {
loginCheck(controller: 'Your_controller_name(if many separate them with pipe(|) )', action: "*") {
before = {
//check if user is logged in(if yes then there will be session.user) and action is not login action
if (!session.user && !actionName.equals('login')) {
//user is not logged in so redirect him to login page
redirect(controller: 'user', action: 'login')
return false
}
}
}
}
}
Reference Link : http://docs.grails.org/2.2.1/ref/Plug-ins/filters.html
See the 'Secured annotation' spring-security-core plugin documentation for Grails
https://grails-plugins.github.io/grails-spring-security-core/v3/

shiro annotation is not working in grails. Can anybody suggest me what is wrong?

When I used #RequiresPermissions I got cannot resolve symbol 'RequiresPermissions' error. I already have imported org.apache.shiro.authz.annotation.RequiresPermissions.
Annotations are used as #RequiresPermissions("module:books:list")
My authorization class
class AuthController {
def shiroSecurityManager
def index = { redirect(action: "login", params: params) }
def login = {
return [ username: params.username, rememberMe: (params.rememberMe != null), targetUri: params.targetUri ]
}
def signIn = {
def authToken = new UsernamePasswordToken(params.username, params.password as String)
// Support for "remember me"
if (params.rememberMe) {
authToken.rememberMe = true
}
// If a controller redirected to this page, redirect back
// to it. Otherwise redirect to the root URI.
def targetUri = params.targetUri ?: "/"
// Handle requests saved by Shiro filters.
SavedRequest savedRequest = WebUtils.getSavedRequest(request)
if (savedRequest) {
targetUri = savedRequest.requestURI - request.contextPath
if (savedRequest.queryString) targetUri = targetUri + '?' + savedRequest.queryString
}
try{
// Perform the actual login. An AuthenticationException
// will be thrown if the username is unrecognised or the
// password is incorrect.
SecurityUtils.subject.login(authToken)
log.info "Redirecting to '${targetUri}'."
redirect(uri: targetUri)
}
catch (AuthenticationException ex){
// Authentication failed, so display the appropriate message
// on the login page.
log.info "Authentication failure for user '${params.username}'."
flash.message = message(code: "login.failed")
// Keep the username and "remember me" setting so that the
// user doesn't have to enter them again.
def m = [ username: params.username ]
if (params.rememberMe) {
m["rememberMe"] = true
}
// Remember the target URI too.
if (params.targetUri) {
m["targetUri"] = params.targetUri
}
// Now redirect back to the login page.
redirect(action: "login", params: m)
}
}
def signOut = {
// Log the user out of the application.
SecurityUtils.subject?.logout()
webRequest.getCurrentRequest().session = null
// For now, redirect back to the home page.
redirect(uri: "/")
}
def unauthorized = {
render "You do not have permission to access this page."
}
}
My application runs but when I login by using user that I have set, it directly sends me to unauthorized page. I have allowed some permissions to the user.
If you look at the Javadoc for that annotation (or the source) you'll see that it's allowed to be assigned to types (class-level) and methods (#Target(value={TYPE,METHOD})). You are defining your controller actions as closures, which is still supported in Grails 2.0+ but methods are preferred now. You cannot use that annotation on closures, since they are not methods even though Grails and Groovy let you use them like methods. If the Target annotation included FIELD in addition to the other types it would work, but it doesn't because the Shiro library doesn't have direct support for closures in Grails controllers.
So change all of your actions from closures to methods, e.g.
def index() { redirect(action: "login", params: params) }
def login() {
...
}
....
and then you can annotate them.

handle successful login event with spring security

My Grails app uses the Spring Security plugin. Whenever a user successfully logs in I want to:
store something in the session
redirect them to a custom page (depending on their role)
I need to handle logout events similarly, which was pretty straightforward because the plugin provides a bean named logoutSuccessHandler that can be overriden. I was hoping to similarly find a bean named loginSuccessHandler, but no such luck.
I read the page in the plugin's docs about event handling, but neither of the event handling mechanisms appears to give me access to the current request or session.
If you want to do some stuff upon successful login. You can listen to InteractiveAuthenticationSuccessEvent
class AuthenticationSuccessEventListener implements
ApplicationListener<InteractiveAuthenticationSuccessEvent> {
#Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
.......do some stuff here
}
}
And then register AuthenticationSuccessEventListener as a spring bean in resources.groovy
You can do whatever you want here, however you wont be able to do redirect from listener.
Here's another similar question
Add a config parameter:
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/myLogin/handleSuccessLogin'
Then add your custom login-handling in the action that handles this URL
class MyLoginController {
def springSecurityService
def handleSuccessLogin() {
session.foo = 'bar'
if (springSecurityService.currentUser.username == 'bob') {
redirect action: 'bobLogin'
} else {
redirect action: 'defaultLogin'
}
}
def bobLogin() {
// bob's login handler
}
def defaultLogin() {
// default login handler
}
}
I recently used this in a project for logging in. Its kind of a hack but works for me. I'm using version 1.2.7.3 of the plugin.
def auth() {
def config = SpringSecurityUtils.securityConfig
if (springSecurityService.isLoggedIn()) {
def user = User.get(principal.id)
def roles = user.getAuthorities()
def admin_role = Role.findByAuthority("ROLE_ADMIN")
//this user is not admin
if(!roles.contains(admin_role)){
//perform redirect to appropriate page
}
redirect uri: config.successHandler.defaultTargetUrl
//log.info(getPrincipal().username + "logged in at :"+new Date())
return
}
String view = 'auth'
String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter]
}
For logging out I used a Logout controller, performed some action before redirecting to the logout handler:
class LogoutController {
/**
* Index action. Redirects to the Spring security logout uri.
*/
def index = {
// perform some action here
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl
}
}

springSecurity.denied.message in grails 2.2.2

i am trying to Different home page for user depending upon its Role
grails.plugins.springsecurity.successHandler.defaultTargetUrl = "/home"
grails.plugins.springsecurity.securityConfigType="InterceptUrlMap"
grails.plugins.springsecurity.interceptUrlMap=[
....
....
'/User/**':['ROLE_USER'],
'/home/**':['ROLE_ADMIN','ROLE_USER'],
....
....
]
i set success handler controller "HomeController"
in that i redirect role wise home page
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
class HomeController {
def index() {
if (SpringSecurityUtils.ifAllGranted('ROLE_ADMIN')) {
redirect controller: '...', action: '...'
return
}
if (SpringSecurityUtils.ifAllGranted('ROLE_USER')) {
redirect controller: 'user', action: 'show'
return
}
}
}
In this When i logged in through ADMIN Profile it hits "HomeController" and redirect as well
But When I trying to Log In from User Profile it gives me an error springSecurity.denied.message...
The problem seems to be with your redirect call:
redirect controller: 'UserController'
it should be
redirect controller: 'user'
Because in this cases you follow the url convension: :8080/your-app/user/show
'/user/**':['ROLE_USER'],
instead
'/User/**':['ROLE_USER'],

Grails Acegi : Redirection on a ajax method and not on the webpage. Why?

I use Acegi with grails but I have a problem with a redirection.
I define in UrlMapping this :
"/" {
controller = "mycontroller"
action = "myaction"
}
In mycontroller :
myaction = {
if (authenticateService.isLoggedIn(){ "/mycontext/public" }
else {
// pseudo code
if (role = ROLE_1) {
redirect "/mycontext/myactionforNormalUser"
}
else if (role = ROLE_ADMIN) {
redirect "/mycontext/myactionforROLEADMIN"
}
}
}
IfI go to my app without login, I'm redirected to the public page, so it's right.
But on login on admin, I'm redirected to the auth/deniedAjax (of acegi) and not on my page.
And if I login as a normal user, I'm redirect on a ajax method define in my gsp.
Do you have an idea ?
Thanks a lot.
Upgraded and working fine now with spring security

Resources