Coupling Android App with Web Service - android

I am creating a Webapplication - Food Review site for which we are also developing an android application.
I want to know how to couple the application session of a particular user over the Internet with the application.
When the user logs in thru the application how can i serve them content related to the user alone. How can i know which user is requesting.
I am from a PHP background so i am a little confused how its done in the mobile application

You can maintain state in the same way a web application does. When a browser stores a cookie all that means is that requests sent to a matching domain get the cookie in the HTTP header. When you construct your HTTP request in Android you have complete control of the headers so it's easy to add your cookie value.
E.G. Post to your authenticator, sending client details. The authenticator would normally respond including the cookie in its response headers, here's a sanitised version of google's cookie setting response headers:
Cache-Control:private, max-age=0
Content-Encoding:gzip
Content-Length:173
Content-Type:text/html; charset=UTF-8
Date:Fri, 04 Mar 2011 12:24:32 GMT
Expires:Fri, 04 Mar 2011 12:24:32 GMT
Location:http://www.google.co.uk/
Server:GSE
Set-Cookie:SID=UNIQUESIDGOESHERE;Domain=.google.co.uk;Path=/;Expires=Mon, 01-Mar-2021 12:24:32 GMT
HSID=SOMETHINGELSEUNIQUEHERE;Domain=.google.co.uk;Path=/;Expires=Mon, 01-Mar-2021 12:24:32 GMT;HttpOnly
You can read that value and attach it to any http requests you make and the server would be non the wiser that you aren't a normal web browser.

Android is pretty much stateless. (I mean even if it can use states, I haven't come across any such example so far)
So I don't think you can have a session as you have on the web.
You can have a token method to authenticate users for a particular time period. like the OAuth implemented web services do.
Your android app sends the token for each request and your server manages the generation and life of that token along with the permissions.
How does this sound?

Related

How to make Android app login requests all appear as one IP

I am developing a native Android app that must interact with a Salesforce org through a SOAP API. Currently, for users of the app to login, they must provide a security token alongside their username and password. This makes the login/signup process uncomfortably long and complicated. As far as I can see, the only solution is to whitelist every IP address in my Salesforce org. I would have thought this is a security issue, so I was wondering if there was a better solution.
As far as I can tell, one solution could be to configure my app to log in through a proxy, and then just whitelist the address of that proxy. It was while researching this that I found this https://serverfault.com/questions/514716/whats-the-minimum-required-squid-config-to-make-a-public-proxy-server that made me think that perhaps there is some other more established way to do this, that I am not aware of.
Basically, my question is, is there any way for an android app running on any phone to make requests to an external API that all appear to come from one IP address (possibly through a proxy server) (without doing anything "dodgy")?
Looks like you're solving wrong problem. Why do you want to bypass SF security features so badly.
Try logging in to SF using REST, not SOAP. The session id you'll receive can be used in any API. So if you log in with OAuth2 you might not need security token. You'd need consumer id and secret (but that's just a pair of values you securely generate in SF, not bound to any particular user. You can even use production's values to login to sandboxes).
There's A LOT of reading if you want to do it right. And some prerequisite step of creating a "Connected App". If possible check if your Android library doesn't have something built-in for OAuth logins (to SF, Gmail, Facebook, LinkedIn, Twitter... you can find OAuth/OpenId in few places)
If you want pure background connection without user realising he's communicating with Salesforce - probably the "Username and password" OAuth flow is best for you. That should be minimal changes in your code compared to SOAP login call. It's weak in a sense you still need to have a password (either user's password or some dedicated integration account) - but there's chance that no security token will be needed. Give it a go (examples below) and check user's login history for errors.
If your users have proper SF accounts then maybe another OAuth flow is better. One that ideally displays them with SF login page they trust and just redirects back to your app when login succeeded. (you probably saw something like this if you recently used SF Data Loader?). That way your app doesn't see the password, just the result. And it'll work even if your client wants to use custom domain, decides to enable Single Sign-On...
Sorry, authentication, authorization are massive topics. But there is a better way so I'd want you to make a conscious decision before you code yourself into a corner... If help materials are too dry / too new & full of keywords then maybe try passing some trailheads:
https://trailhead.salesforce.com/content/learn/modules/identity_basics
https://trailhead.salesforce.com/content/learn/modules/api_basics (read intro and REST API part)
https://trailhead.salesforce.com/en/content/learn/modules/mobile_sdk_introduction/mobilesdk_intro_security
Your SOAP login looks probably like that:
POST
https://test.salesforce.com/services/Soap/c/45.0/
HEADERS
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
PAYLOAD
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
   <soapenv:Body>
      <urn:login>
         <urn:username>uptonogood#example.com</urn:username>
         <urn:password>Nice_Try!111 + security token</urn:password>
      </urn:login>
   </soapenv:Body>
</soapenv:Envelope>
Corresponding OAuth login (forced to return XML although mobile app should "like" JSON better so if you want - ditch the Accept header I've added)
POST
https://test.salesforce.com/services/oauth2/token
HEADERS
Content-Type:application/x-www-form-urlencoded
Accept:application/xml
PAYLOAD
grant_type=password&
client_id=3MVG9fTLmJ60pJ5JaGv0NNHD5nh6P...&
client_secret=3437814...&
username=uptonogood#example.com&
password=Nice_Try!111
The proper way to do this would be to have your own backend through which you proxy your requests.
e.g.:
Android app -> Your backend -> Salesforce

Res.redirect() vs res. Json(). Server for web and mobile

I am new to web development. I had a web project with EJS templating. It redirects directly from the server. Using res.redirect() . I want to create a server for web and mobile both.
Question is... When i use res.json() it sends JSON data to client side. Can work for both.
It is possible to use res.redirect() for both. Web and mobile.
Pros and cons of res.rediret and res.json
Please explain. I appreciate your suggestions in adv. Thanks.
It is possible to use res.redirect() for both. Web and mobile.
If you mean can you use res.redirect() as an alternative to res.json() then the answer is NO. res.redirect() is not an alternative to res.json. res.redirect() only sends a code and a URL back to the client, there is no data in the response. You will still need to use res.json or res.send to get the data you need. Every time you use res.redirect() you are sending a response to the client telling them to make a brand new request to another location. You're not sending any real data. The android app will not get any content till you use res.json or res.send. Redirects just tell the client go get the data from somewhere else.
Below are example responses to an android app when the server uses res.json and res.redirect
res.redirect("/user")
//Response to Android app
302 /user
The response above means what you want is located at "/user" so the mobile app will need to make a request to
res.json(user)
//Response to Android app
{
name: "Arpit Yadav",
phone: 555-555
}
res.redirect sends status code 302 (if not specified), and location (route) to browser, after which browser redirects the request to the specified location, whereas res.json sets Content-Type: application/json and sends data to the browser.
Redirection is generally meant for browser only, but, you can use it for mobile. In that case, you have to handle the logic to re-request with updated location received from server that is not recommended.
In nutshell, both have different purpose. res.redirect to move clients to different route and res.json to actually sends the data.

Symfony 2 api logout

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...

Login to SMTP Server with Apache Commons Net

I'm trying to develop an Android application that takes a username and password from a user and checks his/her credentials against an email server. I just need to send the username and password combination to the email server and if the server accepts, then my application will consider the user to be authenticated.
I tried using Javamail, but apparently it doesn't get along with dalvik. Someone suggested that I try using Apache Commons, but I can't figure out how to get it to do what I need.
If anyone has any ideas, I greatly appreciate the help!
The server that I'm connecting to uses IMAP/SMTP, by the way.
Update: Here's the code that I'm using to do the connect
client = new AuthenticatingSMTPClient();
client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
client.connect(HOST, PORT);
client.login();
client.execTLS();
client.auth(AuthenticatingSMTPClient.AUTH_METHOD.PLAIN,user,pword);
And the server reply is :
220 pod51000.outlook.com Microsoft ESMTP MAIL Service ready at Thu, 14 Feb 2013 18:52:33 +0000
HELO 10.71.12.99
250 pod51000.outlook.com Hello [66.76.192.214]
STARTTLS
220 2.0.0 SMTP server ready
AUTH PLAIN
503 5.5.2 Send hello first
I've never had to do anything like this before, so I just need a little direction on things like how to send "Hello", what else the server expects, etc.
Solved it! Added a client.helo() before authentication and it works beautifully

403 forbidden with simple Android Picasa album list request

I'm having a terrible time accessing Picasa from Android. After hours of researching, I finally determined that the Google API Java Client library is what I should be using. Several hours later and I divined that I have to use Mercurial and Maven to download and build a sample client so that I can get certain secret libraries that aren't included in the download instructions. And of course the sample client is in no way compatible with and only slightly resembles that in the Picasa Developer's Guide.
So after much trouble I create a simple URL and try to list albums for a user, using code from the sample client:
PicasaUrl url = PicasaUrl.relativeToRoot("feed/api/user/someuser");
UserFeed userFeed = client.executeGetUserFeed(url);
Now the actual URL this creates is something like:
https://picasaweb.google.com/data/feed/api/user/someuser?prettyprint=true
If I put this in my browser, it works fine. In my Android client, however, it gives me an HTTP 403 forbidden error. And no, I can't even run the sample client, because it doesn't give me an APK file. (Plus the source code isn't documented, is written like spaghetti, and uses deprecated methods.)
After turning on protocol-level logging, it turns out that this is the HTTP request being sent:
GET https://picasaweb.google.com/data/feed/api/user/someuser?fields=author/name,entry(#gd:etag,category(#scheme,#term),gphoto:access,gphoto:numphotos,link(#href,#rel),summary,title,updated),link(#href,#rel),openSearch:totalResults&kinds=album&max-results=3&prettyprint=false
Accept-Encoding: gzip
Authorization: GoogleLogin auth=null
User-Agent: MyApp/1.0 Google-HTTP-Java-Client/1.6.0-beta (gzip)
GData-Version: 2
Where in the Sam Hill did all that crap come from? But you know what? The URL still works in my browser. This must be something about the Authorization: header.
After much more pain, I managed to modify the authentication from the sample so that a notification would appear and allow the user to authenticate the account. Now I'm able to list albums.
But I still don't understand: how can I list the public albums without authentication?

Categories

Resources