Limit the server to only respond to HTTP requests made from an iOS app - without username and password - ios

I have an iOS app where the user can makes HTTP requests from their phones and the HTTP returns information based on the zip code that the user provides through the phone.
My issue is that anyone can type the URL and the server would respond with the information that corresponds to the zip code they input e.g. http://example.com/zip-code/78515.
My questions is, can I limit the server to only respond to requests made from my iOS app without the user having to create a user and password? In other words, if someone types http://example.com/zip-code/78515 directly in a browser I want the server to ignore the request but if the request comes from my iOS app I want the server to respond accordingly.
For the HTTP request I'm using Laravel.
Here is my Laravel code.
Route:
Route::get('zip-code/{zipCode}', 'AppsAPIController#information');
Controller:
class AppsAPIController extends Controller
{
public function information($zipCode)
{
$info = CityInfo::where('ZipCode', $zipCode)->get();
return ($info);
}
}
Request:
http://example.com/zip-code/78515
Again, the question is, how can I limit the server to only respond to requests made from my iOS app without the user having to create a username and password?

This package seems to do that
https://github.com/spinen/laravel-browser-filter
Basically, you are adding a middleware that reads the user agent out of the request, and denies the rest.

There is no foolproof way to respond only to requests made by your app.
User agent sniffing, navigator feature detection, and like measures may deter most basic attempts to load information from that url (like search engine bots), but anyone with a little time can learn to replicate the HTTP requests made by your app, defeating those measures.
Even requiring a login will not prevent external request (they can send requests matching your login workflow to obtain a valid token, then request the restricted url with it).

(via the comments) I just don’t want to overload the server with unnecessary requests.
In that case, there's a much better solution. Laravel ships with a throttle middleware, which you can use to limit the number of requests per minute per IP (or per logged-in user, if they're authenticated).
Just add throttle:60,1 to your route's middleware and it'll max out at 60 requests per minute for a particular IP address. Set it to something relatively high (so normal use doesn't hit it), but it'll prevent millions of requests from the same IP from using up too many resources.

Related

Microsoft safelinks unlock the user before page load

I m facing a weird issue with microsoft safe links. When we send user unlock emails, microsoft changes the urls with its safe links and when a user clicks the unlock link from email microsoft opens the page in background first for security reasons, user being unlocked and token becomes invalid. So it shows unlock token is invalid when the page loads but user is already unlocked.
Is there anyone had the same issue?
Thanks.
Modify your authentication endpoint to handle preview traffic without burning the auth code. The request from safelinks / Exchange Online Protection won't include the same headers as a normal client request; review the your logs from instances where safelinks burned an auth code to get a sense for the kinds of requests you can reject as unauthorized. Ensure your endpoint is not completing the auth flow for HEAD requests (meaning return a 405 if the request's HTTP method is HEAD); if safelinks is also making GET requests, something like validating the UserAgent header before proceeding with the auth flow should probably work. You don't provide any info about your link structure or auth strategy beyond it involving some form of single-use token exchange, but you should also check the IETF RFC to confirm you're properly adhering to whichever protocol you're using.
Additional thoughts:
The URLs in your emails should always be HTTPS links (not HTTP).
You may lack the email sender reputation for the emails to be presumed safe; read up on strategies for developing a sterling email sender reputation.
Your links may be presumed questionable/unsafe if the link's domain doesn't match the sender's domain.
It's not a great solution for polished product offerings, but try including a plaintext (not hyperlinked) version of the URL in the email; most modern email clients will notice it's a link and automatically hyperlink it for the end user, but safelinks is probably scanning the raw email body for defined href attributes. Their URL parsing has historically been pretty primitive and a lot of people get around it by finding something that confuses safelinks' matching strategy (e.g., https://halon.io/blog/fooled-microsofts-safe-link-technology).
Advise those users to add your domain to their permitlist ("whitelist") so safelinks will ignore your links.

iOS safely pass content between apps

I'm curious if there is a way to safely pass content between apps on iOS. The ultimate goal is to implement oauth between two ios apps.
Since apps are not guaranteed to have unique url schemes, this option is out.
I have considered using keychain groups, but do not have experience with this. It looks like an app needs to specify exactly which apps can access the keychain items.
Are there any other options? Is there some sort of identifier (such as android bundle ID) that can be used to verify the apps during a request?
You can use URL schemes for this.
The basic process
You'll have a ServerApp and many ClientApps. The ServerApp listens to an URL-scheme like serverapp://. The client then can make a call to the server to ask it for authentication. The client has to implement an URL-scheme too. E.g. ClientAppOne implements the URL scheme clientapp1://. The server takes as parameter a backlink to the client app. E.g. the client calls the URL serverapp://auth?back=clientapp1%3A%2F%2Fserverapp-auth (here the backlink is clientapp1://serverapp-auth and has been urlencoded).
The server then checks the users identity, asks him for permission, password, etc. and then uses the backlink to provide the data. How the backlink works exactly is application specific, but you usually need at least 2 parts: an access token and a username. E.g. a backlink will then be clientapp1://serverapp-auth?success=1&token=fi83ia8wfzi3s8fi8s3f8si8sf&user=robert or maybe in case of error clientapp1://serverapp-auth?success=0&errno=421. The client then needs to verify the accesstoken through some public (or private) API, e.g. https://serverapp.example.com/userdetails?apikey=fai83jw93fj93389j&token=fi83ia8wfzi3s8fi8s3f8si8sf. The server will return some structured response.
Necessary components
an URL scheme on the server App
an URL scheme on each client App
an SDK that is to be included into each client app and that handels the details of authentication, and a standard UI component (e.g. facebook has a standard button that says "login with facebook", so the ServerApp needs some re-recognizable button that says something like "login with ServerApp")
a server that provides services that can be accessed through the access token.
a defined API that explains how the client has to communicate with the server
an SDK to be included into the client that handels such client-server-communication (should be part of the SDK mentioned in component 3.)
maybe a wiki that documents all of the steps above, so that you and other developers dont lose track
a way to invalidate access tokens, and a way for the client to detect if an access token has been invalidated. furthermore, if the user changes his password, all access tokens should be invalidated.
Random notes
in your client app you can check if the serverapp is installed by calling [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"serverapp://auth"]].
the URL schemes should be sufficently collission-free. These URLs are never seen by users, only by developers, so they don't have to be beautiful. You can e.g. append the iTunes-Connect-App-ID to your URL-scheme, like serverapp1234567://. This will greatly reduce the possibility that someday some other app will use the same URL scheme.

Authenticate Username and Password iOS

I have a website that users can log into to see their account info.
I would like to build functionality into my iOS app that allows them to log in and see their info in the app. The usernames and passwords are stored in a SQL database.
How can I authenticate the username and password the user types into the app with the database?
If you have better atuthentication system in your web..
then i would prefer you to use the WEBVIEW for your login page. and continues the other using the normal app flow.
there are lot of tutorials for creating username and password login Function in IOS. i dont know whther you are basic or new progrmmer. But try this you may get some idea.
http://www.youtube.com/watch?v=HrZR2SyeoSk.
You can go with JSON serialisation, if you experienced to load data from server.
There are multiple ways you can go about this but at the end of the day you need an endpoint for your iOS application to talk to your web server. This can be done with a TCP connection (little more complicated) or with a RESTful HTTP API endpoint which is generally the way most developers will go.
To get you running up and quickly on the client side have a look at AFNetworking to do the heavy lifting on your HTTP requests. You will then need a URL on your website that the iOS application can query. Abstract things to keep your API on a different subdomain, say for instance by creating a subdomain to handle your API requests. A login example could look like this
http://api.mysite.com/login
For a PHP based REST API here is a tutorial for you, PHP API or you could use a Node.js framework such as Restify
The general practise is to use JSON encoded data when sending requests back and forth from the server, iOS 7 has built in JSON encoding/decoding, node and PHP also have pretty good support.
Once you are able to send and receive HTTP request from your iOS device to your web server it is just a matter of checking the username and password match up on the server side (seems you already know how to do this?) to the ones in your database and sending back a authentication BOOL and option error message if failed.

How to use Stripe Connect in an iOS app

Has anyone had success using Stripe connect with an iOS app. I have a few questions:
I'm following the guidelines here: https://stripe.com/docs/connect/getting-started
Registering an Application: easy, no problem here
Then a little further down:
Send your users to Stripe: again, easy no problem here, I just have a button that opens up the link in a UIWebView. I assume having the client_id in the URL is fine? A lot of my uncertainty is what IDs/keys I should hard-code into the app
Then a little further down:
After the user connects or creates a Stripe account, we'll redirect them back to the redirect_uri you set in yourapplication settings with a code parameter or an error.
What I'm doing here is using the UIWebview's webView:shouldStartLoadWithReqest:navigationType delegate method to check for the string "code=" in the URL. If it finds that, then I'm able to grab the "code" parameter. So in reality, the redirect_uri is completely unnecessary for me. Is this the right way to handle this? Should I be doing this within my app or on my server?
After receiving the code, we are supposed to make a POST call to receive an access_token. Again, should this be done within the app or on the Server? It requires the use of a secret_key, so I'm guessing server? And how do I send credit card information along with this token if the token needs to be sent to the server? I know how to obtain the card number, exp date, and CVV. But in terms of passing it to the server (with or without the token) is something I'm not sure of.
Then when it comes to actually writing PHP, Ruby, or Python code on the server, I'm at a total loss.
Any help would be greatly appreciated.
You should setup a small web app to create stripe charges and storing you customers Authorization Code. Configure two routes in your web app for redirect_uri and webhook_uri and add the url in your Stripe Apps settings. The charges should be created from a server side app because it requires the secret_key / authorization_code which should not be stored in an iPad app. Otherwise they may lead to a security leak. I'm trying to describe the concept below:
Provide the stripe connect button in your app and set the link to open in Safari (not in an web view). You should add a state parameter to the url with an id which is unique to your users.
On tapping the button your user will be redirected to Stripe where s/he will be asked to authorize your application. Upon authorization stripe will hit your redirect_uri with a authorization_code and the state you previously provided. Do a post call according to Stripe Documentation with the authorization_code to get an access_token. Store the access_token mapped with the state in a database.
Define a custom url scheme in your app. Invoke the custom url from your web app. The user supposed to open the url in mobile safari. So invoking the custom url will reopen your application. You can pass an additional parameter to indicate failure / success. In your app update the view based on this parameter.
Now you are all set to create a charge on your server on behalf of the iPad user. Use stripe iOS sdk to generate a card_token from the card information. It'll require your stripe publishable_key. Then define an api in your web app which takes 3 parameters: card_token, user_id and amount. Call this api from your iPad app whenever you want to create a charge. You can also encrypt this information with a key if you're worried about security using any standard encryption method. You can easily decrypt the info in your web app as you know the key.
When this api is called from the iPad app you'll receive the user_id (which you saved as state previously), card_token and amount. Retrieve the access_token mapped to the user_id (or state). You can then made a charge on behalf of the user using the access_token, card_token and amount.
You can use ruby / php / python / node in the server as Stripe provides sdk for them. I assume other languages can be used as well as there is a REST interface.
Please note that this is just a concept. It should work like it but I haven't implemented it yet. I'll update this answer with sample code when I'm done.
You can use UIWebView. You will still need to use redirect urls and monitor the redirect using the delegate "webView:shouldStartLoadWithRequest:navigationType:"

How to test the twitter API locally?

I'm trying to write a web application that would use Twitter via OAuth.
I run my local server as 'localhost', so I need the callback URL to be something like http://localhost/something/twitter.do but Twitter doesn't like that: Not a valid URL format
I'm probably going to do a lot of tests, but once I've approved my app with my username, I can't test again can I? Am I supposed to create multiple twitter accounts? Or can you remove an app and do it again?
You can use 127.0.0.1 instead of localhost.
You can authorize your app as many times as you like from the same twitter account without the necessity to revoke it. However, the authenticate action will only prompt for Allow/Deny once and all subsequent authenticate requests will just pass through until you revoke the privilege.
Twitter's "rate limiting" for API GET calls is based on IP address of the caller. So, you can test your app from your server, using the same IP address, and get (once approved) 15,000 API calls per hour. That means you can pound on your app with many different usernames, as long as your approved IP address remains the same.
When you send the e-mail to Twitter to ask for an increase to your rate limit, you can also ask for the increase to apply to your Twitter username too.
I believe Twitter requires you - if you need to change your IP address, or change the username that is using the app - to send in another request asking for the rate limit increase for that new IP address or username. But, in my experience, Twitter has been pretty quick at turning around these requests (maybe less than 48 hours?).
use like this
for Website :http://127.0.0.1
and for callback URL: http://127.0.0.1/home
or any of your page address like http://127.0.0.1/index
Have you tried creating your own caching mechanism? You can take the result of an initial query, cache it on thread local, and given an expiration time, refresh from Twitter. This would allow you to test your app against Twitter data without incurring call penalties.
There is also another solution (a workaround, rather) which requires you to edit your hosts file.
Here is how you do it on a linux box:
Open your /etc/hosts file as root. To do this, you can open a terminal and type something like sudo vi /etc/hosts.
Pick a non-existent domain to use as your local address, and add it to your hosts file. For example, you will need to add something similar to the following at the end.
127.0.0.1 localhost.cep # this domain name was accepted.
So, that's pretty much it. Pointing your browser to localhost.cep will now take you to your local server. Hope that helped :)
In answer to (1), see this thread, in particular episod's replies: https://dev.twitter.com/discussions/5749
It doesn't matter what callback URL you put in your app's management page on dev.twitter.com (as long as you don't use localhost). You provide the 'real' callback URL as part of your request for an OAuth token.
1.) Don't use localhost. That's not helpful. Why not stand up another server instance or get a testing vm slice from slicehost?
2.) You probably want a bunch of different user accounts and a couple different OAuth key/secret credentials for testing.
You were on the right track though: DO test revoking the app's credentials via your twitter account's connections setting. That should happen gracefully. You might want to store a status value alongside the access token information, so you can mark tokens as revoked.

Resources