My friend implemented an HTTP POST request in iOS and it was working fine.
I have tried to implement the same in Android, but it doesn't work until I added the User Agent (I got it with the help of some sniffer tools).
But in iOS he is not specifying the User Agent.
So,
What is the relevance of User Agent in HTTP Request?
Why is it not consistent between iOS and Android?
iOS already specifies the User Agent by default. The user agent sent with NSURLConnection on iOS is
User-Agent: <app identifier>/<app version> CFNetwork/609.1.4 Darwin/12.4.0
where <app identifier> is your bundle ID (e.g. com.company.app) and <app version> is the current version of your app. Apparently, as you experience, Android does not set a default User Agent with (non-browser) HTTP requests.
The server can use this information to adapt its response to the client's needs; e.g. showing a mobile version of a webpage instead of a desktop version, or just don't return anything (to prevent simple screen scraping).
Related
We have a mobile app that calls endpoints on host https://www.currentdomain.com. we are migrating to https://www.newdomain.com in a month
The network team is planning to setup a dns redirect from currentdomain to newdomain.
What is the best possible way to handle this change in the app with minimal change and work? What will happen if the app calls the endpoint on currentdomain after setting up the dns redirect?
You can support redirection in your APIs.I am not sure how much is it possible at your end but if yes, then no changes will be required at app side.
Otherwise http redirection can be handled easily by apps, like in iOS 1 method needs to be added & can redirect request to the desired url.
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/RequestChanges.html
Redirect handler in android
https://developer.android.com/reference/org/apache/http/client/RedirectHandler.html
1) Apps Type: Mobile Banking
2) Existing Worklight Version: 6.1 (Consumer Edition)
3) Cordova Version: 3.1.0
4) Supported Platform: Android 4.2+, iOS 7+
5) Server OS: Window Server 2008
6) Application Server: IBM WebSphere Liberty Profile
7) Database: IBM DB2
The Apps was implemented with Custom Challenge handler to authenticate the user from IBM WebSeal, the ChallengeHandler fires HTTPS requests to IBM WebSeal to perform the following:
Get login parameters from the IBM WebSeal (E.g. type of login page, Login Form submitting URL)
Exchange encryption keys (on top of HTTPS, the Bank requires the further encrypt the traffic using jCryption)
Submit encrypted Username/Password
All of the above steps were implemented with jQuery’s ajax(), post() or getJson() function, it is working perfectly in above setup.
The Problems
After the upgrade of Worklight 6.1 to MobileFirst 7.1, the above authentication method no longer works in Android devices, in the other hand iOS still working as intended.
After spending days in troubleshooting the detail request and response logs, we have come into a conclusion that the Android has a different context of Cookies management between jQuery’s ajax() post() with MobileFirst HTTP Requests.
Example:
By using WLJQ.ajax(… myUrl …) generate a Set-Cookie response, the Cookie will be appended automatically to all subsequence ajax request when the request are in the matching domain.
But the Set-Cookies response header from an ajax() request does not affect the following MobileFirst HTTP request functions:
1. ChallengeHandler.submitLoginForm
2. WL.Client.invokeProcedure
3. WL.Client.login
Our ChallengeHandler authenticate the user and remember the user by using cookie value, but since the cookies will not be shared between MobileFirst and jQuery, so a call to WL.Client.InvokeProcedure will be blocked by IBM WebSeal because the request was being identified as unauthenticated user.
We also observed that the user-agent for jQuery ajax/post are very different from above MobileFirst functions:
MobileFirst
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; SM-G925F Build/MMB29K)/Worklight/7.1.0.0 WLNativeAPI(zerolte; MMB29K.G925FXXU3DPCN; SM-G925F; SDK 23; Android 6.0.1)
jQuery (Running on Samsung Galaxy S6)
User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; SM-G925F Build/MMB29K; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.105 Mobile Safari/537.36/Worklight/7.1.0.0
Troubleshoot Summary
1)Update Android’s CookieManager to accept third party cookies
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptThirdPartyCookies(webView, true);
2) Manually retrieve cookie values from jQuery post() and append to MobileFirst function using WL.Client.setCookie
But due to browser restriction we were not able to retrieve Set-Cookie headers value
3) Convert all jQuery calls to use challengeHandler.submitLoginForm, but with this approach the MobileFirst session get reset after every calls of above code so it still does not work.
After opening a PMR with IBM, it is indeed a design change starting WL 6.2. As per IBM below:
• In the iOS operating system Cookie Storage is managed by a singleton
object (shared instance). As a result, app cookies are shared between
AJAX requests from the Webview and from native requests. This is the
reason why the migrated iOS app from v6.1 to post v6.1 seems to continue
working without code change
• In Android operating system this is not the case. Cookie Storage is
specific to each http client, therefore AJAX and native requests do
not share cookies. App code change is required in case app issue
custom AJAX requests
We changed our code to use the IBM recommended API of WLResourceRequest.
Would be better if you will phrase your text as a question. It is not clear if you actually have a question.
If you do, then the topic presented in the question warrants an IBM PMR (support ticket) to be opened, as it will not be possible to handle it via a question on StackOverflow.
If you do open a PMR, please provide full reproduction.
Is it possible to make HTTP request from iOS / Android Application to look for the Server exactly the same as if it came from PC Browser?
So, it would be impossible for the Server to detect that it is not actually from PC but from Mobile.
Yes, you can alter the User Agent header to make it look like the request was made by f.ex Internet Explorer.
Here is some clues on how to accomplish this on Android:
Android HTTP User Agent
iOS:
Change User-Agent and remove App Name and defaults iOS
Set the user agent on the request to other than the default to fool the server into thinking the request is coming from other than a device. One list of user agents is at http://www.useragentstring.com.
I have an android application that uses a symfony based api. I have users that login through the phone, send requests to the server and then logout. The problem is that unless I delete the cookies in the android(which I am storing) the symfony server would not log out the user, despite the fact that the user goes to the logout route.
This is part of my security.yml file (And I have tried a lot of combinations with this file to no avail)
firewalls:
api:
anonymous: ~
provider: users
access_denied_url: /user/accessDenied
pattern: ^/api/user
form_login:
login_path: /api/user/login
success_handler: Authentication_Handler
failure_handler: Failure_Handler
check_path: /api/user/login_check
remember_me: false
logout:
path: /api/user/logoutuser
success_handler: logout_handler
target: /
I have also tried triggering controllers manually that call $this->get('session')->invalidate(); and or that redirect to the logout path(some results around the web suggested that was a good idea, but it did not work) It just seems that, whenever cookies exist, the symfony server just logs the user in, that seems like a security issue to me considering that I am saving the cookies into shared preferences on android. Please help
I believe I have located the problem. On logout the cookie headers are not sent, so the server has no idea whose session to invalidate. Making the android httpclient behave like a full fledged browser can be tricky...
A sample mobile application sends POST requests to a HTTP server which we use to process information sent from the mobile application. We parse HTTP headers and the User-Agent header is always seen as "Apache-HttpClient" on all Android devices with different OSes.
If i perform any action from app in android device, it returns the user agent as Apache-HttpClient/UNAVAILABLE (java 1.4)
what's the problem? It doesn't provide me a User Agent string which contains information like OS information and other details.. Has anyone seen similar behavior before?
Apache-HttpClient/UNAVAILABLE (java 1.4)
Is the default User Agent string for the Apache client that your app is using, it is not an error in itself.
This client know's very little about the system that it is running on, which is for the best - it's just a simple one-size-fits-all method for an Android device (which could be a phone, a tablet, a TV or even a car!) to make http requests to the outside world.
User Agent strings are a way for User Agents (read "browsers") to identify themselves.
In the case of an Android App, your App is the browser, so the User agent string is for you to define within your app.
See: Android Generic User Agent (UA)
If you want to send information about the device then you need to collect that information with your app and then send it. Though, if you are collecting that data then you might as well put it in the body of the request rather than HTTP headers anyway.