The application I\'m working on already has Spring Security to handle form based authentication. Now the requirement is to login a user programmatically via an external serv
I have a similar setup in my application. Here are the basic elements as far as I can tell:
You need to create an AuthenticationProvider
like so:
public class TokenAuthenticationProvider implements AuthenticationProvider {
@Autowired private SomeService userSvc;
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
if (auth.isAuthenticated())
return auth;
String token = auth.getCredentials().toString();
User user = userSvc.validateApiAuthenticationToken(token);
if (user != null) {
auth = new PreAuthenticatedAuthenticationToken(user, token);
auth.setAuthenticated(true);
logger.debug("Token authentication. Token: " + token + "; user: " + user.getDisplayName());
} else
throw new BadCredentialsException("Invalid token " + token);
return auth;
}
}
You also need to create a Filter
to turn the custom parameter into an authentication token:
public class AuthenticationTokenFilter implements Filter {
@Override
public void init(FilterConfig fc) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
SecurityContext context = SecurityContextHolder.getContext();
if (context.getAuthentication() != null && context.getAuthentication().isAuthenticated()) {
// do nothing
} else {
Map params = req.getParameterMap();
if (!params.isEmpty() && params.containsKey("auth_token")) {
String token = params.get("auth_token")[0];
if (token != null) {
Authentication auth = new TokenAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}
fc.doFilter(req, res);
}
@Override
public void destroy() {
}
class TokenAuthentication implements Authentication {
private String token;
private TokenAuthentication(String token) {
this.token = token;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return new ArrayList(0);
}
@Override
public Object getCredentials() {
return token;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return null;
}
@Override
public boolean isAuthenticated() {
return false;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
// your custom logic here
}
}
}
You need to create beans for these:
Finally, you need to wire these beans into your security config (adjust accordingly):
There might be another way, but this definitely works (using Spring Security 3.1 at the moment).