I'm trying to build an app using Google Cloud Messaging.
I used the google gcm samples, with almost no modifications, and so far, I can send message between my client app and my personnal little php server. (no code problem here)
In samples, google let a sendRegistrationToServer() method (click here) for me to write when InstanceId is set, but I don't find any clue on the net about how to manage such things.
How should my database look like to handle users and tokens ?
(if someone could provide a little database structure example, it would make my day !)
Since tokens register an app or a phone and users a user (which imply a registration activity to get username and password, and I haven't made it yet), I kind of don't want to mix them in the same table,
but I might have misconceptions about the purpose of token.
For instance, I wonder why nobody seem to save the token in SharedPreferences...
EDIT : now I get the whole process :
Registration Activity --> Register your user
Send email adress and secured password to your server
Connection Activity --> Connect your user
Get a gcm_token and send it to your server and then map it with connection informations
This seems so simple and clear right now, but really didn't back then, so maybe it could help someone else...
The token may change so it is not useful to store it in shared preferences its better to call InstanceID.getToken so you are sure you always get the correct token value. The important thing is to know whether or not you have sent the latest token to your application server, this boolean should be stored in shared preferences.
You should have a class that extends InstanceIDListenerService in which you implement onTokenRefresh to handle new tokens.
You should map your app-generated user IDs to tokens, note that a single user may have many valid tokens associated with them. You don't have to store the tokens with your user's username's and passwords but there should be some mapping of user IDs to tokens.
Eg:
User (uid, uname, pword)
Token (uid, token_value)
A gcm should be associated with a user object.
Once a user gets his gcm token, its a user token and not device token as you might think.
For a simple database integration within your app i suggest you to use Parse.com and their android guide for getting started.
The token is getting authorized each time you open the app, and it might change along time - thats why nobody saves it and reusing the same token evreytime
Related
Some months ago, Doug Stevenson told me to use the Firebase checkment dedicated to the "ID Tokens verification": https://firebase.google.com/docs/auth/admin/verify-id-tokens
I have read the doc. What I have understood is: I can't trust the Android app when it announces to the server (Firebase Firestore Rules, Firebase Firestorage Rules, Cloud Functions) the ID of the user, because it can take an existing ID other than its actual own ID and announce it. So I have to use the token system proposed in the doc.
What I have understood too is: I must get the token just after the user successfully has logged in. Then I send it to the server and it "checks it". But then... what? Okay, the server checks it. But the result of this check, what should the server do with it?
Should I do all of this (send the token to the server, check it server-side, do something server-side with the result of this check) before each call made by the Android app to the server?
Examples:
if my Android user wants to edit its account, he will fill in the form (firstname, age, bank code, picture avatar). This data will be sent to Firestore and Firestorage, so their Rules will be executed ; the UID of the user must be passed, but in fact it should be the token, no? (since the Android app can lie on the UID by sending a fake UID if it's a hacker, cf. the beginning of this SO Question).
if my Android app sends data to Cloud Functions, that treats it and itself saves it into Firestore and Firestorage, should I use the token system too?
When writing directly to Firestore or Cloud Storage, the user can't fake sending a UID other than their own. As long as your security rules check it correctly, you won't have a problem. There are examples of how this works in the documentation. There is no need to verify any ID tokens when using security rules to control access - this is all handled automatically.
You use the Firebase Admin SDK to verify a token in the where your client app is directly invoking an HTTP type function, and that function needs to make sure that only valid users are allow to execute the code. The client sends the user's token along with the request, as shown in the documentation you linked, and the code on the backend should verify the token before doing any work on behalf of the user. There is really no need to try to pass along an ID token in any other type of Cloud Function.
Currently, as per sample app of quickblox, Account key, Service Key and Service secret is stored in app itself.
My concern is that anybody can easily reverse engineer an app to get these secrets and create any number of fake account to troll other users (or even delete accounts?).
Alternatively, even if I generate session token on server, a user can get hold of this token and (as per my understanding) achieve the same thing as above.
What I want is to give user just enough information to login with his server generated credentials and send/receive messages.
Is there a way to achieve this? Maybe something like creating a session on server which allows only login and chat.
The right way is to obfuscate your Account key, Service Key and Service secret values
there are a lot of ways to do it, also ProGuard can help with this
You also can create a session token on a server side and pass this token to your app by some way, for example to have another backend with such API, so end user will request a token from that API and next just use it withiut storing any sensetive data inside an app
We have a working website and now developing android application. Some API calls are public however some api calls requires valid user. One server side it is being maintained through sessions and cookies. How can I communicate with server securely from app. I want that user login once until user press logout or uninstall the app. I don't want to store user username and password in app because it can be easily access by anyone if device is rooted and also I don't have password if user is using facebook login method. What should I do to in app and on server side to make it secure and easy. I think apps like facebook etc use those type of approaches in their apps which I am searching.
I have done research on this and found only that I should use static HttpClient.
I am using volley library for network calls because it suites me.
You use a token. When the user logs in (over an HTTPS webservice), he sends up his username and password. The server stores that in a database and returns a token, just like a cookie would. All future requests from the app to the webservice should be done over HTTPS and should have that token as one of the parameters. The server can then lookup who it assigned that token to in its database, and send the user the appropriate data. If the token isn't there or isn't in the db, you return an error. When the user logs out, you delete the token from the DB.
The token number space needs to be big enough that a random token can't be guessed. Using a second piece of data on each request (such as user name, or something identifying the phone such as ANDROID_ID) would help prevent guessing attacks. And of course if you get repeated requests from someone with bad tokens you should treat that as an attack, just like you would with bad cookies.
I'm trying Google Plus sign-in in an Android app (with backend support).
I could get access token and email from the user, but know I don't know how should I recognise this user from the server. I'm sending this to the server (email and oauth token) with a POST throught SSL
Of course I could recognise them with their email, but that would open the doors for everyone how knows another email that's on the database.
How could I verify that the user's correctly authenticated and has sent me the correct oauth token for this email?
Thanks!
Two thoughts:
1) Generally, you shouldn't be sending the auth token over the wire if you can help it. Instead you should be using a hybrid flow where the client gets a one time code when it authenticates, passes you this one time code, and you can redeem this for an auth token and a refresh token. Using this method, your server also has offline access on behalf of the user. See https://developers.google.com/+/web/signin/server-side-flow for details. However, I'm not entirely sure how this works with the Android library.
2) Regardless of (1), generally what you can do is to use the plus.people.get method on the server with the userID of "me" to get the user's userID and verify this against what you're expecting. See https://developers.google.com/+/api/latest/people/get for more details.
Yours is a perfect case to use the Authorization code flow.
See this link. It has some workflow diagrams that you might want to see. In your case the user should authenticate and receive an authorization code (and not a token!).
He would then send the authorization code to your server, you can exchange this code for access + refresh tokens. Have your client registered for the scope and have the client credentials.
The access token flow (called the implicit grant flow) is generally used when requests need to be sent directly from the user's browser.
And, as #Prisoner already mentioned, you will have offline access too. That would be a much better design.
EDIT - you might also want to take a look at What is the difference between the 2 workflows? When to use Authorization Code flow?
I'm interested in the best way to do user auth in a mobile app. At the moment the set up is quite simple. I'm storing the username and password on the app and sending it to the api each time I need to run a restricted query.
This I feel is probably the wrong way to go about this.
Would a better way to be to send the username and password when the user logs in and then store that user's id? The problem with this is that then the api accepts a user id and not a username and password. A user id will be much easier to "guess" at and malicious persons would be able to submit a req to the api with randomly selected user id's performing actions under their account. I have an api key. Is this secure enough?
The issue is that I want to start integrating twitter and facebook oauth into the app. I haven't read much about it, but I think you get a "token". How would this work with the set up that you're suggesting? Would there be benefit to creating a token in my own database of users and using the token (whether it be mine, facebook's or twitter's) as the authorisation? Or would it make sense to keep each service separate and deal with them separately?
Thank you.
The correct way would be to generate auth token on the server when user logs and send this token in login reply. Then this token is used in subsequent requests.
This means that server must keep track of auth tokens it generates. You can also track token creation times and make tokens expire after some time.
Token must be a sufficiently long random string, so that it can not be easily guessed. How to do this was answered before: How to generate a random alpha-numeric string?
Personally I prefer the UUID approach.
Update:
This problem was already solved in web browsers, via cookies and sessions. You can reuse this mechanism in your Android requests (though some REST purists disprove this approach):
Enable sessions on server.
When user logs into a server add some data to session, for instance time of login:
request.getSession().setAttribute("timeOfLogin", System.currentTimeMillis());
Since sessions are enabled, you also need to enable support for cookies in your HttpClient requests: Using Cookies across Activities when using HttpClient
Every time a request is made, server should check if session contains timeOfLogin attribute. Otherwise it should return HTTP 401 reply.
When user logs out, call server logout url and clear the cookies on client.