[UI] Encrypt passwords in db
[validation.git] / ui / src / main / java / org / akraino / validation / ui / login / LoginStrategyImpl.java
1 /*
2  * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may
5  * not use this file except in compliance with the License. You may obtain
6  * a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13  * implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16
17 package org.akraino.validation.ui.login;
18
19 import java.io.IOException;
20 import java.io.UnsupportedEncodingException;
21 import java.security.InvalidKeyException;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import javax.crypto.BadPaddingException;
29 import javax.crypto.Cipher;
30 import javax.crypto.IllegalBlockSizeException;
31 import javax.crypto.NoSuchPaddingException;
32 import javax.crypto.SecretKey;
33 import javax.crypto.spec.SecretKeySpec;
34 import javax.servlet.http.Cookie;
35 import javax.servlet.http.HttpServletRequest;
36 import javax.servlet.http.HttpServletResponse;
37
38 import org.apache.commons.codec.binary.Hex;
39 import org.onap.portalsdk.core.auth.LoginStrategy;
40 import org.onap.portalsdk.core.command.LoginBean;
41 import org.onap.portalsdk.core.domain.RoleFunction;
42 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
43 import org.onap.portalsdk.core.menu.MenuProperties;
44 import org.onap.portalsdk.core.onboarding.exception.CipherUtilException;
45 import org.onap.portalsdk.core.onboarding.exception.PortalAPIException;
46 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
47 import org.onap.portalsdk.core.service.LoginService;
48 import org.onap.portalsdk.core.service.RoleService;
49 import org.onap.portalsdk.core.util.SystemProperties;
50 import org.onap.portalsdk.core.web.support.UserUtils;
51 import org.springframework.beans.factory.annotation.Autowired;
52 import org.springframework.web.servlet.ModelAndView;
53
54 /**
55  * Implements basic single-signon login strategy for open-source applications
56  * when users start at Portal. Extracts an encrypted user ID sent by Portal.
57  */
58 public class LoginStrategyImpl extends LoginStrategy {
59
60     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(LoginStrategyImpl.class);
61
62     @Autowired
63     private RoleService roleService;
64
65     @Autowired
66     private LoginService loginService;
67
68     /**
69      * login for open source is same as external login in the non-open-source
70      * version.
71      */
72     @Override
73     public ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
74         invalidateExistingSession(request);
75
76         LoginBean commandBean = new LoginBean();
77         String loginId = request.getParameter("loginId");
78         String password = request.getParameter("password");
79         String key = System.getenv("ENCRYPTION_KEY");
80         password = aesEncrypt(password, key);
81         commandBean.setLoginId(loginId);
82         commandBean.setLoginPwd(password);
83         // commandBean.setUserid(loginId);
84         commandBean = loginService.findUser(commandBean,
85                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap());
86         List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(loginId);
87
88         if (commandBean.getUser() == null) {
89             String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
90                     : "login.error.external.invalid";
91             Map<String, String> model = new HashMap<>();
92             model.put("error", loginErrorMessage);
93             return new ModelAndView("login_external", "model", model);
94         } else {
95             // store the currently logged in user's information in the session
96             UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
97                     commandBean.getBusinessDirectMenu(),
98                     SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR), roleFunctionList);
99             initateSessionMgtHandler(request);
100             // user has been authenticated, now take them to the welcome page
101             return new ModelAndView("redirect:welcome.htm");
102         }
103     }
104
105     @Override
106     public ModelAndView doExternalLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
107
108         invalidateExistingSession(request);
109
110         LoginBean commandBean = new LoginBean();
111         String loginId = request.getParameter("loginId");
112         String password = request.getParameter("password");
113         String key = System.getenv("ENCRYPTION_KEY");
114         password = aesEncrypt(password, key);
115         commandBean.setLoginId(loginId);
116         commandBean.setLoginPwd(password);
117         // commandBean.setUserid(loginId);
118         commandBean = loginService.findUser(commandBean,
119                 (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap());
120         List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(loginId);
121
122         if (commandBean.getUser() == null) {
123             String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
124                     : "login.error.external.invalid";
125             Map<String, String> model = new HashMap<>();
126             model.put("error", loginErrorMessage);
127             return new ModelAndView("login_external", "model", model);
128         } else {
129             // store the currently logged in user's information in the session
130             UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
131                     commandBean.getBusinessDirectMenu(),
132                     SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR), roleFunctionList);
133             initateSessionMgtHandler(request);
134             // user has been authenticated, now take them to the welcome page
135             return new ModelAndView("redirect:welcome");
136         }
137     }
138
139     @Override
140     public String getUserId(HttpServletRequest request) throws PortalAPIException {
141         // Check ECOMP Portal cookie
142         Cookie ep = getCookie(request, EP_SERVICE);
143         if (ep == null) {
144             LOGGER.debug(EELFLoggerDelegate.debugLogger, "getUserId: no EP_SERVICE cookie, returning null");
145             return null;
146         }
147
148         String userid = null;
149         try {
150             userid = getUserIdFromCookie(request);
151         } catch (Exception e) {
152             LOGGER.error(EELFLoggerDelegate.errorLogger, "getUserId failed", e);
153         }
154         return userid;
155     }
156
157     /**
158      * Searches the request for the user-ID cookie and decrypts the value using a
159      * key configured in properties
160      *
161      * @param request HttpServletRequest
162      * @return User ID
163      * @throws CipherUtilException On any failure to decrypt
164      */
165     private String getUserIdFromCookie(HttpServletRequest request) throws CipherUtilException {
166         String userId = "";
167         Cookie userIdCookie = getCookie(request, USER_ID);
168         if (userIdCookie != null) {
169             final String cookieValue = userIdCookie.getValue();
170             if (!SystemProperties.containsProperty(SystemProperties.Decryption_Key))
171                 throw new IllegalStateException("Failed to find property " + SystemProperties.Decryption_Key);
172             final String decryptionKey = SystemProperties.getProperty(SystemProperties.Decryption_Key);
173             userId = CipherUtil.decrypt(cookieValue, decryptionKey);
174             LOGGER.debug(EELFLoggerDelegate.debugLogger, "getUserIdFromCookie: decrypted as {}", userId);
175         }
176         return userId;
177     }
178
179     /**
180      * Searches the request for the named cookie.
181      *
182      * @param request    HttpServletRequest
183      * @param cookieName Name of desired cookie
184      * @return Cookie if found; otherwise null.
185      */
186     private Cookie getCookie(HttpServletRequest request, String cookieName) {
187         Cookie[] cookies = request.getCookies();
188         if (cookies != null)
189             for (Cookie cookie : cookies)
190                 if (cookie.getName().equals(cookieName))
191                     return cookie;
192         return null;
193     }
194
195     private String aesEncrypt(String password, String strKey) {
196         try {
197             byte[] keyBytes = Arrays.copyOf(strKey.getBytes("ASCII"), 16);
198             SecretKey key = new SecretKeySpec(keyBytes, "AES");
199             Cipher cipher = Cipher.getInstance("AES");
200             cipher.init(Cipher.ENCRYPT_MODE, key);
201             byte[] cleartext = password.getBytes("UTF-8");
202             byte[] ciphertextBytes = cipher.doFinal(cleartext);
203             return new String(Hex.encodeHex(ciphertextBytes));
204         } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | UnsupportedEncodingException
205                 | IllegalBlockSizeException | BadPaddingException e) {
206             LOGGER.error(EELFLoggerDelegate.errorLogger,
207                     "Error when encrypting password key" + UserUtils.getStackTrace(e));
208             return null;
209         }
210     }
211
212 }