Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions pdp/conf.dist/ranger-pdp-site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@
<description>PEM-encoded public key for verifying JWT signatures.</description>
</property>

<property>
<name>ranger.pdp.authn.jwt.cookie.name</name>
<value>hadoop-jwt</value>
<description>Cookie name from which a JWT bearer token may be read.</description>
</property>

<property>
<name>ranger.pdp.authn.jwt.audiences</name>
<value/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,6 @@ private void addAuthFilter(Context ctx) {
authFilterDef.addInitParameter(RangerPdpConstants.PROP_AUTHN_JWT_ENABLED, Boolean.toString(config.isJwtAuthnEnabled()));
authFilterDef.addInitParameter(RangerPdpConstants.PROP_AUTHN_JWT_PROVIDER_URL, config.getJwtProviderUrl());
authFilterDef.addInitParameter(RangerPdpConstants.PROP_AUTHN_JWT_PUBLIC_KEY, config.getJwtPublicKey());
authFilterDef.addInitParameter(RangerPdpConstants.PROP_AUTHN_JWT_COOKIE_NAME, config.getJwtCookieName());
authFilterDef.addInitParameter(RangerPdpConstants.PROP_AUTHN_JWT_AUDIENCES, config.getJwtAudiences());

// Kerberos / SPNEGO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,6 @@ public String getJwtPublicKey() {
return get(RangerPdpConstants.PROP_AUTHN_JWT_PUBLIC_KEY, "");
}

public String getJwtCookieName() {
return get(RangerPdpConstants.PROP_AUTHN_JWT_COOKIE_NAME, "hadoop-jwt");
}

public String getJwtAudiences() {
return get(RangerPdpConstants.PROP_AUTHN_JWT_AUDIENCES, "");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ private RangerPdpConstants() {
public static final String PROP_AUTHN_JWT_ENABLED = PROP_AUTHN_JWT_PREFIX + "enabled";
public static final String PROP_AUTHN_JWT_PROVIDER_URL = PROP_AUTHN_JWT_PREFIX + "provider.url";
public static final String PROP_AUTHN_JWT_PUBLIC_KEY = PROP_AUTHN_JWT_PREFIX + "public.key";
public static final String PROP_AUTHN_JWT_COOKIE_NAME = PROP_AUTHN_JWT_PREFIX + "cookie.name";
public static final String PROP_AUTHN_JWT_AUDIENCES = PROP_AUTHN_JWT_PREFIX + "audiences";

// Kerberos/SPNEGO auth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@
/**
* Authenticates requests using a JWT bearer token.
*
* <p>Checks for the token in the {@code Authorization: Bearer <token>} header first,
* then in the configured JWT cookie. Delegates signature verification and expiry/audience
* <p>Checks for the token in the {@code Authorization: Bearer <token>} header
* Delegates signature verification and expiry/audience
* checks to {@link RangerDefaultJwtAuthHandler} from the {@code ranger-authn} module.
*
* <p>Configuration keys (all prefixed with {@code ranger.pdp.authn.jwt.}):
* <ul>
* <li>{@code provider.url} – JWKS endpoint URL (optional if public key is set)
* <li>{@code public.key} – PEM-encoded public key (optional if provider URL is set)
* <li>{@code cookie.name} – JWT cookie name (default: {@code hadoop-jwt})
* <li>{@code audiences} – comma-separated list of accepted audiences (optional)
* </ul>
*/
Expand All @@ -58,7 +57,6 @@ public void init(Properties config) throws Exception {

copyIfPresent(config, RangerPdpConstants.PROP_AUTHN_JWT_PROVIDER_URL, jwtConfig, RangerDefaultJwtAuthHandler.KEY_PROVIDER_URL);
copyIfPresent(config, RangerPdpConstants.PROP_AUTHN_JWT_PUBLIC_KEY, jwtConfig, RangerDefaultJwtAuthHandler.KEY_JWT_PUBLIC_KEY);
copyIfPresent(config, RangerPdpConstants.PROP_AUTHN_JWT_COOKIE_NAME, jwtConfig, RangerDefaultJwtAuthHandler.KEY_JWT_COOKIE_NAME);
copyIfPresent(config, RangerPdpConstants.PROP_AUTHN_JWT_AUDIENCES, jwtConfig, RangerDefaultJwtAuthHandler.KEY_JWT_AUDIENCES);

delegate = new RangerDefaultJwtAuthHandler();
Expand Down
6 changes: 0 additions & 6 deletions pdp/src/main/resources/ranger-pdp-default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@
<description>PEM-encoded public key for verifying JWT signatures.</description>
</property>

<property>
<name>ranger.pdp.authn.jwt.cookie.name</name>
<value>hadoop-jwt</value>
<description>Cookie name from which a JWT bearer token may be read.</description>
</property>

<property>
<name>ranger.pdp.authn.jwt.audiences</name>
<value/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
Expand All @@ -44,29 +43,14 @@ public class RangerDefaultJwtAuthHandler extends RangerJwtAuthHandler {
public static boolean canAuthenticateRequest(final ServletRequest request) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String jwtAuthHeaderStr = getJwtAuthHeader(httpServletRequest);
String jwtCookieStr = StringUtils.isBlank(jwtAuthHeaderStr) ? getJwtCookie(httpServletRequest) : null;

return shouldProceedAuth(jwtAuthHeaderStr, jwtCookieStr);
return shouldProceedAuth(jwtAuthHeaderStr);
}

public static String getJwtAuthHeader(final HttpServletRequest httpServletRequest) {
return httpServletRequest.getHeader(AUTHORIZATION_HEADER);
}

public static String getJwtCookie(final HttpServletRequest httpServletRequest) {
String jwtCookieStr = null;
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookieName.equals(cookie.getName())) {
jwtCookieStr = cookie.getName() + "=" + cookie.getValue();
break;
}
}
}
return jwtCookieStr;
}

@Override
public ConfigurableJWTProcessor<SecurityContext> getJwtProcessor(JWSKeySelector<SecurityContext> keySelector) {
ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
Expand All @@ -82,10 +66,9 @@ public ConfigurableJWTProcessor<SecurityContext> getJwtProcessor(JWSKeySelector<
public RangerAuth authenticate(HttpServletRequest httpServletRequest) {
RangerAuth rangerAuth = null;
String jwtAuthHeaderStr = getJwtAuthHeader(httpServletRequest);
String jwtCookieStr = StringUtils.isBlank(jwtAuthHeaderStr) ? getJwtCookie(httpServletRequest) : null;
String doAsUser = httpServletRequest.getParameter(DO_AS_PARAMETER);
// authenticate against the JWT first to get the real (token-verified) user
String realUser = authenticate(jwtAuthHeaderStr, jwtCookieStr);
String realUser = authenticate(jwtAuthHeaderStr);

if (realUser != null) {
String effectiveUser = realUser;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,18 @@ public abstract class RangerJwtAuthHandler implements RangerAuthHandler {
public static final String TYPE = "ranger-jwt"; // Constant that identifies the authentication mechanism.
public static final String KEY_PROVIDER_URL = "jwks.provider-url"; // JWKS provider URL
public static final String KEY_JWT_PUBLIC_KEY = "jwt.public-key"; // JWT token provider public key
public static final String KEY_JWT_COOKIE_NAME = "jwt.cookie-name"; // JWT cookie name
public static final String KEY_JWT_AUDIENCES = "jwt.audiences";
public static final String KEY_JWT_ISS = "jwt.issuer";
public static final String JWT_AUTHZ_PREFIX = "Bearer ";

protected static String cookieName = "hadoop-jwt";

protected List<String> audiences;
protected String issuer;
protected JWKSource<SecurityContext> keySource;
private JWSVerifier verifier;
private String jwksProviderUrl;

public static boolean shouldProceedAuth(final String authHeader, final String jwtCookie) {
return (StringUtils.isNotBlank(authHeader) && authHeader.startsWith(JWT_AUTHZ_PREFIX)) || (StringUtils.isNotBlank(jwtCookie) && jwtCookie.startsWith(cookieName));
public static boolean shouldProceedAuth(final String authHeader) {
return (StringUtils.isNotBlank(authHeader) && authHeader.startsWith(JWT_AUTHZ_PREFIX));
}

@Override
Expand All @@ -89,12 +86,6 @@ public void initialize(final Properties config) throws Exception {
throw new Exception("RangerJwtAuthHandler: Mandatory configs ('jwks.provider-url' & 'jwt.public-key') are missing, must provide atleast one.");
}

// setup custom cookie name if configured
String customCookieName = config.getProperty(KEY_JWT_COOKIE_NAME);
if (customCookieName != null) {
cookieName = customCookieName;
}

// setup audiences if configured
String audiencesStr = config.getProperty(KEY_JWT_AUDIENCES);
if (StringUtils.isNotBlank(audiencesStr)) {
Expand All @@ -114,13 +105,13 @@ public void initialize(final Properties config) throws Exception {

public abstract ConfigurableJWTProcessor<SecurityContext> getJwtProcessor(JWSKeySelector<SecurityContext> keySelector);

protected String authenticate(final String jwtAuthHeader, final String jwtCookie) {
protected String authenticate(final String jwtAuthHeader) {
if (LOG.isDebugEnabled()) {
LOG.debug("===>>> RangerJwtAuthHandler.authenticate()");
}

if (shouldProceedAuth(jwtAuthHeader, jwtCookie)) {
String serializedJWT = getJWT(jwtAuthHeader, jwtCookie);
if (shouldProceedAuth(jwtAuthHeader)) {
String serializedJWT = getJWT(jwtAuthHeader);

if (StringUtils.isNotBlank(serializedJWT)) {
try {
Expand Down Expand Up @@ -151,22 +142,14 @@ protected String authenticate(final String jwtAuthHeader, final String jwtCookie
return null;
}

protected String getJWT(final String jwtAuthHeader, final String jwtCookie) {
protected String getJWT(final String jwtAuthHeader) {
String serializedJWT = null;

// try to fetch from AUTH header
if (StringUtils.isNotBlank(jwtAuthHeader) && jwtAuthHeader.startsWith(JWT_AUTHZ_PREFIX)) {
serializedJWT = jwtAuthHeader.substring(JWT_AUTHZ_PREFIX.length());
}

// if not found in AUTH header, try to fetch from cookie
if (StringUtils.isBlank(serializedJWT) && StringUtils.isNotBlank(jwtCookie)) {
String[] cookie = jwtCookie.split("=");
if (cookieName.equals(cookie[0])) {
serializedJWT = cookie[1];
}
}

return serializedJWT;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ public void initialize() {

config.setProperty(RangerJwtAuthHandler.KEY_PROVIDER_URL, PropertiesUtil.getProperty(RangerSSOAuthenticationFilter.JWT_AUTH_PROVIDER_URL));
config.setProperty(RangerJwtAuthHandler.KEY_JWT_PUBLIC_KEY, PropertiesUtil.getProperty(RangerSSOAuthenticationFilter.JWT_PUBLIC_KEY, ""));
config.setProperty(RangerJwtAuthHandler.KEY_JWT_COOKIE_NAME, PropertiesUtil.getProperty(RangerSSOAuthenticationFilter.JWT_COOKIE_NAME, RangerSSOAuthenticationFilter.JWT_COOKIE_NAME_DEFAULT));
config.setProperty(RangerJwtAuthHandler.KEY_JWT_AUDIENCES, PropertiesUtil.getProperty(RangerSSOAuthenticationFilter.JWT_AUDIENCES, ""));
config.setProperty(RangerJwtAuthHandler.KEY_JWT_ISS, PropertiesUtil.getProperty(RangerSSOAuthenticationFilter.JWT_ISSUER, ""));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

Expand Down Expand Up @@ -178,7 +177,7 @@ void testDoFilter_skipsJwt_whenAlreadyAuthenticated_evenIfBearerHeaderPresent()
}

@Test
void testDoFilter_skipsJwtFilter_whenNoBearerAndNoCookie() throws Exception {
void testDoFilter_skipsJwtFilter_whenNoBearer() throws Exception {
PropertiesUtil.getPropertiesMap().put("ranger.sso.enabled", "false");

HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
Expand All @@ -187,7 +186,6 @@ void testDoFilter_skipsJwtFilter_whenNoBearerAndNoCookie() throws Exception {

// no bearer header, no cookies
Mockito.when(req.getHeader("Authorization")).thenReturn(null);
Mockito.when(req.getCookies()).thenReturn(null);

RangerJwtAuthFilter jwt = Mockito.mock(RangerJwtAuthFilter.class);
RangerJwtAuthWrapper wrapper = new RangerJwtAuthWrapper();
Expand All @@ -199,26 +197,6 @@ void testDoFilter_skipsJwtFilter_whenNoBearerAndNoCookie() throws Exception {
verify(chain, times(1)).doFilter(req, res);
}

@Test
void testDoFilter_invokesJwtFilter_whenJwtCookiePresent() throws Exception {
PropertiesUtil.getPropertiesMap().put("ranger.sso.enabled", "false");

HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
HttpServletResponse res = Mockito.mock(HttpServletResponse.class);
FilterChain chain = Mockito.mock(FilterChain.class);

Mockito.when(req.getHeader("Authorization")).thenReturn(null);
Mockito.when(req.getCookies()).thenReturn(new Cookie[] {new Cookie("hadoop-jwt", "abc")});
RangerJwtAuthFilter jwt = Mockito.mock(RangerJwtAuthFilter.class);
RangerJwtAuthWrapper wrapper = new RangerJwtAuthWrapper();
setField(wrapper, "rangerJwtAuthFilter", jwt);

wrapper.doFilter(req, res, chain);

verify(jwt, times(1)).doFilter(req, res, chain);
verify(chain, times(1)).doFilter(req, res);
}

@Test
void testDoFilter_redirectsToLogin_whenJwtAttemptedButUnauthenticated_andBrowserAgent() throws Exception {
PropertiesUtil.getPropertiesMap().put("ranger.sso.enabled", "false");
Expand Down
Loading