1
2
3
4
5
6
7
8
9
10
11
12
13 package org.springframework.security.oauth2.provider.authentication;
14
15 import java.io.IOException;
16
17 import javax.servlet.Filter;
18 import javax.servlet.FilterChain;
19 import javax.servlet.FilterConfig;
20 import javax.servlet.ServletException;
21 import javax.servlet.ServletRequest;
22 import javax.servlet.ServletResponse;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.springframework.beans.factory.InitializingBean;
29 import org.springframework.security.authentication.AbstractAuthenticationToken;
30 import org.springframework.security.authentication.AnonymousAuthenticationToken;
31 import org.springframework.security.authentication.AuthenticationDetailsSource;
32 import org.springframework.security.authentication.AuthenticationEventPublisher;
33 import org.springframework.security.authentication.AuthenticationManager;
34 import org.springframework.security.authentication.BadCredentialsException;
35 import org.springframework.security.authentication.InsufficientAuthenticationException;
36 import org.springframework.security.core.Authentication;
37 import org.springframework.security.core.AuthenticationException;
38 import org.springframework.security.core.context.SecurityContextHolder;
39 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
40 import org.springframework.security.oauth2.provider.OAuth2Authentication;
41 import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
42 import org.springframework.security.web.AuthenticationEntryPoint;
43 import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
44 import org.springframework.util.Assert;
45
46
47
48
49
50
51
52
53
54 public class OAuth2AuthenticationProcessingFilter implements Filter, InitializingBean {
55
56 private final static Log logger = LogFactory.getLog(OAuth2AuthenticationProcessingFilter.class);
57
58 private AuthenticationEntryPoint authenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
59
60 private AuthenticationManager authenticationManager;
61
62 private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();
63
64 private TokenExtractor tokenExtractor = new BearerTokenExtractor();
65
66 private AuthenticationEventPublisher eventPublisher = new NullEventPublisher();
67
68 private boolean stateless = true;
69
70
71
72
73
74
75
76
77 public void setStateless(boolean stateless) {
78 this.stateless = stateless;
79 }
80
81
82
83
84 public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
85 this.authenticationEntryPoint = authenticationEntryPoint;
86 }
87
88
89
90
91 public void setAuthenticationManager(AuthenticationManager authenticationManager) {
92 this.authenticationManager = authenticationManager;
93 }
94
95
96
97
98 public void setTokenExtractor(TokenExtractor tokenExtractor) {
99 this.tokenExtractor = tokenExtractor;
100 }
101
102
103
104
105 public void setAuthenticationEventPublisher(AuthenticationEventPublisher eventPublisher) {
106 this.eventPublisher = eventPublisher;
107 }
108
109
110
111
112 public void setAuthenticationDetailsSource(
113 AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource) {
114 Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");
115 this.authenticationDetailsSource = authenticationDetailsSource;
116 }
117
118 public void afterPropertiesSet() {
119 Assert.state(authenticationManager != null, "AuthenticationManager is required");
120 }
121
122 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
123 ServletException {
124
125 final boolean debug = logger.isDebugEnabled();
126 final HttpServletRequest request = (HttpServletRequest) req;
127 final HttpServletResponse response = (HttpServletResponse) res;
128
129 try {
130
131 Authentication authentication = tokenExtractor.extract(request);
132
133 if (authentication == null) {
134 if (stateless && isAuthenticated()) {
135 if (debug) {
136 logger.debug("Clearing security context.");
137 }
138 SecurityContextHolder.clearContext();
139 }
140 if (debug) {
141 logger.debug("No token in request, will continue chain.");
142 }
143 }
144 else {
145 request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
146 if (authentication instanceof AbstractAuthenticationToken) {
147 AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
148 needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
149 }
150 Authentication authResult = authenticationManager.authenticate(authentication);
151
152 if (debug) {
153 logger.debug("Authentication success: " + authResult);
154 }
155
156 eventPublisher.publishAuthenticationSuccess(authResult);
157 SecurityContextHolder.getContext().setAuthentication(authResult);
158
159 }
160 }
161 catch (OAuth2Exception failed) {
162 SecurityContextHolder.clearContext();
163
164 if (debug) {
165 logger.debug("Authentication request failed: " + failed);
166 }
167 eventPublisher.publishAuthenticationFailure(new BadCredentialsException(failed.getMessage(), failed),
168 new PreAuthenticatedAuthenticationToken("access-token", "N/A"));
169
170 authenticationEntryPoint.commence(request, response,
171 new InsufficientAuthenticationException(failed.getMessage(), failed));
172
173 return;
174 }
175
176 chain.doFilter(request, response);
177 }
178
179 private boolean isAuthenticated() {
180 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
181 if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
182 return false;
183 }
184 return true;
185 }
186
187 public void init(FilterConfig filterConfig) throws ServletException {
188 }
189
190 public void destroy() {
191 }
192
193 private static final class NullEventPublisher implements AuthenticationEventPublisher {
194 public void publishAuthenticationFailure(AuthenticationException exception, Authentication authentication) {
195 }
196
197 public void publishAuthenticationSuccess(Authentication authentication) {
198 }
199 }
200
201 }