package org.fluxtream.core.auth; import org.fluxtream.core.domain.Guest; import org.fluxtream.core.domain.oauth2.AuthorizationToken; import org.fluxtream.core.services.GuestService; import org.fluxtream.core.services.OAuth2MgmtService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; /** * User: candide * Date: 18/04/14 * Time: 18:18 */ public class FlxOAuth2ProcessingFilter implements Filter { @Autowired OAuth2MgmtService oAuth2MgmtService; @Autowired GuestService guestService; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) req; final HttpServletResponse response = (HttpServletResponse) res; try { String tokenValue = parseToken(request); if (tokenValue!=null&&!tokenValue.equals("undefined")) { AuthorizationToken authToken = oAuth2MgmtService.getTokenFromAccessToken(tokenValue); if (authToken!=null&&authToken.getExpirationIn()>0) { final Guest guest = guestService.getGuestById(authToken.guestId); final FlxUserDetails userDetails = new FlxUserDetails(guest); PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(userDetails, authToken, getAuthorities(guest)); authentication.setDetails(userDetails); authentication.setAuthenticated(true); SecurityContextHolder.getContext().setAuthentication(authentication); } else throw new Exception("No AuthorizationToken found or token expired"); } } catch (Exception failed) { SecurityContextHolder.clearContext(); // cf: http://tools.ietf.org/html/rfc6749 5.2 response.sendError(401, "oAuth2: Sorry, we couldn't authenticate your request: " + failed.getMessage()); return; } chain.doFilter(request, response); } private Collection<? extends GrantedAuthority> getAuthorities(final Guest one) { final List<String> userRoles = one.getUserRoles(); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); for (String userRole : userRoles) authorities.add(new SimpleGrantedAuthority(userRole)); return authorities; } protected String parseToken(HttpServletRequest request) { // first check the header... String token = parseHeaderToken(request); // bearer type allows a request parameter as well if (token == null) { token = request.getParameter("access_token"); } return token; } /** * Parse the OAuth header parameters. The parameters will be oauth-decoded. * * @param request The request. * @return The parsed parameters, or null if no OAuth authorization header was supplied. */ protected String parseHeaderToken(HttpServletRequest request) { @SuppressWarnings("unchecked") Enumeration<String> headers = request.getHeaders("Authorization"); while (headers.hasMoreElements()) { // typically there is only one (most servers enforce that) String value = headers.nextElement(); if ((value.toLowerCase().startsWith("Bearer".toLowerCase()))) { String authHeaderValue = value.substring("Bearer".length()).trim(); int commaIndex = authHeaderValue.indexOf(','); if (commaIndex > 0) { authHeaderValue = authHeaderValue.substring(0, commaIndex); } return authHeaderValue; } else { // todo: support additional authorization schemes for different token types, e.g. "MAC" specified by // http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token } } return null; } }