@Override public void aroundWriteTo(WriterInterceptorContext responseCtx) throws IOException, WebApplicationException { RequestDetails requestDetails = (RequestDetails) responseCtx.getProperty(TMP_REQDETAILS); if (requestDetails.principal != null) { ByteArrayOutputStream content = new ByteArrayOutputStream(); OutputStream oldStream = responseCtx.getOutputStream(); responseCtx.setOutputStream(content); responseCtx.proceed(); byte[] contentData = content.toByteArray(); RESTResponseSigner responseSigner = new RESTResponseSigner( requestDetails.nonce, requestDetails.signature, requestDetails.statusCode, contentData); try { responseCtx .getHeaders() .add( RESTRequestSigner.HEADER_SIGNATURE, signResponse(requestDetails.principal, responseSigner.getDataToSign())); } catch (InvalidKeyException e) { logServerError( "Invalid key for identity " + requestDetails.identity + " : " + e.getMessage(), e, null); throw new WebApplicationException(INTERNAL_SERVER_ERROR); } catch (BackendAccessException e) { logServerError("Unexpected BackendAccessException" + e.getMessage(), e, null); throw new WebApplicationException(INTERNAL_SERVER_ERROR); } oldStream.write(contentData); } }
@Override public void filter(ContainerRequestContext requestContext) throws IOException { String nonce = requestContext.getHeaderString(HEADER_NONCE); String identity = requestContext.getHeaderString(HEADER_IDENTITY); try { if (StringUtils.isNotEmpty(identity)) { MDC.put(MDC_IDENTITY, identity); } String timestampStr = requestContext.getHeaderString(HEADER_TIMESTAMP); String signature = requestContext.getHeaderString(HEADER_SIGNATURE); if (!ValidationUtils.notEmpty(nonce, identity, timestampStr, signature)) { logUnauthorizedAccess( "Unauthorized request (missing any of nonce, identify, timestamp, signature)", requestContext); throw new AccessUnauthorizedException(); } URI requestUri = requestContext.getUriInfo().getRequestUri(); StringBuilder path = new StringBuilder(requestUri.getPath()); if (requestUri.getRawQuery() != null) { path.append('?').append(requestUri.getRawQuery()); } RESTRequestSigner restRequestSigner = new RESTRequestSigner( requestContext.getMethod(), path.toString(), nonce, timestampStr, identity); ByteArrayOutputStream content = new ByteArrayOutputStream(); InputStream is = requestContext.getEntityStream(); IOUtils.copy( is, contentMaxSize != null ? new BoundedOutputStream(content, contentMaxSize, true) : content); byte[] contentData = content.toByteArray(); restRequestSigner.setContent(contentData); try { Date timestamp = TimeUtils.parseISOUTCDateTime(timestampStr); if (timestamp.after(new Date(System.currentTimeMillis() + expiry))) { String message = "Unauthorized request (expired timestamp): " + timestampStr; logUnauthorizedAccess(message, requestContext); throw new AccessUnauthorizedException(message); } if (replayAttackValidator.checkNonceReplay(nonce)) { String message = "Unauthorized request (duplicated nonce): " + nonce; logUnauthorizedAccess(message, requestContext); throw new AccessUnauthorizedException(); } requestContext.setEntityStream(new ByteArrayInputStream(contentData)); Principal principal = findUserPrincipal(identity); if (principal == null) { logUnauthorizedAccess( "Unauthorized request (principal not found): " + identity, requestContext); throw new AccessUnauthorizedException(); } if (!verifySignature( principal, restRequestSigner.getDataToSign(), signature, requestContext)) { logUnauthorizedAccess( "Unauthorized request (invalid signature): " + restRequestSigner.toString(), requestContext); throw new AccessUnauthorizedException(); } updateAuthenticatedContext(requestContext, principal); } catch (ParseException e) { logBadRequest("Invalid timestamp: " + timestampStr, e, requestContext); throw new WebApplicationException(BAD_REQUEST); } } finally { try { MDC.remove(MDC_IDENTITY); } catch (IllegalArgumentException e) { // } } }