Skip to content

Instantly share code, notes, and snippets.

@yterradas
Last active January 30, 2018 14:06
Show Gist options
  • Save yterradas/7e95378640eeb597ce33 to your computer and use it in GitHub Desktop.
Save yterradas/7e95378640eeb597ce33 to your computer and use it in GitHub Desktop.
Override AnonymousAuthenticationFilter with a custom implementation.
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig
extends WebSecurityConfigurerAdapter {
@Value("${oauth.check_token.url:http://localhost:3030/oauth/token/info}")
private String checkTokenUrl;
@Autowired @Qualifier("restTemplate")
private RestOperations authRestTemplate;
@Override
protected void configure( HttpSecurity http )
throws Exception {
// @formatter:off
http.anonymous().authenticationFilter(proxyAuthenticationFilter()).authorities("ROLE_USER")
// NOTE: filter must be enable
// .sessionManagement().disable()
.and()
.headers().disable()
.requestCache().disable()
.formLogin().disable()
.rememberMe().disable()
.x509().disable()
.jee().disable()
.httpBasic().disable()
.csrf().disable()
.logout().disable();
// @formatter:on
}
@Override
public void configure( WebSecurity web )
throws Exception {
// @formatter:off
// NOTE: disable in production
web.debug(true);
// @formatter:on
}
protected ProxyAuthenticationFilter proxyAuthenticationFilter()
throws Exception {
return new ProxyAuthenticationFilter(checkTokenUrl, authRestTemplate);
}
}
public class ProxyAuthenticationFilter
extends AnonymousAuthenticationFilter {
private final Logger log = LoggerFactory.getLogger(getClass());
private RestOperations authTemplate;
private String checkTokenUrl;
public ProxyAuthenticationFilter( final String checkTokenUrl, final RestOperations authTemplate ) {
super("PROXY_AUTH_FILTER");
this.checkTokenUrl = checkTokenUrl;
this.authTemplate = authTemplate;
}
@Override
public void doFilter( ServletRequest req, ServletResponse res, FilterChain chain )
throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(createAuthentication((HttpServletRequest) req));
if ( log.isDebugEnabled() ) {
log.debug("Populated SecurityContextHolder with authenticated user: {}",
SecurityContextHolder.getContext().getAuthentication());
}
chain.doFilter(req, res);
}
@Override
protected Authentication createAuthentication( final HttpServletRequest request )
throws AuthenticationException {
AuthUserInfo authDetails = getUserInfo(request);
// NOTE: delete once this is returned from provider
if (authDetails != null) {
authDetails.setUserId("abcde12345");
authDetails.setUsername("username");
}
if (null == authDetails) {
throw new AuthenticationCredentialsNotFoundException("Could not authenticate user");
}
if ( isEmpty(authDetails.getUsername()) || isEmpty(authDetails.getUserId()) ) {
throw new BadCredentialsException("User details does not have sufficient credentials");
}
// NOTE: delete once this is returned from provider
List<? extends GrantedAuthority> authorities = Collections
.unmodifiableList(Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
AuthUser principal = new AuthUser(authDetails.getUsername(), authDetails.getUserId(), authorities);
return new AnonymousAuthenticationToken("ANONYMOUS", principal, authorities);
}
private AuthUserInfo getUserInfo( HttpServletRequest request ) {
final String authHeader = request.getHeader("Authorization");
if ( log.isDebugEnabled() ) {
log.debug("Validating: {} with provider", authHeader);
}
HttpEntity<String> entity = new HttpEntity<>(
new HttpHeaders() {{
set("Authorization", authHeader);
}}
);
AuthUserInfo authDetails = null;
try {
ResponseEntity<AuthUserInfo> authProviderResp = authTemplate
.exchange(checkTokenUrl, HttpMethod.GET, entity, AuthUserInfo.class);
authDetails = authProviderResp.getBody();
} catch (RestClientException e) {
log.error("Could not communicate with OAuth2 provider", e);
}
return authDetails;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment