Java Client Libraries: Configure read timeouts? - asana

I am using the official Java client libraries (https://github.com/Asana/java-asana/) and I am frequently running into
java.net.SocketTimeoutException: Read timed out
and
java.net.SocketTimeoutException: connect timed out
problems. Is there any chance to configure those values, e.g. like done via
URLConnection.setReadTimeout
?

For the meantime, this solution can be used. This however, includes copying code from the Asana client libraries, which is problematic. I've created an issue: https://github.com/Asana/java-asana/issues/47
new Client(new AccessTokenDispatcher(personalAccessToken) {
#Override
public HttpRequest buildRequest(String method, GenericUrl url, HttpContent content) throws IOException {
HttpRequest request = httpTransport.createRequestFactory(req -> {
req.setConnectTimeout(connectTimeout);
req.setReadTimeout(readTimeout);
}).buildRequest(method, url, content);
request.getHeaders().setAuthorization("Bearer " + personalAccessToken);
return request;
}
});

Related

Unable to call nuxeo rest api from rest client when integrated with Keycloak authentication plugin

I wanted to integrate keycloak as authentication plugin for nuxeo platform both running on my local machine
Set up details
Nuxeo platform version: 10.10 (runs on tomcat 9)
Keycloak version: 6.0.1
keycloak tomcat adapter distribution: keycloak-tomcat8-adapter-dist
I followed the steps mentioned in link https://github.com/nuxeo/nuxeo/tree/master/nuxeo-services/login/nuxeo-platform-login-keycloak.
Here, I built the nuxeo-platform-login-keycloak plugin for keycloak 6.0.1 version.
On keycloak,
I set up a auth client under newly created realm 'demo'
Client details available in
client configuration
I created role as 'Members' and added admin role to it
I created a user 'keycloakuser' and added to 'Members'.
When nuxeo ui is hit from browser, the authentication flow works fine. It redirects me to login page of keycloak, on valid credentials, it redirects me to nuxeo ui.
The user created along with 'Members' group assigned to it.
Error Scenario
To call rest api from postman, I configured Oauth2 for authentication.
Auth url: http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth
Token Url: http://localhost:8080/auth/realms/demo/protocol/openid-connect/token
Client: testclient
Client secret: *****
Scope: openid
I used access_token obtained using Oauth2 flow, to make API call as http://localhost:8190/nuxeo/api/v1/id/document_id. It is failing with
java.lang.ClassCastException: class org.apache.catalina.core.ApplicationHttpRequest cannot be cast to class org.apache.catalina.connector.RequestFacade (org.apache.catalina.core.ApplicationHttpRequest and org.apache.catalina.connector.RequestFacade are in unnamed module of loader java.net.URLClassLoader #39aeed2f)
at org.nuxeo.ecm.platform.ui.web.keycloak.DeploymentResult.invokeOn(DeploymentResult.java:79) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.keycloak.KeycloakAuthenticatorProvider.provide(KeycloakAuthenticatorProvider.java:56) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.keycloak.KeycloakAuthenticationPlugin.handleRetrieveIdentity(KeycloakAuthenticationPlugin.java:113) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.handleRetrieveIdentity(NuxeoAuthenticationFilter.java:1137) [nuxeo-platform-web-common-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.doFilterInternal(NuxeoAuthenticationFilter.java:548) [nuxeo-platform-web-common-10.10.jar:?]
Observation:
1. The API request call is not hitting the keycloak endpoint
2. I tried to print the reqqest type (actually the request wrapper type) in both scenarios.
For browser request, it was org.apache.catalina.connector.RequestFacade and for api request it was org.apache.catalina.core.ApplicationHttpRequest which is not extending org.apache.catalina.connector.RequestFacade
Questions:
1. Does above behavior (mentioend in point 2) differ in tomcat versions earlier to tomcat 9?
2. Is the problem with compatibility issues with tomcat version and keycloak adapters jar version?
Late answer, but it may come handy for new readers. I had the exact same issue some months ago. It seems to be due to a bug in the nuxeo-platform-login-keycloak plugin.
I endend making the following changes to org.nuxeo.ecm.platform.ui.web.keycloak.DeploymentResult:
public class DeploymentResult {
final static Logger LOGGER = LoggerFactory.getLogger(DeploymentResult.class);
private boolean isOk;
private static KeycloakDeployment keycloakDeployment;
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
private Request request;
private CatalinaHttpFacade facade;
public DeploymentResult(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
}
boolean isOk() {
return isOk;
}
public static KeycloakDeployment getKeycloakDeployment() {
return keycloakDeployment;
}
public Request getRequest() {
return request;
}
public CatalinaHttpFacade getFacade() {
return facade;
}
public DeploymentResult invokeOn(AdapterDeploymentContext deploymentContext) {
// In Tomcat, a HttpServletRequest and a HttpServletResponse are wrapped in a Facades
if (httpServletRequest instanceof RequestFacade) {
// Received upon logout.
request = unwrapRequest(httpServletRequest);
} else {
request = unwrapRequest(((ServletRequestWrapper) httpServletRequest).getRequest());
}
facade = new CatalinaHttpFacade(httpServletResponse, request);
if (keycloakDeployment == null) {
keycloakDeployment = deploymentContext.resolveDeployment(facade);
}
if (keycloakDeployment.isConfigured()) {
isOk = true;
return this;
}
isOk = false;
return this;
}
/**
* Get the wrapper {#link Request} hidden in a {#link ServletRequest} object
*
* #param servletRequest, the main ServletRequest object
* #return the wrapper {#link Request} in {#link ServletRequest}
*/
private Request unwrapRequest(final ServletRequest servletRequest) {
try {
final Field f = servletRequest.getClass().getDeclaredField("request");
f.setAccessible(true); // grant access to (protected) field
return (Request) f.get(servletRequest);
} catch (final NoSuchFieldException | IllegalAccessException e) {
LOGGER.error("Couldn't unwrap request", e);
throw new RuntimeException(e);
} catch (final Exception e) {
LOGGER.error("Couldn't unwrap request", e);
throw e;
}
}
}
After building and deploying the plugin with these changes, I was allowed to call Nuxeo's REST API with bearer authentication using access token obtained through Keycloak.
Disclaimer: I focused on making it work, not on making it clean...

Preflight request fails on Chrome, Safary, Opera

I´m struggling with CORS requests on an Springsecurity backen project + Angulajs frontend.
CORS requests are working fine on IE (also with curl, wget and python requests) but miserably fail on Chrome and Safary because of Preflight bad request.
I know that those Browsers are blocking CORS POSTs, making the request empty as soon as the reach the backend, in fact I don’t see any data when I log out the request from backend. I tried every possible combination of:
Frontend side:
1) $http(method: POST)
2) $http.post(
3) Adding flags: Access-Control-Allow-Origin, Access-Control-Expose, etc.
4) Adding all possible header combination: ‘Content–Type’:’application/
Browser side:
1) Start chrome with flag: --disable-web-security
2) Installing Chrome extension CORS
Backend side:
1) Spring Security Disable csfr
2) Spring Security Permit all
3) Spring Security HttpMethod.OPTION
4) Set up a CORS Filter that accept all origins: “*”
5) Activated CORS framework for spring extending WebMvcConfigurerAdapter class.
Nothing, NHOTING worked for me!
I discussed this issue in another post: CORS POST request fails on Chrome, Safari and Firefox
I´m still unable to perform CORS requests, this is now I major issue and I suspect the problem is in LoginFilter:
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
private TokenAuthenticationService tokenAuthenticationService;
public JWTLoginFilter(String url, AuthenticationManager
authenticationManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
try {
ServletInputStream inputStream = httpServletRequest.getInputStream();
httpServletRequest.getCharacterEncoding();
AccountCredentials credentials = null;
ObjectMapper mapper = new ObjectMapper();
credentials = mapper.readValue(inputStream, AccountCredentials.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
return getAuthenticationManager().authenticate(token);
} catch (JsonMappingException e) {
e.printStackTrace();
throw e;
} catch (JsonParseException e) {
e.printStackTrace();
throw e;
} catch (AuthenticationException e) {
e.printStackTrace();
throw e;
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
throws IOException, ServletException {
AccountCredentials cred = (AccountCredentials) authentication.getPrincipal();
tokenAuthenticationService.addAuthentication(response, cred);
}
}
EDIT
the exact error on Google Chrome is:
:8000/#!/login:1 XMLHttpRequest cannot load http://localhost:8080/myApp/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 403.
So I found that it does not has ANYTHING to do with the request headers, but the problems are the response headers.
To make the preflight passing through, all response headers have to be mapped, as example:
response.addHeader("Access-Control-Expose-Headers", "xsrf-token, Authorization, Barer, Token");
The preflight request is sent AUTOMATICALLY with verb option by browser itself BEFORE the real request is sent.
You must configure your server to send response with some headers when this preflight request is sent. With spring security you can use :
#Provider
#Component
public class CrossDomainContainerResponseFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext containerRequestContext,
ContainerResponseContext containerResponseContext) throws IOException {
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "YOUR FRONTEND URI");
containerResponseContext.getHeaders().add("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin");
containerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
}
}
If you are using XML config, you can also use the <cors /> tag.
The --disable-web-security never worked for me on Chrome. But it worked on Vivaldi Browser.

Spring Security OAuth2: CORS preflight channel did not succeed

I was receiving this error while making a call to '/oauth/token' when I was making an HTTP call to the server instance running on my own system. I fixed this by creating a filter like this:
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
if (httpServletRequest.getMethod() != "OPTIONS") {
chain.doFilter(req, res);
} else {
// In case of HTTP OPTIONS method, just return the response
}
}
I have added it as a filter in WebConfigurer:
private void initCORSFilter(ServletContext servletContext, EnumSet<DispatcherType> disps) {
log.debug("Registering CORS Filter");
FilterRegistration.Dynamic corsFilter = servletContext.addFilter("corsFilter", new SimpleCORSFilter());
Map<String, String> parameters = new HashMap<>();
corsFilter.setInitParameters(parameters);
corsFilter.addMappingForUrlPatterns(disps, true, "/*");
corsFilter.setAsyncSupported(true);
}
I am getting this error in FireFox:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://182.176.221.94:9091/ams/oauth/token. (Reason: CORS preflight channel did not succeed).
In short I was making sure the the preflight OPTIONS call always gets a response to proceed ahead. This was working on my own system, but now that the server instance is deployed on a Linux server, I am again getting this issue. And I am getting this only on calling 'oauth/token', everything other call is working fine.
What can I possibly do to get rid of this. Any help?
Your filter does not need to be annotated with #Component and it should be mapped with adequate url pattern in WebConfigurer class like other filters used in JHipster.
Also your filter should not break the filter chain as it does for OPTIONS. It's not consistent to allow OPTIONS method in header and then to not return the headers if you are processing an OPTIONS request.
The problem was that I was using != comparison for if (httpServletRequest.getMethod() != "OPTIONS". I changed it to if (!httpServletRequest.getMethod().equalsIgnoreCase("OPTIONS")) instead and it worked. This could have something to do with the fact that I tested on local machine while running the codebase but created a WAR file out of it and deployed on the server where it didn't work. I am not sure what exactly is the reason, but this fixed the issue.

Dart request succeeding ... somehow?

I'm developing a dart application which will consume a REST service I'm building. I started writing out the dart code to perform an ajax request to my login endpoint. However, even when my dart ajax request should fail, it claims to succeed.
I don't have any services up and running (and even if I did it would be using the wrong domain / port right now), but this code gives a 200 OK HttpResponse every time:
class PlayerController {
const PlayerController();
static const String LOGIN_URL = "login";
void login(String username, String password) {
Map<String, String> headers = {"Content-Type": "application/x-www-form-urlencoded"};
String body = "j_username=$username&j_password=$password&submit=Login";
HttpRequest.request(LOGIN_URL, method: "POST", requestHeaders: headers, sendData: body)
.then((request) => processLogin(request, username))
.catchError((e) => processLoginError(e));
}
void processLogin(var whatIsThis, String username) {
query("#loginButton").text = "Logout";
//TODO get the player then set them
}
void processLoginError(var e) {
print("total failure to login because of $e");
}
}
It always hits the processLogin method, and never hits the processLoginError method. Does anyone have any idea why this would be? Should I be performing this ajax request in a different way? (If you couldn't guess, it will be signing into spring security).
I read somewhere that file system requests always succeed. Is Dart somehow making this a file system request rather than a web request?
This is because the request actually completes successfully.
Your request to "login" will actually call http://127.0.0.1:6521/[Path_to_your_Dart_file]/login
The server started by Dart when running in Dartium (127.0.0.1:6521) seems to answer to every POST request with HTTP 200 and an empty response body.
If you change the method from POST to GET, it will fail as expected.
As for why the server does this - I don't really know. This would have to be answered by the Dart team.

Generate PDF using Managed Bean with custom HTTP headers

Background
Generate a report in various formats (e.g., PDF, delimited, HTML) using an ADF Task Flow.
Problem
HTTP headers are being sent twice: once by the framework and once by a bean.
Source Code
The source code includes:
Button Action
Managed Bean
Task Flow
Button Action
The button action:
<af:commandButton text="Report" id="submitReport" action="Execute" />
Managed Bean
The Managed Bean is fairly complex. The code to responseComplete is getting called, however it does not seem to be called sufficiently early to prevent the application framework from writing the HTTP headers.
HTTP Response Header Override
/**
* Sets the HTTP headers required to indicate to the browser that the
* report is to be downloaded (rather than displayed in the current
* window).
*/
protected void setDownloadHeaders() {
HttpServletResponse response = getServletResponse();
response.setHeader( "Content-Description", getContentDescription() );
response.setHeader( "Content-Disposition", "attachment, filename="
+ getFilename() );
response.setHeader( "Content-Type", getContentType() );
response.setHeader( "Content-Transfer-Encoding",
getContentTransferEncoding() );
}
Issue Response Complete
getFacesContext().responseComplete();
Bean Run and Configure
public void run() {
try {
Report report = getReport();
configure(report.getParameters());
report.run();
} catch (Exception e) {
e.printStackTrace();
}
}
private void configure(Parameters p) {
p.put(ReportImpl.SYSTEM_REPORT_PROTOCOL, "http");
p.put(ReportImpl.SYSTEM_REPORT_HOST, "localhost");
p.put(ReportImpl.SYSTEM_REPORT_PORT, "7002");
p.put(ReportImpl.SYSTEM_REPORT_PATH, "/reports/rwservlet");
p.put(Parameters.PARAM_REPORT_FORMAT, "pdf");
p.put("report_cmdkey", getReportName());
p.put("report_ORACLE_1", getReportDestinationType());
p.put("report_ORACLE_2", getReportDestinationFormat());
}
Task Flow
The Task Flow calls Execute, which refers to the bean's run() method:
entry -> main -> Execute -> ReportBeanRun
Where:
<method-call id="ReportBeanRun">
<description>Executes a report</description>
<display-name>Execute Report</display-name>
<method>#{reportBean.run}</method>
<outcome>
<fixed-outcome>success</fixed-outcome>
</outcome>
</method-call>
The bean is assigned to the request scope, with a few managed properties:
<control-flow-rule id="__3">
<from-activity-id>main</from-activity-id>
<control-flow-case id="ExecuteReport">
<from-outcome>Execute</from-outcome>
<to-activity-id>ReportBeanRun</to-activity-id>
</control-flow-case>
</control-flow-rule>
<managed-bean id="ReportBean">
<description>Executes a report</description>
<display-name>ReportBean</display-name>
<managed-bean-scope>request</managed-bean-scope>
...
</managed-bean>
The <fixed-outcome>success</fixed-outcome> strikes me as incorrect -- I don't want the method call to return to another task.
Restrictions
The report server receives requests from the web server exclusively. The report server URL cannot be used by browsers to download directly, for security reasons.
Error Messages
The error message that is generated:
Duplicate headers received from server
Error 349 (net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION): Multiple distinct Content-Disposition headers received. This is disallowed to protect against HTTP response splitting attacks.
Nevertheless, the report is being generated. Preventing the framework from writing the HTTP headers would resolve this issue.
Question
How can you set the HTTP headers in ADF while using a Task Flow to generate a PDF by calling a managed bean?
Ideas
Some additional ideas:
Override the Page Lifecycle Phase Listener (ADFPhaseListener + PageLifecycle)
Develop a custom Servlet on the web server
Related Links
http://www.oracle.com/technetwork/middleware/bi-publisher/adf-bip-ucm-integration-179699.pdf
http://www.slideshare.net/lucbors/reports-no-notes#btnNext
http://www.techartifact.com/blogs/2012/03/calling-oracle-report-from-adf-applications.html?goback=%2Egde_4212375_member_102062735
http://docs.oracle.com/cd/E29049_01/web.1112/e16182/adf_lifecycle.htm#CIABEJFB
Thank you!
The problem was an incorrect implementation of RFC 2183:
response.setHeader( "Content-Disposition", "attachment; filename="
+ getFilename() );
The ; cannot be a ,.

Resources