-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Detect authorization bearer token properly #6813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
DefaultBearerTokenResolver has a bug that makes it miss authorization bearer tokens, if the "Bearer" is written in lower case as "bearer". The latter can be observed, when running Zuul as an API gateway that forwards authorization bearer tokens to downstream services. This seems to be fixed in spring-security master, but is still an issue in 5.1.x.
@TheFonz2017 Please sign the Contributor License Agreement! Click here to manually synchronize the status of this Pull Request. See the FAQ for frequently asked questions. |
@TheFonz2017 Thank you for signing the Contributor License Agreement! |
Note: there is an additional issue in this class. That is in line 39. |
The pattern used for matching needed to be applied in a case insensitive way. Note that according to https://tools.ietf.org/html/rfc6750#section-2.1 one could also argue that this implementation was correct and that generally the "Bearer" part should always be written exactly like this. In that case Spring Cloud Security OAuth2 would have a bug, since it does not pay attention to having "Bearer" capitalized.
@TheFonz2017 thanks for the PR! This was actually already addressed in 5.2, so we'd likely instead backport 63f2b60 instead of merging this PR. In addition, this is currently an open discussion over on #6228, and we need to make sure to resolve that before proceeding with a backport. |
Thanks for the update. I will wait then.
Dependencies I used - for reference
Authorization Header Re-Writing Zuul PRE-Filterimport static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
import java.util.Map;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
public class ZuulAuthorizationHeaderProxyFilter extends ZuulFilter {
@SuppressWarnings("unused")
private ZuulProperties zuulProperties;
@SuppressWarnings("unused")
private DiscoveryClientRouteLocator routeLocator;
/**
* Creates a new Zuul filter for canary testing using the given properties.
* @param zuulProperties the Zuul configurations as given in application.yml
* @param routeLocator the route locator.
*/
public ZuulAuthorizationHeaderProxyFilter(ZuulProperties zuulProperties, DiscoveryClientRouteLocator routeLocator) {
this.zuulProperties = zuulProperties;
this.routeLocator = routeLocator;
}
@Override
public boolean shouldFilter() {
// Only run, if there is a Zuul request header set for the authorization,
// and if it contains a bearer token.
RequestContext ctx = RequestContext.getCurrentContext();
Map<String, String> zuulRequestHeaders = ctx.getZuulRequestHeaders();
String authorizationHeaderValue = zuulRequestHeaders.get("authorization");
authorizationHeaderValue = authorizationHeaderValue != null ? authorizationHeaderValue : zuulRequestHeaders.get("Authorization");
return (authorizationHeaderValue != null) && (authorizationHeaderValue.trim().toLowerCase().startsWith("bearer"));
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
Map<String, String> zuulRequestHeaders = ctx.getZuulRequestHeaders();
String authorizationHeaderValue = zuulRequestHeaders.get("authorization");
authorizationHeaderValue = authorizationHeaderValue != null ? authorizationHeaderValue : zuulRequestHeaders.get("Authorization");
if(authorizationHeaderValue == null)
throw new ZuulException("Error! Could not retrieve authorization header from Zuul request headers.", 500, "Header not found. This must be an illegal state.");
authorizationHeaderValue = authorizationHeaderValue.replace("bearer", "Bearer");
zuulRequestHeaders.put("authorization", authorizationHeaderValue);
return null;
}
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return 11; // one after the OAuth2TokenRelayFilter
}
} |
DefaultBearerTokenResolver has a bug that makes it miss authorization bearer tokens, if the "Bearer" is written in lower case as "bearer". The latter can be observed, when running Zuul as an API gateway that forwards authorization bearer tokens to downstream services. This seems to be fixed in spring-security master, but is still an issue in 5.1.x.