Angular 4 httpd post call fails in iOS - nativescript

I am having a weird problem in a POST call in iOS using Nativescript and Angular 4. I have tested the same code in Android and works perfect. The server does not register any error but the call fails. This is the code I am using right now:
...
import { Http, Headers, Response, RequestOptions } from "#angular/http";
...
let headers = new Headers();
headers.append("Content-Type", "application/x-www-form-urlencoded");
let options = new RequestOptions({ headers: headers });
let body =
"Username=" + this.username
+"&Password=" + this.password;
this.http.post("http://myserver.com/api/login", body, options)
.map(result => result.json())
.subscribe(
result => {
this.loader.hide();
if (result.Authenticated) {
// Do something...
}
else {
Dialogs.alert({title: 'Error', message: "Username and/or password are incorrect.", okButtonText: "Close"});
}
},
error => {
Dialogs.alert({title: 'Error', message: "There was an error trying to send the request, please try again later.", okButtonText: "Close"});
}
)
The app shows me There was an error trying to send the request, please try again later. message, but there is no error in the server and the curious thing is that Android works fine.
I have enabled the enableProdMode() in Angular and no luck.
Any help please?
Thanks!

We were having crashing and hanging issues on Nativescript iOS + http connections until yesterday. We switched to https connections for our servers' API and everything is working perfectly now.
Maybe it has something to do with the secure / non secure connections on iOS?
Try switching to a secure connection and see what happens.
If you can't do that, try adding this to your info.plist file to allow http connections:
<key>NSAppTransportSecurity</key>
<dict>
<!--Include to allow all connections (DANGER)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

Related

Spring Keycloak Adapter sometimes returns with "Token is not active" when uploading files

lately we are facing an issue that our Spring Boot backend service (stateless REST service) SOMETIMES returns an HTTP 401 (Unauthorized) error when users try to upload files >70 MB (or in other words, when the request takes longer than just a couple of seconds). This does not occur consistently and only happens sometimes (~every second or third attempt).
The www-authenticate header contains the following in these cases:
Bearer realm="test", error "invalid_token", error_description="Token is not active"
Our Spring (Boot) configuration is simple:
keycloak.auth-server-url=${KEYCLOAK_URL:http://keycloak:8080/auth}
keycloak.realm=${KEYCLOAK_REALM:test}
keycloak.resource=${KEYCLOAK_CLIENT:test}
keycloak.cors=true
keycloak.bearer-only=true
Essentially, our frontend code uses keycloak-js and does the following to keep the access token fresh:
setInterval(() => {
// updates the token if it expires within the next 5s
this.keycloak.updateToken(5).then((refreshed) => {
console.log('Access token updated:', refreshed)
if (refreshed) {
store.commit(AuthMutationTypes.SET_TOKEN, this.keycloak.token);
}
}).catch(() => {
console.log('Failed to refresh token');
});
}, 300);
Further, we use Axios and a respective request filter to inject the current token:
axios.interceptors.request.use(
(request: AxiosRequestConfig) => {
if (store.getters.isAuthenticated) {
request.headers.Authorization = 'Bearer ' + store.getters.token;
}
return request;
}
);
This worked very well so far and we have never experienced such a thing for our usual GETs/POSTs/PUTs etc. This happens only when users try to upload files larger than (around) 70MBish.
Any hint or tip how to debug this any further? We appreciate any help...
Cheers

Invalid character returned in IE but not in Firefox and Chrome

I'm using fetch to return a JSON payload to a React SPA. My web server backend is ASP.NET Core 2.0. I recently updated to ASP.NET Core 2.0 and for the life of me can't figure out why IE no longer works with the web application.
The fetch is pretty straight forward.
fetch(getApiPath() + url, {
credentials: 'include'
})
.then(function(response){
if (response.status === 401 && history) {
history.push("/login")
throw new Error('Redirecting to login');
} else if (response.status === 200) {
return response.json();
} else {
throw new Error(response.statusText);
}
})
.then(success)
.catch(function(e) {
console.log(e)
});
The server end is also pretty straight forward.
[Authorize]
[Route("/dashboard")]
public object Index()
{
Log.Debug("Index");
return new { dashboard = _dashboard, authenticated = HttpContext.User.Identity.IsAuthenticated };
}
The problem manifests itself in a "Invalid Character" error in IE. This works fine in Chrome and Firefox. When looking at the response body, the IE response, is in fact an invalid character while in Chrome, it is the JSON payload.
I'm a little unsure where to even start looking into why IE wouldn't receive or parse the HTTP response correctly. Any ideas?
EDIT:
Making a cross-origin request from a Webpack Dev Server running on port 10000 to a local ASP.NET Core app running on 10001. When packaged for deployment, both the React App and the ASP.NET Core App run on 10000.
Headers between the two requests.
IE Request
IE Response
Chrome
Updated the endpoint to return an IActionResult and explicitly returning JSON. Same result. I've also realized it doesn't work in Edge either.
[Authorize]
[Route("/dashboard")]
public IActionResult Index()
{
return Json(
new { dashboard = _dashboard, authenticated = HttpContext.User.Identity.IsAuthenticated }
);
}
Without additional info I suspect the issue is related to ASP.Net's content negotiation and the fact your method return type is object. Don't use object, this is not Java :))
Before anything else, make sure fetch is sending an Accept: application/json header in IE.
I would also recommend for you to change the return type to IActionResult (or JSONResult if you want to force JSON) for your controller methods.

Vertx client gets clientabort exception

I am geting clientabort sockettimeout read exception at server side while invoking a rest service through https client inside vertx application. If i invoke a http setvice, it works fine though.
I get 200 ok in vertx and do not get any data back. And also i get connection was closed error in vertx.
Any idea why it happens. Help appreciated.
Code:
final HttpClient httpClient1 = vertx.createHttpClient(
new HttpClientOptions()
.setDefaultHost("localhost")
.setDefaultPo‌​rt(8443)
.setSsl(true‌​)
.setKeepAlive(true)‌
​.setMaxPoolSize(100)‌​
.setTrustAll(true)
);
‌​HttpClientRequest req = httpClient1.request(HttpMethod.POST, "/api/test/");
req.headers()
.set("Content-Length","10000000")‌​
.set("Content-Type",‌​"application/json")
.‌​set("Cache-Control", "no-transform, max-age=0");
Buffer body=Buffer.buffer("Hello World");
req.write(body);
That's not the way to send a request.
Hope working example may help you.
Server:
final Vertx vertx = Vertx.vertx();
vertx.createHttpServer().requestHandler((c) -> {
c.bodyHandler(b -> {
System.out.println(b.toString());
});
c.response().end("ok");
}).listen(8443);
Client:
final HttpClient client = vertx.createHttpClient(
new HttpClientOptions()
.setDefaultHost("localhost")
.setDefaultPort(8443));
client.request(HttpMethod.POST, "/", (r) -> {
System.out.println("Got response");
}).putHeader("Content-Length", Integer.toString("Hello".length()))
.write("Hello").end();
Two important notes: you must end .request() with .end() and you must set Content-Length correctly.

How come I keep getting a "Request failed with response code 401" when trying to push via Urban Airship?

I have double, triple, and quadruple checked that I have the right master key that I'm passing. My parameters are taking directly from the UA website also so it can't be that. Anyone see what I'm doing wrong here???
Parse.Cloud.define("sendPush", function(request, response) {
var Buffer = require('buffer').Buffer;
var parameters = {
"audience" : "all",
"device_types" : "all",
"notification" : {
"alert" : "Hello from Urban Airship."
}
};
var params = JSON.stringify(parameters);
Parse.Cloud.httpRequest({
url: "https://go.urbanairship.com/api/push/",
method: 'POST',
headers: {
"Content-Type" : "application/json",
"Authorization" : 'Basic ' + new Buffer('MASTER_KEY').toString('base64'),
"Accept" : "application/vnd.urbanairship+json; version=3;"
},
body: params,
success: function(httpResponse) {
response.error(httpResponse);
},
error: function(httpResponse) {
response.error('Request failed with response code ' + httpResponse.status);
}
});
});
I've also tried adding in APP_SECRET:
"Authorization" : 'Basic ' + new Buffer('APP_SECRET':'MASTER_KEY').toString('base64'),
It's not clear from your code sample if you are including the app key in your request. API requests to Urban Airship use HTTP basic authentication. The username portion is the application key and the password portion in this case is the master secret. The application secret is restricted to lower-security APIs and is for use in the distributed application. The master secret is needed for sending messages and other server API requests.
Urban Airship provides a guide for troubleshooting common API issues.
I had the same problem and tried to figure it out by Network diagnosing tools for more than two days. Because after debugging I checked that I send the right credentials to UA. After all I called the UA and ask them to check the Credentials (in my case was appKey and appToken for streaming with java-connect API) if they are still valid. They checked and approved the validation but just in case sent me a new credentials. And I could connect with the new credentials!
It is for sure a bug by UA because I tested the whole time by another test application, which was a Desktop java application and I could connect to the server (with the same appKey and appToken) and get the events, but I got 401 error in my main Application, which was a Web Application running on TomCat 8.0 . It means It worked in a same time in with the same credential for one application and did not work for another application.

SailsJS - using sails.io.js with JWT

I have implemented an AngularJS app, communicating with Sails backend through websockets, using sails.io.js.
Since the backend is basically a pure API and will be connected to from other apps as well, I'm trying to disable sessions completely and use JWT.
I have set up express-jwt and can use regular HTTP requests quite nicely, but when I send a request through sails.io.js, nothing happens at all - websocket request keeps pending on the client, and there's nothing happening on the server (with "silly" log level).
I've tried patching sails.io.js to support the query parameter, and when connecting, I send the token from Angular, but in the best case, I get a response with error message coming from express-jwt saying credentials are missing...
I've also seen some hints that socket.js in sails needs to be modified with beforeConnect, I've seen socketio-jwt, but have no idea where and how to plug that in, in Sails.
Has anyone implemented this and is using JWT with Sails and sockets? I'd appreciate any kind of hint in what direction to go :)
I realised that policy I've put in place and that was using express-jwt abstracted too much away from me, so I didn't figure out what exactly was happening. Once I looked at other examples, I've figured out that I only needed to check what's different for websocket requests than regular, and I quickly found a way around the problem.
So:
set up token signing and sending on login
Angular takes the token and saves to local storage
Create an interceptor for HTTP requests to add authorization header and token
Fix up sails.io.js to forward query parameters provided through options (as mentioned in the question)
When connecting using sails.io.js, send token as query parameter, i.e. url + '?token=' + token
In sails policy, check all combinations for token, including req.socket.handshake.query, as below:
module.exports = function (req, res, next) {
var token;
if (req.headers && req.headers.authorization) {
var parts = req.headers.authorization.split(' ');
if (parts.length == 2) {
var scheme = parts[0],
credentials = parts[1];
if (/^Bearer$/i.test(scheme)) {
token = credentials;
}
} else {
return res.json(401, {err: 'Format is Authorization: Bearer [token]'});
}
} else if (req.param('token')) {
token = req.param('token');
// We delete the token from param to not mess with blueprints
delete req.query.token;
}
// If connection from socket
else if (req.socket && req.socket.handshake && req.socket.handshake.query && req.socket.handshake.query.token) {
token = req.socket.handshake.query.token;
} else {
sails.log(req.socket.handshake);
return res.json(401, {err: 'No Authorization header was found'});
}
JWTService.verifyToken(token, function (err, token) {
if (err) {
return res.json(401, {err: 'The token is not valid'});
}
sails.log('Token valid');
req.token = token;
return next();
});
};
It works well! :)

Resources