package org.jboss.resteasy.skeleton.key.as7; import org.apache.catalina.connector.Request; import org.jboss.resteasy.skeleton.key.RSATokenVerifier; import org.jboss.resteasy.skeleton.key.ResourceMetadata; import org.jboss.resteasy.skeleton.key.SkeletonKeyPrincipal; import org.jboss.resteasy.skeleton.key.SkeletonKeySession; import org.jboss.resteasy.skeleton.key.VerificationException; import org.jboss.resteasy.skeleton.key.as7.i18n.LogMessages; import org.jboss.resteasy.skeleton.key.as7.i18n.Messages; import org.jboss.resteasy.skeleton.key.representations.SkeletonKeyToken; import org.jboss.resteasy.spi.ResteasyProviderFactory; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.Principal; import java.security.cert.X509Certificate; import java.util.Set; /** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */ public class CatalinaBearerTokenAuthenticator { protected ResourceMetadata resourceMetadata; protected boolean challenge; protected String tokenString; protected SkeletonKeyToken token; private Principal principal; protected boolean propagateToken; public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge) { this.resourceMetadata = resourceMetadata; this.challenge = challenge; this.propagateToken = propagateToken; } public ResourceMetadata getResourceMetadata() { return resourceMetadata; } public String getTokenString() { return tokenString; } public SkeletonKeyToken getToken() { return token; } public Principal getPrincipal() { return principal; } public boolean login(Request request, HttpServletResponse response) throws LoginException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader == null) { if (challenge) { challengeResponse(response, null, null); return false; } else { return false; } } String[] split = authHeader.trim().split("\\s+"); if (split == null || split.length != 2) challengeResponse(response, null, null); if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(response, null, null); tokenString = split[1]; try { token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata); } catch (VerificationException e) { LogMessages.LOGGER.error(Messages.MESSAGES.failedToVerifyToken(), e); challengeResponse(response, "invalid_token", e.getMessage()); } boolean verifyCaller = false; Set<String> roles = null; if (resourceMetadata.getResourceName() != null) { SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName()); if (access != null) roles = access.getRoles(); verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName()); } else { verifyCaller = token.isVerifyCaller(); SkeletonKeyToken.Access access = token.getRealmAccess(); if (access != null) roles = access.getRoles(); } String surrogate = null; if (verifyCaller) { if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0) { response.sendError(400); throw new LoginException(Messages.MESSAGES.noTrustedCertificates()); } // for now, we just make sure JBoss Web did two-way SSL // assume JBoss Web verifies the client cert X509Certificate[] chain = request.getCertificateChain(); if (chain == null || chain.length == 0) { response.sendError(400); throw new LoginException(Messages.MESSAGES.noCertificatesProvidedByJBossWeb()); } surrogate = chain[0].getSubjectX500Principal().getName(); } SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate); principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles); request.setUserPrincipal(principal); request.setAuthType("OAUTH_BEARER"); if (propagateToken) { SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata); request.setAttribute(SkeletonKeySession.class.getName(), skSession); ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession); } return true; } protected void challengeResponse(HttpServletResponse response, String error, String description) throws LoginException { StringBuilder header = new StringBuilder("Bearer realm=\""); header.append(resourceMetadata.getRealm()).append("\""); if (error != null) { header.append(", error=\"").append(error).append("\""); } if (description != null) { header.append(", error_description=\"").append(description).append("\""); } response.setHeader("WWW-Authenticate", header.toString()); try { response.sendError(401); } catch (IOException e) { throw new RuntimeException(e); } throw new LoginException(Messages.MESSAGES.challenged()); } }