There are lots of guidelines, sample codes that show how to secure REST API with Spring Security, but most of them assume a web client and talk about login page, redirection, using cookie, etc. May be even a simple filter that checks for the custom token in HTTP header might be enough. How do I implement security for below requirements? Is there any gist/github project doing the same? My knowledge in spring security is limited, so if there is a simpler way to implement this with spring security, please let me know.
- REST API served by stateless backend over HTTPS
- client could be web app, mobile app, any SPA style app, third-party APIs
- no Basic Auth, no cookies, no UI (no JSP/HTML/static-resources), no redirections, no OAuth provider.
- custom token set on HTTPS headers
- The token validation done against external store (like MemCached/Redis/ or even any RDBMS)
- All APIs need to be authenticated except for selected paths (like /login, /signup, /public, etc..)
I use Springboot, spring security, etc.. prefer a solution with Java config (no XML)
The code secure all endpoints - but I'm sure that you can play with that :). The token is stored in Redis using Spring Boot Starter Security and you have to define our own
UserDetailsService
which you pass intoAuthenticationManagerBuilder
.Long story short - copy paste
EmbeddedRedisConfiguration
andSecurityConfig
and replaceAuthenticationManagerBuilder
to your logic.HTTP:
Requesting token - sending basic HTTP auth content in a request header. A token is given back in a response header.
Same request but using token:
If you pass wrong username/password or token you get 401.
JAVA
I added those dependencies into
build.gradle
Then Redis configration
Security config:
Usually in tutorials you find
AuthenticationManagerBuilder
usinginMemoryAuthentication
but there is a lot more choices (LDAP, ...) Just take a look into class definition. I'm usinguserDetailsService
which requiresUserDetailsService
object.And finally my user service using
CrudRepository
.You're right, it isn't easy and there aren't many good examples out there. Examples i saw made it so you couldn't use other spring security stuff side by side. I did something similar recently, here's what i did.
You need a custom token to hold your header value
You need a spring security filter to extract the header and ask the manager to authenticate it, something like thisemphasized text
Register your custom filter in spring security chain
A custom auth provider to validate that token extracted with the filter.
Finally, register your provider as a bean so the authentication manager finds it in some @Configuration class. You probably could just @Component it too, i prefer this method
I recommend JSON Web Tokens http://jwt.io/ , it's stateless and scalable.
Here is an example project, https://github.com/brahalla/Cerberus
My sample app does exactly this - securing REST endpoints using Spring Security in a stateless scenario. Individual REST calls are authenticated using an HTTP header. Authentication information is stored on the server side in an in-memory cache and provides the same semantics as those offered by the HTTP session in a typical web application. The app uses the full Spring Security infrastructure with very minimum custom code. No bare filters, no code outside of the Spring Security infrastructure.
The basic idea is to implement the following four Spring Security components:
org.springframework.security.web.AuthenticationEntryPoint
to trap REST calls requiring authentication but missing the required authentication token and thereby deny the requests.org.springframework.security.core.Authentication
to hold the authentication information required for the REST API.org.springframework.security.authentication.AuthenticationProvider
to perform the actual authentication (against a database, an LDAP server, a web service, etc.).org.springframework.security.web.context.SecurityContextRepository
to hold the authentication token in between HTTP requests. In the sample, the implementation saves the token in an EHCACHE instance.The sample uses XML configuration but you can easily come up with the equivalent Java config.
Another Example Project which uses JWT - Jhipster
Try Generating a Microservice application using JHipster. It generates a template with out of the box integration between Spring Security and JWT.
https://jhipster.github.io/security/