Rest Assured Proxy Setting issue (java.net.ConnectException: Connection timed out exception) - java

One of the API (Say XYZ API) call alone requires the proxy to be set, When I run a suite where this API is called before and after every test script in the suite there is java.net.ConnectException seen randomly.
Only for XYZ API, I set and reset the proxy using the line:
RestAssured.proxy(String, int)
and
RestAssured.reset()
Please help me resolve this issue. Could this be a bug?
Note: This API call fails randomly just saying first 10 times it would have passed may be the 11th it fails with exception rest all scripts are then skipped in execution.
Code snapshot:
public void GetAuthenticationToken(String userid, String password)
{
RestAssured.proxy(config.getProperty("ProxyHost"),Integer.parseInt(config.getProperty("ProxyPort"))); //Authentication API is outside network and requires proxy
String APIUrl_Aut = config.getProperty("APIUrl_Aut");
String APIBody_Aut = "grant_type=password&username="+userid+"&password="+password;
//Making post request with authentication
Response response = RestAssured.given().log().all().headers("Accept", "application/json","Content-Type","application/x-www-form-urlencoded").body(APIBody_Aut).
when().post(APIUrl_Aut).then().contentType(ContentType.JSON).extract().response();
if (response.getStatusCode() == 200)
{
WritePropertyToTemp("AUTH_TOKEN", "Bearer "+response.body().jsonPath().get("access_token").toString());
WritePropertyToTemp("AUTH_TOKEN_OnlyToken",response.body().jsonPath().get("access_token").toString());
log.info("Authentication token generated successfully");
}
else
log.info("Authentication token failed to generate");
RestAssured.reset(); //Resetting proxy
}

Related

Retrieve Firebase User using token, from Google Cloud application running locally

I'm working on a Java API that functions as an endpoint API, and on production
it runs on the Google Cloud Platform. API methods are called by passing a Firebase token as part of the URL, and the token is used to create a User that's available inside the API method:
#ApiMethod(path = "myPath/{tokenId}/doSomething", httpMethod = "get")
public ResponseMessage ReturnSomething(#Named("tokenId") String tokenId, User user) throws UnauthorizedException, BadRequestException, InternalServerErrorException, FirebaseAuthException
{
if (user == null)
...
In production, when the URL is called from an Angular application on Firebase that passes the token in the URL, user is correctly created. I don't fully understand how the User is created from the token, I only know that it somehow happens "automatically" as part of Firebase integration with Google Cloud.
I want to debug the API locally by using Debug As > App Engine from inside Eclipse. When I do this however, and call the API from my local Angular application running using Firebase serve, the token is correctly passed to my locally running API, however user is always null.
#ApiMethod(path = "myPath/{tokenId}/doSomething", httpMethod = "get")
public ResponseMessage ReturnSomething(#Named("tokenId") String tokenId, User user) throws UnauthorizedException, BadRequestException, InternalServerErrorException, FirebaseAuthException
{
if (user == null)
// this is always null
I suspect this is a problem with my locally running Java API correctly authenticating to Firebase. I've looked at this guide, which suggests that the GOOGLE_APPLICATION_CREDENTIALS property on Windows should be set to the path of the JSON key of the App Engine default service account, which is the normal way to ensure that local access is granted to Google Cloud (and presumably Firebase) resources.
I've added this explicitly (I'd already run gcloud auth application-default login anyway, using the command line) however it's still not working. I just get null for the user and there's no indication of what's going on. I don't want to programatically authenticate as that means altering the API code to authenticate differently during debugging. How do I retrieve a User when debugging locally as App Engine?
UPDATE
I've realised that although the tokenId in the URL is present, I'm getting the following error when the API is called:
WARNING: Authentication failed: com.google.api.auth.UnauthenticatedException: No auth token is contained in the HTTP request
The tokenId value in the code below is a valid value, so I'm not sure why I'm getting this message:
#ApiMethod(path = "myPath/{tokenId}/doSomething", httpMethod = "get")
public ResponseMessage ReturnSomething(#Named("tokenId") String tokenId, User user)
I discovered that this was actually a problem with the Auth0 library that's being used in Angular to support authenticated HTTP requests to the Java API. The Auth0 library is used to inject the auth token into the Bearer of the request header whenever an Angular http.get is called from the Angular application. Creation of the User depends on this property being present in the HTTP header, with its value set to the value of the auth token.
I fixed this by altering the config for this library. I needed to temporarily whitelist localhost for the port (8080) that the API runs on, to allow Auth0 to inject the token into the HTTP header whenever there is a request to localhost:8080
const jwtConf: JwtModuleOptions = {
config: {
tokenGetter: getToken,
whitelistedDomains: ['localhost:8080']
}
};

CamelHttpResponseCode is null on service error

I'm new to camel and writing a small POC to implement in an existing application. Application takes a xml request as input which contains the requested services and relevant data. It then calls those services one by one.
When a service is called successfully then I retrieve the http response code in a processor like below and do further logic:
Object code = exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE);
if(null!=code && code instanceof Integer)
{
responseCode = (Integer) code;
}
In success case, responseCode received = 201
Based on the responseCode, I know if the service call is successful and then proceed with the next one.
However, I tried to produce the negative scenario by making the service url incorrect and can't see the http response code anymore:
Original service url - http://xxx:0000/.../.../.../.../...
Modified service url - http://xxx:0000/.../.../.../.../abc/...
In failure case, responseCode received = null
In postman, I get the below error:
org.apache.camel.http.common.HttpOperationFailedException: HTTP
operation failed invoking http://xxx:0000/.../.../.../.../abc/...
with statusCode: 404 at
org.apache.camel.component.http.HttpProducer.populateHttpOperationFailedException(HttpProducer.java:274)
at
org.apache.camel.component.http.HttpProducer.process(HttpProducer.java:183)
I don't know why exchange doesn't contain the http response code when it's present in the error message in the postman.
I'm using onException to handle any exceptions and then calling a processor to process the flow further:
<camel:onException>
<camel:exception>java.lang.Exception</camel:exception>
<camel:process ref="xxxProcessor" />
</camel:onException>
I think I can consider responseCode=null as failure and proceed with my logic but want to understand why response code is being returned as null.
Thanks in advance!
I figured it out. It seems that in case of service exception, an instance of org.apache.camel.http.common.HttpOperationFailedException is thrown and the http status code is present in it. It can be retrieved in the processor like below:
Exception e = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
if(null!=e && e instanceof HttpOperationFailedException)
{
HttpOperationFailedException httpOperationFailedException = (HttpOperationFailedException)e;
responseCode=httpOperationFailedException.getStatusCode();
}
The accepted answer helped me and it might have been valid! In the camel version I'm usin (2.20.1), getting the exception via the property does not seem to work. The following does
HttpOperationFailedException httpOperationFailedException = exchange.getException(HttpOperationFailedException.class);
if(null!=e) {
responseCode = httpOperationFailedException.getStatusCode());
}

Send multiple httpRequest by different proxies

I am using HTTPClient Fluent API version 4.3.2 to send multiple request to various addresses defined by user. Each address will use its particular proxy setting. Below is my current code:
try {
final Executor executor = Executor.newInstance().auth(proxy, userName, passWord);
System.out.println(executor.execute(Request.Get(uri).viaProxy(proxy)).returnResponse().getStatusLine());
} catch (final Exception e) {
e.printStackTrace();
}
I am facing a problem, when I connect to Address 1 with Proxy 1 (correct value of proxy username and proxy password), the request send properly as expected.
But when I add Address 2 with Proxy 1 (wrong value of proxy username and proxy password), with the expectation is request will fail, but it still connect successfully.
I though that after send request through a proxy, the very first proxy setting was cached somewhere in JVM, and I can not set another proxy setting for another request.
Is there any solution for this?
Trying setting proxy prior to request execution
Executor executor = Executor.newInstance().auth(proxy, userName, passWord);
System.out.println(executor
.viaProxy(proxy)
.execute(Request.Get(uri))
.returnResponse().getStatusLine());

Multi-Realm authentication (Forms + Custom authenticator)

We're in the process of building a Worklight application which has a 2 step authentication process.
Step 1: Forms Authentication
We're using the out of the box WASLTPARealm which authenticates us against a custom JAAS module in WebSphere and returns an LTPA token. This works as expected.
Step 2: Custom Authenticator
The second step is a custom Authenticator and Login Module which:
Reads the LTPA cookie that were set in Step 1
Makes a POST request to another application with the LTPA cookie (these 2 apps are trusted via Single Sign-On)
The POST request returns a response with additional session cookies
The user is authenticated
The issue is that the Custom Authenticator doesn't fire when using the client code provided in the documentation. Basically
The customAuthenticator is created via the usual
var customAuthenticator = WL.Client.createChallengeHandler("MyCustomRealm");
Then further down in the client code
var reqURL = '/my_custom_auth_request_url';
var options = {};
options.parameters = {};
options.headers = {};
customAuthenticator.submitLoginForm(reqURL, options, customAuthenticator.submitLoginFormCallback);
Results in a 404
[27/05/13 10:35:07:616 NZST] 00000326 WebSphereForm I com.worklight.core.auth.ext.WebSphereFormBasedAuthenticator processRequest FWLSE0055I: Not recognized.
[27/05/13 10:35:07:616 NZST] 00000326 Authenticatio E com.worklight.core.auth.impl.AuthenticationFilter doFilter FWLSE0048E: Unhandled exception caught: SRVE0190E: File not found: /apps/services/my_custom_auth_request_url
java.io.FileNotFoundException: SRVE0190E: File not found: /apps/services/my_custom_auth_request_url
Which happens because the request gets picked up by the WebSphereFormBasedAuthenticator instead of our Custom Authenticator.
We're writing the request URL to the logs inside the custom authenticator via
public AuthenticationResult processRequest(HttpServletRequest request, HttpServletResponse response, boolean isAccessToProtectedResource) throws IOException, ServletException {
logger.info("Request URL is: " + request.getRequestURI());
But that line never gets hit.
Can 2 authenticators work side by side? The behaviour I'm seeing is that
var wlFormsAuthenticator = WL.Client.createChallengeHandler("WASLTPARealm");
and
var customAuthenticator = WL.Client.createChallengeHandler("MyCustomRealm");
seem to get mixed up. I thought that calling submitLoginForm on the customAuthenticator should not be getting picked up by the WebSphereForms authenticator and instead should go to our custom one.
Can you please clarify the expected behaviour and a potential Workaround?
Also, what DOES work is calling
WL.Client.login("MyCustomRealm", {
onSuccess: function() {
},
onFailure: function() {
}
});
In this case, the Java code gets hit and we successfully authenticate BUT, the URL is
http://localhosT:9080/worklight/apps/services/api/MyApp/common/login
Rather than my_custom_auth_request_url which means we can't filter out the requests in our Java code.
Hope this makes sense. Thanks in advance.
There seem to be a mix of terminology in your description.
Authenticator is server side entity. Custom Authenticator is implemented in Java.
Challenge handler is a client side entity. It is implemented in JavaScript.
From your description I'm guessing that you're trying to submit login form for custom authenticator before actually trying to get some resource from WL server. The problem is that instance of custom authenticator is only created once you try to access protected resource. Authenticator will refuse to receive credentials (or more generally - it will not really exist) unless you trigger authentication first. So your approach is correct, you might call WL.Client.login("realm") to trigger authentication process first. Other options are:
protect application environment using security test and set connectOnStartup:true
protect application environment using security test, set connectOnStartup:false and use WL.Client.connect() API.

Authentication Via Servlet

I have a situation as below:
I have 2 web applications running on Tomcat. Initially User gets logged in to the Application 1 and then. There is a link to the Application 2. On Clicking the link User should be redirected to second application.
Both applications using LDAP authentication.
Now, the problem here is second application has its own Authentication system.
So, We are planning to implicitly authenticate the user which is logged in the first system.
I have written a servlet, which gets executed when I click on link for App2 in the App1.
I am trying to use below code which should call Servlet "ldap-login" on app2 with given parameters.Parameter names are correct.
String targetURL = "http://localhost:8080/app2/ldap-login";
HttpClient client = new HttpClient();
PostMethod doPost = new PostMethod(targetURL);
//doPost.getParams().setBooleanParameter(HttpMethodParams.USE_EXPECT_CONTINUE, true);
doPost.addParameter("login_netid", "alice");
doPost.addParameter("login_password", "alice");
try {
int status = client.executeMethod(doPost);
if (status == HttpStatus.SC_OK) {
// redirect
response.sendRedirect("http://localhost:8080/app2/myPage");
} else {
System.out.println("Service failed, Response Code= " +
HttpStatus.getStatusText(status));
System.out.println("Response Body --> " + doPost.getResponseBodyAsString());
}
} catch (Exception ex) {
System.out.println("ERROR: " +
ex.getClass().getName() + " "+ ex.getMessage());
ex.printStackTrace();
} finally {
doPost.releaseConnection();
}
But I am getting Response "Moved temporarily".
Can anyone suggest me any alternate ?
A 302 Moved Temporarily response is just a redirect. It's exactly the kind of response which you would get when you do response.sendRedirect(). You can also very good get a redirect as a response to a successful login. I suggest to verify on the second application if it isn't indeed redirecting when the login is successful. You should then check if the response code is 302 instead of 200. Or, alternatively, you need to tell HttpClient to follow any redirects automatically.
Even more, if the login actually failed, what kind of response would you get from the second application? Would it throw an exception and thus return a response code of 500? Or would it just conditionally set some error message in the request scope and redisplay the JSP by a forward and thus keep a response code of 200? How would you then distinguish a 200 on a failed login from a 200 on a successful login?
Unrelated to the concrete problem, your approach will likely not work if the second application does not share the same session as the first application. A login is usually stored in the session, but you're not maintaining the session anywhere. Anyway, that's subject for a new question :)
As per the API doc, the sendRedirect call does a temporary redirect. As #BalusC mentioned, you need to handle response code SC_MOVED_TEMPORARILY or SC_FOUND.
The reason it's doing a redirect after login (or might be after any POST request) could be to avoid the Double Submit Problem. Here is another article on that one.

Categories