Problem Description
I am writing application which must connect to the server and download some data from the server. The URL of the file witch must be downloaded is formatted as follow:
http://www.myserver.com/file.xml?username=xxx&password=xxx
Question
URL and password are not provided by the user, I simply keep them in the code and add to the URL where I need. My question is how can I keep securely password and username on the Android device.
I would advise against keeping any kind of credential (username) and authenticator (password) stored on your device, as well as transmitting them around; this is often considered a security flaw, since middle-man attacks can intercept the HTTP traffic and easily identify both.
I would recommend instead the creation a token engine that would associate temporary identifiers to users and devices. For example:
User ID 100 receives a temporary token, code A1S2D3F4 (randomly generated.)
The code is associated with the device ID AND200.
Whenever device AND200 tries to access the server, it would generate the following URL:
http://www.myserver.com/file.xml?t=A1S2D3F4
Notice that there is no content identifying the user, nor its credentials or passwords. You may check if the device generating the URL is the one the token was originally associated with. Adittional controls may be implemented to detect tokens being used out of their lifespan, and help identify malicious users.
In Android you can use Md5 encoding method for password encoding and if you need to save those user details then it store in the shared preference
Did you see if you can use Google OAuth2: http://developer.android.com/training/id-auth/authenticate.html
If not, do not send user name and password in the URL but in a HTTPS POST and the correct way is using SOAP web services.
Just as a hint there is a good talk on google io conference about security of android apps.
Link
They don't cover secure server communication explicitly but give some hints about it and provide an encryption library to simplify any encryption tasks.
Related
I have a website and my own server and database, I also have an native Android app. I need to allow users to be able to sign-in with their account from the website inside the app in order to sync information and other things they need to use. I've been stuck for a couple of days trying to figure out how to do that. I've found a lot of content regarding OAuth and AppAuth but they are focused on using an OAuth API to the job. Back on my server, I use Hybridauth for social login, but users can also register directly on the site. How would be the proper way to allow my users to sign-in to their website account through the Android app?
You're overthinking it. OAuth isn't meant for users to log in, it's meant to enable external services to access data on behalf of a user.
To make a user log in? Create a POST endpoint on your webservice named login. It should take two parameters- username and password. The body of the login service should salt and hash the password, then check if the hash equals the hash stored in the db for the same user. If so, you're logged in and you return a success packet with a unique token to authenticate you for later requests. If not, you return a failure. The Android app would ask the user for their data, then send a request to the endpoint. On success it saves the token and sends it in all future requests to authenticate yourself, either as a parameter or as a header.
This is of course the simplest possible version. More advanced features would include expiring of login tokens, refresh tokens, possible lockout if you have too many bad requests, etc. But the above is the basic idea. Although really I'd look for an open source solution you can take, as there's quite a lot of complexity when you get into all the stuff mentioned above, and its a place where a mistake that leads to a vulnerability is probably the most dangerous.
I'm developing an Android app which has a service to upload images/files to a FTP server.
To make that possible, the app on the device has to log in into the FTP server before sending data.
And here comes my problem. The user does not need to / have to know about the FTP login data. Only the app itself. I have to store the login data in the Java class. But how should I secure the user and password?
I could encrypt it or obfuscate it. But I think it would be possible for a hacker to read the password at the runtime when the "setPassword(passwordString) methods is called by the JVM:
String passwordString = "myPass";
JSch ssh = new JSch();
session = ssh.getSession(SFTP_USER, HOST_ADDRESS, 22);
session.setPassword(passwordString);
So how could I store my credentials inside the APK file and secure them? I don't want anyone to get access to my FTP server.
how could I store my credentials inside the APK file and secure them? I don't want anyone to get access to my FTP server.
The stated problem cannot be solved.
It does not matter how clever your obfuscation technique is. If you hide fixed credentials in the APK file then someone who analyses your app is going to find them.
If you take only one thing from this answer, let it be that having a single, static password for your server is extremely problematic, as you'll never be able to change the password server-side, because you'd break all the apps. It will be a matter of time before your password is public knowledge and there will be nothing you can do about it.
Any reasonable approach requires separate access credentials for every individual user.
A traditional user sign-up system that involves a confirmation email is a pretty good approach. You can use something like Google+ sign-in or Facebook Connect to minimize the hassle for the end user.
If you absolutely insist on having zero user interaction, an approach that might work (somewhat) is to have the app register for Google Cloud Messaging and then send it a push notification containing access credentials, which the app will store in the KeyChain.
If you generate a unique user ID and password for every app installation, you'll be able to monitor the server and block any abusive access credentials without affecting any of the other users. If you somehow factor the code signing identity of the APK file into the process, you'll have a basic defense against people repackaging your app. This approach will not protect you against an intelligent attacker, but it might raise the bar high enough for your purposes.
Also, regardless what you do, be sure to properly verify your server's SSL certificate. If you don't, an attacker will simply run your connection through a proxy server.
I managed to implement the auth function described by google using a clientid.
So when visiting the html page, one gets asked to authenticate with a google account.
Question: As it is now, everyone can use the site, as long as he/she has a Google account to authenticate with. How do i restrict the usage to a certain group of users? Do i need to manage a list of unique user ids provided by the User object? Or is there already something prebuild, that i can make use of?
I think the safest would be to keep a list of Ids. What are the basis that you expect google or anyone else to know what kind of users you want to allow?
Even if its only geographic there are times when people might be using proxies or using yor site from a remote location.
The site you linked to also says so much :
Specifying Authorized Clients in the API Backend
You must specify which clients are allowed to access the API backend
by means of a whitelist of client IDs. A client ID is generated by the
Google API console from a client secret, such as the SHA1 fingerprint
of a key used to secure an Android app, or from the Bundle ID/Apple
Store ID pair for an iOS app, as described in Creating OAuth 2.0
Client IDs. At runtime, a client app is granted the authorization
token it needs to send requests to the API backend if its client
secret matches one contained in a client ID within the API backend's
client ID whitelist.
Also its only common authentication (who is it), authorization (what they can do on your site) comes from you.
My company is building a RESTful API that will return moderately sensitive information (i.e. financial information, but not account numbers). I have control over the RESTful API code/server and also am building the Android app. I've setup the API to use OAuth 2 with authorization code grant flow (with client ID and secret), and I auto-approve users without them having to approve the client since we own both client and provider. We use CAS for SSO and I am using this for the Authorization server as part of the OAuth 2 process when the user logs in to retrieve the token.
I am contemplating various ways to secure the data on the Android app. I've concluded that storing the client id and secret on the device is definitely not going to happen, but am thinking that storing the auth token might work, since it is only risk to the individual user (and really only if they happen to have a rooted phone).
Here are two options I have thought of. They both require me to have a sort of proxy server that is CAS protected, does the dance with the API server, and returns the auth token. This gets rid of the need for storing the client id and secret in the app code.
Here are what I've come up with:
1) Require the user to enter their password to access data each time they startup the App. This is definitely the most foolproof method. If this were done, I'd probably want to save the userID for convenience, but in that case couldn't use the CAS login (since it's web-based). I might be able to use a headless browser on the backend to log the user into CAS and retrieve the token based on what they enter in the Android form, but this seems hacky. Saving the userID is similar to what the Chase app does (if you happen to use this one) - it saves the userID but not your password between sessions.
2) Store the auth token on the Android device. This is a little less secure, but almost foolproof. When the user starts the app for the first time, open the webpage to the CAS login of the proxy server that returns the token (similar to https://developers.google.com/accounts/docs/MobileApps). After the user logs in and the token is returned to the app, encrypt it and store it private to the application. Also, use ProGuard to obfuscate the code, making the encryption algorithm more difficult to reverse engineer. I could also work in a token refresh, but I think this would be more of a false sense of security.
3) Don't use CAS but come up with another way to get an auth token for the service.
Any advice of how others have implemented similar scenarios (if it's been done)?
Thanks.
Well the reason why standards like OAuth are developed is that not everyone has to rethink the same attack vectors again and again. So most often it is your best choice to stick to something already available instead of baking your own thing.
The first problem with clients that are not capable of secretly storing data is that the user's data could be accessed by some attacker. As it is technically not possible to prevent this (code obfuscation won't help you against an expert attacker), the access token in OAuth 2 typically expires after short time and doesn't give an attacker full access (bounded by scope). Certainly you shouldn't store any refresh token on such a device.
The second problem is client impersonation. An attacker could steal your client secret and access your API in his own (maybe malicious) app. The user would still have to login there himself. The OAuth draft there requires the server to do everything it can to prevent this, but it is really hard.
The authorization server MUST authenticate the client whenever possible. If the authorization server cannot authenticate the client due to the client's nature, the authorization server MUST require the registration of any redirection URI used for receiving authorization responses, and SHOULD utilize other means to protect resource owners from such potentially malicious clients. For example, the authorization server can engage the resource owner to assist in identifying the client and its origin.
I think Google are the first to try another approach to authenticate a client on such devices, by checking the signature of the application, but they are not yet ready for prime time. If you want more insight into that approach, see my answer here.
For now, your best bet is to stay on the OAuth way, i.e. having the access token, client ID and client secrect (when using the authorization code grant flow) on the device, and configure your server to do additional checks. If you feel more secure obfuscating these, just do it, but always think of it as if these values were publicly available.
Here's the problem: I'm developing a desktop application to interface with a server, and the client has to log in. Something like with Skype or IM applications. I want to give the client the option of being logged in automatically, ie. no need to type in their credentials every time the applications loads.
How can I achieve this, while protecting the client's information?
Thank you, I've been pondering this problem for days now and I can't seem to come up with a solution. Any help or guidance would be gold at this stage.
If you are using a secure communication channel to the server (like using SSL, for instance) then you could send the username and a hash of the password (using a cryptographically secure hash function like SHA-512 - there's no known feasible collision or preimage attacks).
What you save locally is the username and the hash of the password. Given that the communication channel to the server is secure nobody else will see the information sent (no replay attack possible). And using a cryptographically secure hash function means that it's a one-way function, no "going back" to the original input.
Another way would be to get a token of authentication from the server upon successful login. Then the protocol could accept authentication of user combined with the token within a certain duration of time. Then you don't have to store the hash of the password locally, only the username and the token. Thus if somebody gets the token it will expire at some point. But bear in mind that the token should not be reissued using another token, only with a correct username/password combination. Additionally, the user should not be able to change/see the password if logged in using a token either. If you want to go even further then you could also restrict the token to only work from certain IP address(es).