Statistics
| Branch: | Tag: | Revision:

root / gss / src / gr / ebs / gss / server / Login.java @ 11af52e2

History | View | Annotate | Download (11 kB)

1
/*
2
 * Copyright 2008, 2009 Electronic Business Systems Ltd.
3
 *
4
 * This file is part of GSS.
5
 *
6
 * GSS is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * GSS is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
package gr.ebs.gss.server;
20

    
21
import static gr.ebs.gss.server.configuration.GSSConfigurationFactory.getConfiguration;
22
import gr.ebs.gss.client.exceptions.DuplicateNameException;
23
import gr.ebs.gss.client.exceptions.ObjectNotFoundException;
24
import gr.ebs.gss.client.exceptions.RpcException;
25
import gr.ebs.gss.server.domain.Nonce;
26
import gr.ebs.gss.server.domain.User;
27
import gr.ebs.gss.server.ejb.ExternalAPI;
28

    
29
import java.io.IOException;
30
import java.io.PrintWriter;
31
import java.net.URL;
32
import java.net.URLEncoder;
33

    
34
import javax.naming.Context;
35
import javax.naming.InitialContext;
36
import javax.naming.NamingException;
37
import javax.rmi.PortableRemoteObject;
38
import javax.servlet.http.Cookie;
39
import javax.servlet.http.HttpServlet;
40
import javax.servlet.http.HttpServletRequest;
41
import javax.servlet.http.HttpServletResponse;
42

    
43
import org.apache.commons.codec.binary.Base64;
44
import org.apache.commons.logging.Log;
45
import org.apache.commons.logging.LogFactory;
46

    
47
/**
48
 * The servlet that handles user logins.
49
 *
50
 * @author past
51
 */
52
public class Login extends HttpServlet {
53
        /**
54
         * The request parameter name for the nonce.
55
         */
56
        private static final String NONCE_PARAM = "nonce";
57

    
58
        /**
59
         * The request parameter name for the URL to redirect
60
         * to after authentication.
61
         */
62
        private static final String NEXT_URL_PARAM = "next";
63

    
64
        /**
65
         * The serial version UID of the class.
66
         */
67
        private static final long serialVersionUID = 1L;
68

    
69
        /**
70
         * The name of the authentication cookie.
71
         */
72
        private static final String AUTH_COOKIE = "_gss_a";
73

    
74
        /**
75
         * The separator character for the authentication cookie.
76
         */
77
        private static final char COOKIE_SEPARATOR = '|';
78

    
79
        /**
80
         * The logger.
81
         */
82
        private static Log logger = LogFactory.getLog(Login.class);
83

    
84
        /**
85
         * A helper method that retrieves a reference to the ExternalAPI bean and
86
         * stores it for future use.
87
         *
88
         * @return an ExternalAPI instance
89
         * @throws RpcException in case an error occurs
90
         */
91
        private ExternalAPI getService() throws RpcException {
92
                try {
93
                        final Context ctx = new InitialContext();
94
                        final Object ref = ctx.lookup(getConfiguration().getString("externalApiPath"));
95
                        return (ExternalAPI) PortableRemoteObject.narrow(ref, ExternalAPI.class);
96
                } catch (final NamingException e) {
97
                        logger.error("Unable to retrieve the ExternalAPI EJB", e);
98
                        throw new RpcException("An error occurred while contacting the naming service");
99
                }
100
        }
101

    
102
        /**
103
         * Return the name of the service.
104
         */
105
        private String getServiceName() {
106
                return getConfiguration().getString("serviceName", "GSS");
107
        }
108

    
109
        @Override
110
        public void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
111
                // Fetch the next URL to display, if any.
112
                String nextUrl = request.getParameter(NEXT_URL_PARAM);
113
                // Fetch the supplied nonce, if any.
114
                String nonce = request.getParameter(NONCE_PARAM);
115
                String[] attrs = new String[] {"REMOTE_USER", "HTTP_SHIB_INETORGPERSON_DISPLAYNAME",
116
                                        "HTTP_SHIB_INETORGPERSON_GIVENNAME", "HTTP_SHIB_PERSON_COMMONNAME",
117
                                        "HTTP_SHIB_PERSON_SURNAME", "HTTP_SHIB_INETORGPERSON_MAIL",
118
                                        "HTTP_SHIB_EP_UNSCOPEDAFFILIATION"};
119
                StringBuilder buf = new StringBuilder("Shibboleth Attributes\n");
120
                for (String attr: attrs)
121
                        buf.append(attr+": ").append(request.getAttribute(attr)).append('\n');
122
                logger.info(buf);
123
                User user = null;
124
                response.setContentType("text/html");
125
                Object usernameAttr = request.getAttribute("REMOTE_USER");
126
                Object nameAttr = request.getAttribute("HTTP_SHIB_INETORGPERSON_DISPLAYNAME");
127
                Object givennameAttr = request.getAttribute("HTTP_SHIB_INETORGPERSON_GIVENNAME"); // Multi-valued
128
                Object cnAttr = request.getAttribute("HTTP_SHIB_PERSON_COMMONNAME"); // Multi-valued
129
                Object snAttr = request.getAttribute("HTTP_SHIB_PERSON_SURNAME"); // Multi-valued
130
                Object mailAttr = request.getAttribute("HTTP_SHIB_INETORGPERSON_MAIL"); // Multi-valued
131
                Object userclassAttr = request.getAttribute("HTTP_SHIB_EP_UNSCOPEDAFFILIATION"); // Multi-valued
132
                if (usernameAttr == null) {
133
                        String authErrorUrl = "authenticationError.jsp";
134
                        authErrorUrl += "?name=" + (nameAttr==null? "-": nameAttr.toString());
135
                        authErrorUrl += "&givenname=" + (givennameAttr==null? "-": givennameAttr.toString());
136
                        authErrorUrl += "&sn=" + (snAttr==null? "-": snAttr.toString());
137
                        authErrorUrl += "&cn=" + (cnAttr==null? "-": cnAttr.toString());
138
                        authErrorUrl += "&mail=" + (mailAttr==null? "-": mailAttr.toString());
139
                        authErrorUrl += "&userclass=" + (userclassAttr==null? "-": userclassAttr.toString());
140
                        response.sendRedirect(authErrorUrl);
141
                        return;
142
                }
143
                String username = usernameAttr.toString();
144
                String name;
145
                if (nameAttr != null && !nameAttr.toString().isEmpty())
146
                        name = nameAttr.toString();
147
                else if (cnAttr != null && !cnAttr.toString().isEmpty()) {
148
                        name = cnAttr.toString();
149
                        if (name.indexOf(';') != -1)
150
                                name = name.substring(0, name.indexOf(';'));
151
                } else if (givennameAttr != null && snAttr != null && !givennameAttr.toString().isEmpty() && !snAttr.toString().isEmpty()) {
152
                        String givenname = givennameAttr.toString();
153
                        if (givenname.indexOf(';') != -1)
154
                                givenname = givenname.substring(0, givenname.indexOf(';'));
155
                        String sn = snAttr.toString();
156
                        if (sn.indexOf(';') != -1)
157
                                sn = sn.substring(0, sn.indexOf(';'));
158
                        name = givenname + ' ' + sn;
159
                } else if (givennameAttr == null && snAttr != null && !snAttr.toString().isEmpty()) {
160
                        name = snAttr.toString();
161
                        if (name.indexOf(';') != -1)
162
                                name = name.substring(0, name.indexOf(';'));
163
                } else
164
                        name = username;
165
                String mail = mailAttr != null ? mailAttr.toString() : username;
166
                if (mail.indexOf(';') != -1)
167
                        mail = mail.substring(0, mail.indexOf(';'));
168
                // XXX we are not using the user class currently
169
                String userclass = userclassAttr != null ? userclassAttr.toString() : "";
170
                if (userclass.indexOf(';') != -1)
171
                        userclass = userclass.substring(0, userclass.indexOf(';'));
172
                try {
173
                        user = getService().findUser(username);
174
                        if (user == null)
175
                                user = getService().createUser(username, name, mail);
176
                        if (!user.hasAcceptedPolicy()) {
177
                                String policyUrl = "policy.jsp";
178
                                if (request.getQueryString() != null)
179
                                        policyUrl += "?user=" + username + "&" + request.getQueryString();
180
                                response.sendRedirect(policyUrl);
181
                                return;
182
                        }
183
                        // Update the user name and e-mail if modified.
184
                        if (!user.getName().equals(name) || !user.getEmail().equals(mail))
185
                                user = getService().updateUser(username, name, mail);
186
                        if (user.getAuthToken() == null)
187
                                user = getService().updateUserToken(user.getId());
188
                } catch (RpcException e) {
189
                        String error = "An error occurred while communicating with the service";
190
                        logger.error(error, e);
191
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
192
                        return;
193
                } catch (DuplicateNameException e) {
194
                        String error = "User with username " + username + " already exists";
195
                        logger.error(error, e);
196
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
197
                        return;
198
                } catch (ObjectNotFoundException e) {
199
                        String error = "No username was provided";
200
                        logger.error(error, e);
201
                        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
202
                        return;
203
                }
204
                String tokenEncoded = new String(Base64.encodeBase64(user.getAuthToken()), "US-ASCII");
205
                String userEncoded = URLEncoder.encode(user.getUsername(), "US-ASCII");
206
                if (logger.isDebugEnabled())
207
                        logger.debug("user: "+userEncoded+" token: "+tokenEncoded);
208
                if (nextUrl != null) {
209
                        URL next = new URL(nextUrl);
210
                        String domain = next.getHost();
211
                        String path = next.getPath();
212
                        Cookie cookie = new Cookie(AUTH_COOKIE, userEncoded + COOKIE_SEPARATOR +
213
                                                tokenEncoded);
214
                        cookie.setMaxAge(-1);
215
                        cookie.setDomain(domain);
216
                        cookie.setPath(path);
217
                    response.addCookie(cookie);
218
                    response.sendRedirect(nextUrl);
219
                } else if (nonce != null) {
220
                        nonce = URLEncoder.encode(nonce, "US-ASCII");
221
                        Nonce n = null;
222
                        try {
223
                                if (logger.isDebugEnabled())
224
                                        logger.debug("user: "+user.getId()+" nonce: "+nonce);
225
                                n = getService().getNonce(nonce, user.getId());
226
                        } catch (ObjectNotFoundException e) {
227
                            PrintWriter out = response.getWriter();
228
                            out.println("<HTML>");
229
                            out.println("<HEAD><TITLE>" + getServiceName() + " Authentication</TITLE>" +
230
                                            "<LINK TYPE='text/css' REL='stylesheet' HREF='gss.css'></HEAD>");
231
                            out.println("<BODY><CENTER><P>");
232
                            out.println("The supplied nonce could not be found!");
233
                            out.println("</CENTER></BODY></HTML>");
234
                            return;
235
                        } catch (RpcException e) {
236
                                String error = "An error occurred while communicating with the service";
237
                                logger.error(error, e);
238
                                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
239
                                return;
240
                        }
241
                        try {
242
                                getService().activateUserNonce(user.getId(), nonce, n.getNonceExpiryDate());
243
                        } catch (ObjectNotFoundException e) {
244
                                String error = "Unable to find user";
245
                                logger.error(error, e);
246
                                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
247
                                return;
248
                        } catch (RpcException e) {
249
                                String error = "An error occurred while communicating with the service";
250
                                logger.error(error, e);
251
                                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, error);
252
                                return;
253
                        }
254
                        try {
255
                                getService().removeNonce(n.getId());
256
                        } catch (ObjectNotFoundException e) {
257
                                logger.info("Nonce already removed!", e);
258
                        } catch (RpcException e) {
259
                                logger.warn("Could not remove nonce from data store", e);
260
                        }
261
                    PrintWriter out = response.getWriter();
262
                    out.println("<HTML>");
263
                    out.println("<HEAD><TITLE>" + getServiceName() + " Authentication</TITLE>" +
264
                                    "<LINK TYPE='text/css' REL='stylesheet' HREF='gss.css'></HEAD>");
265
                    out.println("<BODY><CENTER><P>");
266
                    out.println("You can now close this browser window and return to your application.");
267
                    out.println("</CENTER></BODY></HTML>");
268
                } else {
269
                    PrintWriter out = response.getWriter();
270
                    out.println("<HTML>");
271
                    out.println("<HEAD><TITLE>" + getServiceName() + " Authentication</TITLE>" +
272
                                    "<LINK TYPE='text/css' REL='stylesheet' HREF='gss.css'></HEAD>");
273
                    out.println("<BODY><CENTER><P>");
274
                    out.println("Name: " + user.getName() + "<BR>");
275
                    out.println("E-mail: " + user.getEmail() + "<BR><P>");
276
                    out.println("Username: " + user.getUsername() + "<BR>");
277
                    out.println("Athentication token: " + tokenEncoded + "<BR>");
278
                    out.println("</CENTER></BODY></HTML>");
279
                }
280
        }
281
}