RESTful Device specific Authentication of Phone Number - rest

We have an API that sends a verification code to user's mobile number. The API is:
POST /api/users/verification/start/
{
"mobile": "9849735434"
}
The above API returns following response:
{
"isVerified": false
}
If the response is "isVerified": true, we don't send a verification code to user's mobile. If it is false, we send a code.
Currently, all this works on the just mobile number. We want to make it based on (mobile + device) to make it more secure.
To achieve this, we store a user-identification cookie on the client machine and we are planning to identify the device on basis of that. How should API be modified for this new requirement? Few approaches:
Create different API that works on basis of (mobile + cookie) and sends isVerified: true only if both matches with the value stored in our database.
Modify existing API to achieve this - Since this support for device-specific OTP is not required always, we will have to pass some flag to make it only mobile-based OR (mobile and cookie).
How should we design such API to verify users based on mobile and device?

Hope this would help you, you can modify code and follow some client and server steps.
CLIENT SIDE
Step 1.
Get mobile no and country from user
GET UUID from user device. ( UUID :Is Secure.ANDROID_ID unique for each device?)
Hit Own Api with this params.
SERVER SIDE
Step 2.
Get Validate it, is this mobile no is Valid https://github.com/googlei18n/libphonenumber (we can do it from Client side too)
Step 3.
Generate OTP between 0001 - 9999 or more
Send OTP api call to send on Mobile no as per OTP service provider’s API.
Save OTP no into database along with Mobile no And UUID.
CLIENT SIDE
Step 4.
get mobile no and OTP and hit api
check OTP from DB same OTP then response success else Wrong OTP message you can send.

There are different options.
When you want to use cookies, why do you need a separate API at all? If the client has a cookie, let the client send this cookie as a cookie. Your service can analyze the cookie when needed and decide about further steps.
If you cannot send cookies and the 1st approach is not an option to you:
Device should not know, what type is it from the point of view of your service. That is why I'd suggest to use two services - one without cookies and one with cookies.
You say "RESTful". In the current form your service is not RESTful.
A) Using verbs makes the service NOT RESTful. Rename it for instance to
"POST /api/users/verification/"
B) Two operations are mixed within a single one: Check if client is authenticated and starting authentication process. Split it into two:
To check if the client is authenticated:
"GET /api/users/verification/mobile/9849735434"
To start authentication:
"POST /api/users/verification/mobile/9849735434"
For the POST you don't need a body in this case.

I would modify the existing API to fit the new requirement and here is the important thing I would do while modifying.
Whenever you create any API always have a "version" passed from the client this way you would know which section of the code to execute.
e.g Assume your mobile users have 2 different version of the app, once before this release another after. To have both the user running versioning is helpful.
Pass "Device Type" from client to check whether the client is mobile/tab or other, this will have multiple advantages firstly you will know how much user base is in phone/web, another advantage is you can customize the output size accordingly as web will have more information compared to the mobile app.
Now that you have device and version information you just have to write condition in your existing API. Once you feel there is no old version usage we can retire that portion of API.

Related

Questions on making a web API with sessions

I am attempting to make a website's back-end API (I want to make the back-end independent of the front-end so I'm only making a server-side API for now, abiding to RESTfulness as much as possible). I haven't done this before so I'm unaware of the 'best' & most secure way to do things.
How I do it now:
Some parts of the API should only be accessible to a specific user after they login and up to 24 hours later.
To do this, I am generating a random Session ID whenever a user logs in (I'm using passwordless logins so the user is assigned that ID when they click on a link in their email) on the server side, which respond by sending that session ID to the client once. The client then stores this session ID in localstorage (or a file in disk if the client is not a web browser).
Next, I store that ID along with the associated email in my DB (MySQL table) on the server side.
Now every time the client want something from my API, they have to provide the email & session ID in the URL (I don't want cookies for now), which the server checks against the ones in the DB, if they exist then the server responds fully else responds with an error.
After 24 hours, the server deletes the email/session ID pair and the user has to login again (to generate another session ID and associate it with their email).
Now the questions:
Is my method secure or does it have obvious vulnerabilities? Is
there another battle-tested way I'm not aware of?
Is there a better way for the client to store the session ID (if
they are a web browser)?
What is the best way to generate a unique session ID? Currently I
generate a random 16-char string that I set as the primary key of
the session-email table.
Is using a MySQL table the most performant/best way to store session
IDs (given it will be queried with each request)?
Do I need to encrypt session IDs in any way? Is it secure for the
client to send it as a 'naked' URL param?
Sorry for having too many questions in one post but I think they're related by the single scenario above. If it makes any difference, I'm using F# and I expect my client to either be an android app or a web app.
Your REST API MUST not know anything about the REST client session, not even the session id. If you don't want to send a password by every request, all you can do is signing the user id, and the timeout, so the service can authenticate based on the signature. Use JSON web token: https://en.wikipedia.org/wiki/JSON_Web_Token
You can have a server side REST client, which can have the session your described. The question is, does it really worth the effort to develop a REST service instead of a regular web application? I am not sure in your case, but typically the answer is no, because you won't have any 3rd party REST client and your application does not have enough traffic to justify the layered architecture or it is not big enough to split into multiple processes, etc...
If security is important then you MUST use a true random generator algorithm or hardware. https://en.wikipedia.org/wiki/Random_number_generation#.22True.22_vs._pseudo-random_numbers It is not safe to send anything through HTTP, you must use HTTPS instead. You MUST use the standard Authorization header instead of a query param. https://en.wikipedia.org/wiki/Basic_access_authentication

Authenticating calls from Phonegap app to REST server

I'm building an app with Phonegap. It simply reads xml feeds to display latest articles uploaded by a school for parents to read.
There will be an option where each user of the app can decide whether they want to receive Push Notifications or not. I have a simple database table where the device's registration i.d. from Google Cloud Console is stored. When the user clicks "yes", the registration i.d. is generated and stored on the server. If they then click "no", it's deleted. I want to secure these call to the server with basic HTTP authentification.
Any documentation I have seen on basic authentification describes the sending of username and passwords. But with my application, there is no username or password as the users do not need to sign up. What do I send to authenticate the client? Would there be a key hard-coded on the client side and sent with each request? Couln't this be easily exposed by unpacking the .apk?
I object to the premise of the question. I actually see this as less a security issue and more a preferences issue. Understanding the distinction makes the development of your feature much easier.
Simply modify your application to allow the user to configure what he or she wants to see in the settings and then store the preferences wherever you want on the client (like local storage). The server can then push as before, but the app should simply refuse to render those pushes that the user doesn't want to see.
If you want to simply disseminate non-sensitive content to the users who want to see it, this is a preferences issue and/or a publish/subscribe issue. But it is not a security issue.
Since you have access to server side, you have the control of the whole process. So, in order to handle that, you may think about something like session cookies that a web server creates in case of normal authentication.
I have done something similar and what I've done is to generate a kind of token server side that is stored in the cookies of the device or the localStorage.
So the process flow should be something like this :
Generate a token and store it on the device (cookies or local storage).
For each request, send this value in a http header
From server side, you may identify the user from that token.
For example : you maintain a table that identifies device/token.
That's it
In addition to what the other answers said you can pass a custom useragent string as part of the requests, and validate it matches what you expect. It's not a sure way to 'secure' requests, but along with a (simple) token system and HTTPS this could be enough for your needs.

FOSOAuthServerBundle Create Client

I'm currently trying to setup FOSOAuthServerBundle with my Symfony2 app.
Everything seems to be setup and functional, anyway I'm stuck after the installation.
What is the proper workflow with URLs to get the access_token ?
I tried /oauth/v2/auth, but sounds like I need to define a Client object first.
How to create/generate Client ? Clients are always supposed to be created manually ?
FOSOAuthServerBundle doc is great, but seems to skip all the usage workflow. Am I supposed to check the OAuth2 doc for this ?
Thanks !
In short, yes. You should be using the oAuth2 RFC to determine which workflow you want to use. In regards to client registration the RFC specifically states that the means through which a client registers is beyond the scope of the specification (https://www.rfc-editor.org/rfc/rfc6749#section-2).
With that being said I can give you some insight into how I did this. My application is a mobile phone application that connects to several services running on various servers. I'm also using the Resource Owner Password Credentials Grant.
The way I approached this was: when the application loads, the first thing it does is to check if it has an oAuth2 client id. If it doesn't, then it POSTS to a create client endpoint I've setted up with the meta-data I need. The endpoint validates the POST, creates the client and returns the client information. The application stores the client id and the process doesn't have to be repeated the next time.
Application loads;
Application checks for oAuth2 client id;
If there is one, the process ends;
If there isn't, it posts to http://www.example.com/client;
If we get a 200, store the oAuth2 client id.
I could have also created the oAuth2 client when the user created an account in the application, but I wanted to make the registration process as fast as possible. Creating the client would have added some extra waiting time to the process.
Check this: http://blog.logicexception.com/2012/04/securing-syfmony2-rest-service-wiith.html
It's quite simple to convert to Doctrine, whether you use it.
There's a command-line that does exactly what you need: create a Client!

How to secure Rest Based API?

We intend to develop rest based api. I explored the topic but it seems, you can secure api when your client is an app (So there are many ways, public key - private key etc). What about websites / mobile website, if we are accessing rest based api in website which do not use any login for accessing contents ( login would be optional ) then how could we restrict other people from accessing rest based api ?
Does it make sense using Oauth2.0 ? I don't have clear idea of that.
More clear question could be ,How can we secure get or post request exposed over web for the website which doesn't use any login ?
If it's simple get request or post request , which will return you json data on specific input, now i have mobile website , who will access those data using get request or post request to fetch data. Well, some else can also access it , problem is i am not using Login, user can access data directly. But how can we restrict other people from accessing that data.
What do you think is the difference between securing a website that is not using REST vs one that is using REST API?
OAuth provides authorisation capabilities for your site, in a REST architecture this means a user of the mobile application will have to provide their credentials before being allowed to access the resource. The application can then decide on if that user has access to the requested resource. However you've said your website doesn't need use authorisation.
You can use certificates however good luck managing the certificate for each client. My take on it is for your explanation you don't need to secure your website because you will never be able to manage a trust relationship between the client and the server. There are some options though:
You build your own client application that you ship out to people which can verify itself with the server using a packaged certificate with the client. E.g. iOS has this kind of feature if you build for that device.
You provide a capability to download a certificate that is 'installed' in the browser and used when communicating to your REST API
Use something like a handshaking protocol so when a client wants to make the first request it says; 'hi I'm a client can we chat?' And the server responds with 'yes for the next X minutes we can however make sure you send me this key everytime you tell me something YYYYYY' (you can use something like SecureUDID or equivalent for other devices than iOS).
There are probably others but you get the basic idea. Again in my opinion if your resource doesn't need authorisation then you don't need to secure that REST API. Can I ask what kind of data are you exposing via this REST API or functionality your providing? That might help provide a better answer.
You want authorization: only some agents (mobile clients) and/or users should be allowed to access those APIs.
To solve that problem, you need identification: a way for the server to tell who is who (or what), so the right decision can be made.
There are many different way to provide some form of identification, depending how much you care about security.
The simplest is a user agent string, specific to your mobile clients. But it can be faked easily. Slightly harder to fake are client based 'secrets' - embed some kind of secret or key in your mobile client code. You can make it really complicated and secret, but as ramsinb pointed out, you can't get security this way as it would require you to be able to guarantee that the secret you're shipping with the client (wether it's code, algorithm or any other fancy construct) can't be compromised or reverse engineered. Not happening when you don't control the client.
From there, 3 choices:
Security isn't really required, don't bother
Security isn't really required, but you still want to limit access to your API to either legit users/agents or people ready to invest some time hacking your protection - go with a specific user agent or a client embedded secret - don't invest much into it as it won't block people who really want access to get it anyway
Security IS required - and then I don't think there is a way around authentication, wether it's login/password, user specific (device specific?) keys, OpenID, etc... No matter what, you'll have to add to the user burden to some extent, although you can limit that burden by allowing authentication to persist (cookies, storage....)

How to ensure/determine that a post is coming from an specific application running on an iPhone/iTouch?

Building an iPhone OS application that will allow users to anonymously post information to a web application (in my particular case it will be a Rails based site) ... and I want to ensure that I only accept posts that originate from a specific application running on an iPhone/iTouch.
How is this best accomplished?
(btw, if your answer applies to Android please feel free to post it here as well as I'm curious to know if the techniques are the same or vary).
Thanks
The best way would be to implement a known call and response pattern. Send a value of some sort (integer, string, hash of a timestamp) to the iPhone/iTouch application. Have the application modify this information in a known way and send it back for verification. Then all you have to do is use a different modification algorithm per-platform and that will verify what type of device is being used.
VERY simple example:
Server sends 100 with the response to an iPhone.
iPhone adds 10 to this value and sends back with request.
Server detects the value was increased by 10 and now knows it was from an iPhone.
Then on your Android clients add 20 and on another platform add 30 and so on...
You could also add a hidden field in the form. or in the data being passed up if it is XML or other format
Encrypt or sign something using the public key of a key pair, then decrypt or verify it on the server with the private key. Ultimately, anything that can be sent can be duplicated, be it a spoofed html header or an encrypted block. The app has to know the secret handshake, and anyone with access to it (and sufficient technical skills) can figure out the secret handshake.
I would suggest the following approach.
Build an ssl enabled access to your rails app.
Now create a user account for every plattform you want to use and enable your applications to log in with the correct key. If you use the ssl standard in a correct way there shouldn't be a way to sniff the password and you can use standard components on the rail and the phone side of your app.
You then need to secure the login credentials on your phone with the appropriate technics. Eg. put it in the keychain on the Iphone.