I have a requirement to use two kinds of authentication, for web we @EnableRedisHttpSession and for other consumers like mobile we use @EnableAuthorizationServer with @EnableResourceServer.
suppose we try to protect a controller common to both the authentication mechanisms for e.g /api/v1/test
i have hit a roadblock. i am only able to use one kind of authentication scheme if i set @WebSecurityConfigurerAdapter @order(2) and @ResourceServerConfigurerAdapter @order(3) then i can only access the resource via web
and if i set @ResourceServerConfigurerAdapter @order(2) and @WebSecurityConfigurerAdapter @order(3) then only OAuth works.
i am unable to use both the mechanism at the same time.how can we make the two work together, for e.g if the request comes from web use the filter responsible for that and if the request comes from mobile use the appropriate filter. web uses cookies and API Consumers use Authorization : Bearer header.
please help
It's sounds very strange. I suggest you to review how REST API is used and why it should be used by browser users. Better to separate web views and REST API, don't mix it.
However, answering your question "can I use two kinds of authentication for some URI at once" - yes, you can.
You need custom RequestMatcher
that will decide how to route incoming request.
So:
Authorization
header
contains "Bearer"Code example:
public abstract class AntPathRequestMatcherWrapper implements RequestMatcher {
private AntPathRequestMatcher delegate;
public AntPathRequestMatcherWrapper(String pattern) {
this.delegate = new AntPathRequestMatcher(pattern);
}
@Override
public boolean matches(HttpServletRequest request) {
if (precondition(request)) {
return delegate.matches(request);
}
return false;
}
protected abstract boolean precondition(HttpServletRequest request);
}
@EnableResourceServer
@Configuration
public class ResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcherWrapper("/api/v1/test") {
@Override
protected boolean precondition(HttpServletRequest request) {
return String.valueOf(request.getHeader("Authorization")).contains("Bearer");
}
}).authorizeRequests().anyRequest().authenticated();
}
}
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new AntPathRequestMatcherWrapper("/api/v1/test") {
@Override
protected boolean precondition(HttpServletRequest request) {
return !String.valueOf(request.getHeader("Authorization")).contains("Bearer");
}
}).authorizeRequests().anyRequest().authenticated();
}
}
Using this configuration it's possible to use two different authentication types for one URI /api/v1/test
.
In addition, I highly recommended to read the article about Spring Security architecture by Dave Syer, to understand how does it work:
https://spring.io/guides/topicals/spring-security-architecture/#_web_security