I have read a lot of tutorials on Sync Adapter such as the tutorial on http://www.c99.org/2010/01/23/writing-an-android-sync-provider-part-1 as well as the SampleSyncAdapter sample code on Android Developer website. But I don't understand that how the server side handles the Authentication and synchronization queries. Is it possible for me to use php to query from a mySQL server database?
Asked
Active
Viewed 4,847 times
1 Answers
15
The piece you're missing is not part of a Sync Adapter. It's the AbstractAccountAuthenticator
. It's the class that actually deals with the user's password, and passing it to the server, and it will need to be written in a manner that's well paired with the server in question.
How:
First off, how does the process work?
- User enters username and password on the Settings->Accounts and Sync page.
- (Later...) Sync process starts.
- SyncAdapter calls blockingGetAuthToken()
- AccountAuthenticator starts.
- AccountAuthenticator uses regular http (or ideally, https) authentication to connect to the server, and once authenticated, requests a 'token' from the sever. This token is a large (say, 128 bit) random number, should only be able to be obtained from the server if you've logged in using password based authentication.
- AccountAutenticator caches the token, and then returns the token to the SyncAdapter.
- SyncAdapter tries to access content on the server, and passes the token as part of the http headers in its requests.
- Server accepts the token in lieu of normal http-auth, and allows the request to be served.
- Future sync attempts will end up skipping much of this process. On the following sync attempts, when the SyncAdapter calls blockingGetAuthToken(), the AccountAuthenticator simply returns the cached token, not needing to re-authenticate.
So this token is limited use -- After a while, the server will refuse to accept it. At that point, the SyncAdapter tries to use the token and gets an authentication error. So then what?
- The SyncAdapter calls invalidateToken(token) and passes the (now expired token) back to the AccountAuthenticator.
- AccountAuthenticator finds the token in its cache and throws it away.
- On the next call to blockingGetAuthToken(), the AccountAuthenticator will go communicate with the server and get a new token. From there, sync proceeds normally.
Why?
So there are several advantages.
- Normal http auth transmits the password in plaintext over the internet. If tokens are used, the password is sent only once, the token many times. This somewhat reduces the exposire of the password to sniffing.
- https authentication avoids the plaintext problem, but can be expensive, in terms of a mobile connection. Use of tokens allows lighter-weight http connections for the server calls that actually carry data, the https overhead is only seen on the first request, when the token is obtained.
- Segregation -- An AccountAuthenticator knows the user's actual pasword. The SyncAdapter only gets access to the the token and never learns the password. This is important to, say Google, because it allows a third party app to use a gmail account and pasword to authenticate, without the third party app (which could be malicious) to get the pasword (and forward it to a devious naer-do-well)
Expiration:
Tokens are kind of dangerous. Anyone who gets access to the token can login as you. So, good practices here:
- The server should expire a user's tokens after a fixed period of time. More paranoia -- shorter timeouts.
- The server should expire all a user's tokens whenever the user changes their password.
- The server should probably not expire a token assigned to a web device if the user on a web interface logs out. There isn't really a 'logout' concept for tokens.
- The server should consider tying a token to the IP address that first requests it, and then refuse authentication (but not necessarily expire) the token if a different IP address subsequently tries to use that token. If you do this, the server will definitely need to be capable of creating multiple tokens per user (one token per user:ipaddress combination) -- consider a user with two mobile devices -- without that, each time one syncs, it would invalidate the other's token. Consider also, two devices both on home wifi (sharing one ip address behind a router, and then one device leaves and starts using mobile network -- That's why you might choose not to expire, so the device still sitting at home can continue to use the token. However, the one device that goes roaming will see an auth failure and establish its own new token. When it comes home, the server should be sure to provide the same token that's already established for that IP address.)
- Depending on your paranoia level, consider only accepting auth tokens over https anyway. Firesheep is a great example of what a stolen Auth Token can get you. If you have user-sensitive data, you should only accept over https. Also, even if you don't have user-sensitive data, you might consider writing a protocol that demands https to change the DB while allowing http to read.

jcwenger
- 11,383
- 1
- 53
- 65
-
Why can't you just hash the username and password each time and send it? Skipping out a number of steps which to me seems mind dumbing. – HGPB Jun 04 '12 at 00:37
-
3Because then anyone who intercepts and stores the hash while it's in transit can login, as you, from anywhere, forever. Have you ever used a free wifi hotspot? Both the owner of the hotspot, and every single person using it, can see and record every bit you transmit. It's proven in the field. See http://codebutler.com/firesheep for a notable example involving stealing Facebook credentials. Note that this will even steal the auth cookie. With an auth cookie, they lose access when the server updates the cookie, but with a username/password hash, they have access until you change your password. – jcwenger Jun 04 '12 at 12:46
-
unless you salt the hash, which is much simpler than dealing with the hassel of tokens – Mbrevda Aug 30 '12 at 21:34
-
Salt isn't the problem, @Mbrevda. If you pass salt, username, and password into a hash, then if you intercept that hash in transit then you have a hash that never changes, isn't tied to a device or time of login, and can still be used, from anwhere, to authenticate as you, forever. This is just as bad as losing your password. – jcwenger Aug 31 '12 at 17:53
-
Sorry, I meant a nonce. If you pass a user name, a nonce, and a hash the only thing that stays the same is the user name. The hash and the nonce change every time. To prevent replay, either make the nonce time based (so that it only works NOW), or keep track of nonce/hash's used and never allow them to be used again. – Mbrevda Sep 03 '12 at 07:26
-
A hash plus a nonce is the definition of the token. The only difference is that the nonce is kept server side only. -- And a second thing. With Auth tokens, the android OS itself stores the password, it's never directly handed to the user application. This allows me to let a completely untrusted application auth against my google apps account, and I can be honestly sure that the app can't directly steal my password or use my password to change my password and steal the entire account. The only thing it gets is the token itself. It can auth as me, without ever knowing my password. That's big. – jcwenger Sep 10 '12 at 13:11
-
@Mbrevda is there a way to do this synchronization without using a token at all? I want to send username and password only. I see that it is less secure, but is there a way to do it and how to do it? I searched but I couldn't finds any example without using a token. – nikmin Jan 10 '13 at 14:30
-
@user837423785723, yes. Build your account and authenticator to simply feed the password back to the user when an auth request comes in. Not to be too trite here, but look at http://developer.android.com/training/id-auth/custom_auth.html, and do exactly the sorts of things that the author from Google tells you NOT to do because they're insecure. :) Also, welcome to StackOverflow. Start owning your identity, my friend... go by a name or a nickname, it makes you look more like part of the community than user
:) – jcwenger Jan 10 '13 at 20:02 -
@jcwenger I have question about this [here](http://stackoverflow.com/questions/14257002/android-contacts-sync-without-auth-token). Can you explain there more thoroughly how to do that? Let's say on the SampleSyncAdapter, what should I change to achieve this. If you can, please answer there, because I need this very urgent. Thanks – nikmin Jan 10 '13 at 21:41