source: trunk/grails-app/controllers/dbnp/authentication/LoginController.groovy

Last change on this file was 2109, checked in by work@…, 11 years ago

fixed shibboleth config issue by first casting to string, then to boolean (thanks to Siemen!)

  • Property svn:keywords set to Rev Author Date
File size: 8.7 KB
Line 
1package dbnp.authentication
2
3import grails.converters.JSON
4
5import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
6
7import org.springframework.security.authentication.AccountExpiredException
8import org.springframework.security.authentication.CredentialsExpiredException
9import org.springframework.security.authentication.DisabledException
10import org.springframework.security.authentication.LockedException
11import org.springframework.security.core.context.SecurityContextHolder as SCH
12import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
13import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
14import org.codehaus.groovy.grails.commons.ConfigurationHolder
15
16import dbnp.authentication.*
17
18class LoginController {
19        /**
20         * Dependency injection for the authenticationTrustResolver.
21         */
22        def authenticationTrustResolver
23
24        /**
25         * Dependency injection for the springSecurityService.
26         */
27        def springSecurityService
28
29        /**
30         * Dependency injection for the GSCF authentication service
31         */
32        def authenticationService
33
34        /**
35         * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
36         */
37        def index = {
38                if (springSecurityService.isLoggedIn()) {
39                        redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
40                }
41                else {
42                        redirect action: auth, params: params
43                }
44        }
45
46        /**
47         * Show the login page.
48         */
49        def auth = {
50                def config = SpringSecurityUtils.securityConfig
51
52                if (springSecurityService.isLoggedIn()) {
53                        if (params.returnURI) {
54                                // see basefilters
55                                redirect uri: params.returnURI
56                        } else {
57                                redirect uri: config.successHandler.defaultTargetUrl
58                        }
59                        return
60                } else if (grailsApplication.config.authentication.shibboleth.toString().toBoolean()) {
61                        // authenticated through shibboleth?
62                        if (request.getHeaderNames().find{ it.toLowerCase() == 'persistent-id'.toLowerCase() }) {
63                                // get shibboleth data
64                                // note: sometimes apache makes the request headers lowercase, sometimes
65                                //               it doesn't. To make sure it always works we use a case insensitive
66                                //               finder to find the request header name
67                                def shibPersistentId    = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'persistent-id'.toLowerCase() })
68                                def shibUid                             = request.getHeader("uid")
69                                def shibEmail                   = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'Shib-InetOrgPerson-mail'.toLowerCase() })
70                                def shibOrganization    = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'schacHomeOrganization'.toLowerCase() })
71                                def shibDisplayName             = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'displayName'.toLowerCase() })
72                                def shibVoName                  = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'coin-vo-name'.toLowerCase() })
73                                def shibUserStatus              = request.getHeader(request.getHeaderNames().find{ it.toLowerCase() == 'coin-user-status'.toLowerCase() })
74
75                                // does a user exist with this username?
76                                def user                                = SecUser.findByUsername(shibPersistentId)
77                                if (!user) {
78                                        // no, create a new user
79                                        user = new SecUser()
80                                        user.username           = shibPersistentId
81                                        user.password           = springSecurityService.encodePassword("myDummyPassword", shibPersistentId)
82                                        user.email                      = shibEmail
83                                        user.displayName        = shibDisplayName
84                                        user.organization       = shibOrganization
85                                        user.voName                     = shibVoName
86                                        user.uid                        = shibUid
87                                        user.userStatus         = shibUserStatus
88                                        user.shibbolethUser     = true
89                                        user.enabled            = true
90                                        user.userConfirmed      = true
91                                        user.adminConfirmed     = true
92                                        user.accountExpired     = false
93                                        user.accountLocked      = false
94                                        user.save(failOnError:true, flush: true)
95                                }
96
97                                // login user
98                                springSecurityService.reauthenticate(user.username, user.password)
99                                // redirect user
100                                if (params.returnURI) {
101                                        // see basefilters
102                                        redirect uri: params.returnURI
103                                } else {
104                                        redirect uri: config.successHandler.defaultTargetUrl
105                                }
106                        }
107                }
108
109                String view = 'auth'
110                String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
111                render view: view, model: [postUrl: postUrl, rememberMeParameter: config.rememberMe.parameter]
112        }
113
114        /**
115         * Shows the login page for users from a module
116         */
117        def auth_remote = {
118                def consumer = params.consumer
119                def token = params.token
120               
121                // Silent means that the user will be sent back, regardless of his login state. He will not
122                // be redirected to the login page.
123                def silent = params.silent ? Boolean.valueOf( params.silent ) : false;
124               
125                if (consumer == null || token == null) {
126                        throw new Exception("Consumer and Token must be given!");
127                }
128
129                log.info( "Remote authentication with " + consumer + " and " + token )
130               
131                def returnUrl;
132               
133                // If no returnUrl is given, find the previous one from the session
134                if( params.returnUrl ) {
135                        returnUrl = params.returnUrl;
136                        session.authRemoteUrl = returnUrl;
137                } else if( session.authRemoteUrl ) {
138                        returnUrl = session.authRemoteUrl;
139                }
140
141                // If the user is already authenticated with this session_id, redirect
142                // him
143                if (authenticationService.isRemotelyLoggedIn(consumer, token)) {
144                        if (returnUrl) {
145                                redirect url: returnUrl
146                        } else {
147                                redirect controller: 'home'
148                        }
149                        return;
150                }
151
152                // If the user is already logged in locally, we log him in and
153                // immediately redirect him
154                if (authenticationService.isLoggedIn()) {
155                        authenticationService.logInRemotely(consumer, token, authenticationService.getLoggedInUser())
156
157                        if (returnUrl) {
158                                redirect url: returnUrl
159                        } else {
160                                redirect controller: 'home'
161                        }
162                        return;
163                }
164               
165                // On silent login, the user should be sent back anyway
166                if( silent ) {
167                        if (returnUrl) {
168                                redirect url: returnUrl
169                        } else {
170                                redirect controller: 'home'
171                        }
172                }
173               
174                // Otherwise we show the login screen
175                def config = SpringSecurityUtils.securityConfig
176                String view = 'auth'
177                String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
178               
179                String redirectUrl = g.createLink(controller: 'login', action: 'auth_remote', params: [consumer: params.consumer, token: params.token], absolute: true)
180                render view: view, model: [postUrl: postUrl,
181                        rememberMeParameter: config.rememberMe.parameter, redirectUrl: redirectUrl]
182        }
183
184        /**
185         * Show denied page.
186         */
187        def denied = {
188                if (springSecurityService.isLoggedIn() &&
189                        authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
190                        // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
191                        redirect action: full, params: params
192                }
193        }
194
195        /**
196         * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
197         */
198        def full = {
199                def config = SpringSecurityUtils.securityConfig
200                render view: 'auth', params: params,
201                        model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
202                                postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
203        }
204
205        /**
206         * Callback after a failed login. Redirects to the auth page with a warning message.
207         */
208        def authfail = {
209                def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]
210                String msg = ''
211                def exception = session[AbstractAuthenticationProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY]
212                if (exception) {
213                        if (exception instanceof AccountExpiredException) {
214                                msg = SpringSecurityUtils.securityConfig.errors.login.expired
215                        }
216                        else if (exception instanceof CredentialsExpiredException) {
217                                msg = SpringSecurityUtils.securityConfig.errors.login.passwordExpired
218                        }
219                        else if (exception instanceof DisabledException) {
220                                msg = SpringSecurityUtils.securityConfig.errors.login.disabled
221                        }
222                        else if (exception instanceof LockedException) {
223                                msg = SpringSecurityUtils.securityConfig.errors.login.locked
224                        }
225                        else {
226                                msg = SpringSecurityUtils.securityConfig.errors.login.fail
227                        }
228                }
229
230                if (springSecurityService.isAjax(request)) {
231                        // set output header to json
232                        response.contentType = 'application/json'
233
234                        render([error: msg] as JSON)
235                }
236                else {
237                        flash.message = msg
238                        redirect action: auth, params: params
239                }
240        }
241
242        /**
243         * The Ajax success redirect url.
244         */
245        def ajaxSuccess = {
246                // set output header to json
247                response.contentType = 'application/json'
248
249                render([success: true, username: springSecurityService.authentication.name] as JSON)
250        }
251
252        /**
253         * The Ajax denied redirect url.
254         */
255        def ajaxDenied = {
256                // set output header to json
257                response.contentType = 'application/json'
258
259                render([error: 'access denied'] as JSON)
260        }
261}
Note: See TracBrowser for help on using the repository browser.