/** * */ package org.ihtsdo.otf.refset.security; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.token.Token; import org.springframework.security.core.token.TokenService; import org.springframework.security.web.context.HttpRequestResponseHolder; import org.springframework.security.web.context.SecurityContextRepository; import org.springframework.util.StringUtils; /** * @author Episteme Partners * */ public class RefsetSecurityContextRepository implements SecurityContextRepository { private static final Logger LOGGER = LoggerFactory.getLogger(RefsetSecurityContextRepository.class); private static final String X_REFSET_TOKEN = "X-REFSET-AUTH-TOKEN"; private String preAuthTokenKey; private String userKey; private TokenService service; private AuthenticationManager mgr; private RefsetIdentityService iService; /** * @param iService the iService to set */ public void setiService(RefsetIdentityService iService) { this.iService = iService; } public RefsetSecurityContextRepository(AuthenticationManager mgr, TokenService service) { this.mgr = mgr; this.service = service; } /* (non-Javadoc) * @see org.springframework.security.web.context.SecurityContextRepository#loadContext(org.springframework.security.web.context.HttpRequestResponseHolder) */ @Override public SecurityContext loadContext( HttpRequestResponseHolder rh) { HttpServletRequest request = rh.getRequest(); HttpServletResponse response = rh.getResponse(); SecurityContext ctx = getContextFromHeaders(request); if (ctx == null) { ctx = SecurityContextHolder.createEmptyContext(); rh.setResponse(new TokenResponseWrapper(response, true, service)); } return ctx; } /* (non-Javadoc) * @see org.springframework.security.web.context.SecurityContextRepository#saveContext(org.springframework.security.core.context.SecurityContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) { new TokenResponseWrapper(response, true, service).saveContext(context); } /* (non-Javadoc) * @see org.springframework.security.web.context.SecurityContextRepository#containsContext(javax.servlet.http.HttpServletRequest) */ @Override public boolean containsContext(HttpServletRequest request) { return getContextFromHeaders(request) != null; } private SecurityContext getContextFromHeaders(HttpServletRequest req) { final SecurityContext ctx; String tokenKey = req.getHeader(X_REFSET_TOKEN); if (!StringUtils.isEmpty(tokenKey)) { LOGGER.debug("Using token {}", tokenKey); final Token token; try { token = service.verifyToken(tokenKey); if (token != null) { ctx = SecurityContextHolder.createEmptyContext(); Authentication auth = iService.getPrincipal(token); ctx.setAuthentication(auth); } else { //do the authentication again; Authentication auth = mgr.authenticate(new UsernamePasswordAuthenticationToken(getUser(req), getPassword(req))); ctx = SecurityContextHolder.createEmptyContext(); ctx.setAuthentication(auth); } } catch (Exception e) { LOGGER.error("Error during authentication {}", e);//this may be the case when token key verification fails throw new AccessDeniedException("User unauthorized try refreshing supplied user details and try again"); } } else { LOGGER.debug("Performing login as no existing auth token {}"); //do the authentication again; Authentication auth = mgr.authenticate(new UsernamePasswordAuthenticationToken(getUser(req), getPassword(req))); ctx = SecurityContextHolder.createEmptyContext(); ctx.setAuthentication(auth); } return ctx; } private String getPassword(HttpServletRequest req) { return req.getHeader(preAuthTokenKey); } private User getUser(HttpServletRequest req) { String preAuthToken = req.getHeader(preAuthTokenKey); String userName = req.getHeader(userKey); final User user = new User(); user.setPassword(preAuthToken); user.setUsername(userName); return user; } /** * @param userKey the userKey to set */ public void setUserKey(String userKey) { this.userKey = userKey; } /** * @param preAuthTokenKey the preAuthTokenKey to set */ public void setPreAuthTokenKey(String preAuthTokenKey) { this.preAuthTokenKey = preAuthTokenKey; } }