How does Instagram lock down their photo upload private API endpoint? - security

I'm in the process of building a REST API for a mobile application I'm working on. Like Instagram, I'm considering locking down some of the endpoints such that they would only be accessible from my mobile app (like their photo upload endpoints).
Has anyone have any insight as to how they locked down certain endpoints to only their app? I imagine a possible solution was the use of a shared secret to sign these specific requests and have it verified server-side before processing the upload.

It looks like they
Check the request header for User-Agent == "Instagram"
Check that there is a valid authentication cookie set
Sign the body of their requests with some sort of hash.
I'm not sure how the hash is created.
Check this out for some of the documentation, but it looks like the authentication section has been blanked out.
https://github.com/mislav/instagram/wiki

Related

Is it possible to re-initialize google authentiation middleware with options before calling challenge in AuthenticationManager

I am developing an application with social logins enabled. My customers will signin using google / facebook etc...
Each customer has a separate uri to login to my application. I can get their client id and secret for google authentication. In case the values are available, can I set those values before making a request to the google auth server. I would like the customers to pay for the API requests based on their usage.
I find that in the handler, the data set in the startup middleware options are used to construct the URI. Is there any way for me to change the client id and secret before making a request to google URI for each customer.
By Default, there is no support for multi-tenancy. Hence, I have coded my own middleware that is highly configurable and solved this issue.

nodejs - private REST API

I have created a simple REST api for my application using node/ express. I am using AngularJS on the front end to serve pages to the user.
I would like to add functionality such that the API can only be accessed via my front-end and anyone should not be able to do a GET/POST request to my site and get the data?
What strategies can I use to achieve this?
HTTP request can be formatted and sent to sever by many other means beside a browser (curl for example), so any server always detecting correct source of a request is not guaranteed.
The basic method to protect an endpoint would be to use some kind of authentication. The requesting client must present something uniquely identifying it. API should provide clients a token after it proves itself authentic (via login etc), and all subsequent requests would be checked for this token.

Self Hosted Web API Authentication

I have a self hosted Web API running, which using DotNetOpenAuth to issue authorization tokens. Basically, the project consists of 2 ApiController endpoints (Authorize and Token). I would like to force the client to have to log in to a form, prior to being able to call either endpoint. (Forms Authentication I guess). However, doesn't seem like it works for self hosted Web API projects, so, I am trying to implement something myself.
As of now, when the user calls the Authorize web get method, I render the login page and force them to login. However, I would like to have a mechanism in place so that once the user logs in, I can send a cookie response. I understand that if you write the cookie in the response, the browser will automatically send any relevant cookies upon subsequent requests.
However, my test client uses a HttpWebRequest to call my web api. Do I have to build the mechanism to save the response cookie to a file on the hard disk, and then, read it back, and associate with the HttpWebRequest on subsequent requests? Or , is there something built into the framework which I can leverage (just like how a browser would automatically take care of this for me).
I figured that once I could figure this part out, I could just extend the AuthorizationFilterAttribute, and use that to check the validity of the incoming cookie.
Thanks. Any help or suggestion is appreciated!

Firebase Authentication in a Chrome Extension Background Page

How would I authenticate with Firebase in a chrome extension? I need to specify the allowed domain list in the Forge. Chrome domain for the extension is just a big hash-like string.
I did read this: authClient.login problems
But the hashed based domain of a chrome extension is not being accepted in the Firebase forge. Is there another way to go about it? Currently am just reading the cookie firebaseSessionKey to just assume that I am logged in. But surely that can't be as secure as letting Firebase validate this session key.
As Rob points out, authentication cannot work in an environment that does not enforce origin restrictions. The fundamental problem here is that any authentication provider (Facebook, Twitter, Persona, or your own service) cannot issue an identity to a browser - i.e. it is meaningless to use Facebook to login to your browser (or extension).
The F1 add-on for Firefox ran into a similar problem (http://f1.mozillamessaging.com/) - where you would authorize F1 to post on twitter/facebook on your behalf. The extension had a website to along with it, from where you would serve the login page and proceed as you would normally in a web page. You'll need some code to communicate between the web page and your extension, chrome provides the tools necessary.
I would recommend the same approach - create a web page on a real domain (Github pages is awesome for this) to go along with your extension. This means your extension can't work offline, but neither can your login or writing to Firebase!
This will work using Google Plus Login Flow which I believe is the only one that allows cross authentication so the scopes are Google Plus Login.
"www[dot]googleapis[dot]com/auth/plus.login"
So what is happening here is you will get the access_token from the extension which you will be sending to firebase with the request using authwihtoauthtoken specifying google as a provider along with the access_token acquired from chrome.identity.getAuthToken()!
https://www.firebase.com/docs/web/api/firebase/authwithoauthtoken.html
Now the fact is that this access token could be issued by any other app, so we need to make sure that it is valid and has been issued for our app, basically we need to know there isn't man in the middle trying to access our database.
This verification is being made by the firebase.
They will check if this token belongs to the same application as the token has been issued to.
So you will need to create another set of credentials under the same application in the google developers console as for your extension. We will be basically doing the same thing as if we were to do it for our webpage but we will be inserting this new set of credentials to firebase's google oAuth in their security section.
They will do this check for us there. They will verify with google if the token is issued to the same app.
That's it.
Background Information.
https://developers.google.com/identity/protocols/OAuth2UserAgent#validatetoken
Use case
Sending ID tokens with requests that need to be authenticated. For example, if you need to pass data to your server and you want to ensure that particular data came from a specific user.
When to verify the access
All tokens need to be verified on your server unless you know that they came directly from Google. Any token that you receive from your client apps must be verified.
Google has a tutorial how to do this for python found at:
"github[dot]com/googleplus/gplus-verifytoken-python"
So basically what is happening here is; instead you doing to verification from on your server, firebase does this verification for you when you enter the CLIENT_ID and APP_SECRET into the firebase and enable the Google Authentication.
The way to do this correctly is a combination or same style of verifying to whom the client_secret was issued. Chrome will give you a access_token and then this access_token will be checked on the firebase's backend.

The "right" way to do oAuth from a mobile client

I am building a cross platform mobile application (using the Xamarian tools, MonoTouch / MonoDroid). I am trying to work through the authentication workflow and am running into a stumbling block. I have searched all over for a clear answer and have yet to find it.
Here is an overview of my current setup.
I have a web site built in nodejs.
I use passport.js to do oAuth login on the web site. This works great, users can login to my site using Twitter or Facebook.
Now I want to extend this same login functionality to my mobile clients.
I see 2 options
Embed the app id and app secret's in the mobile clients and make direct oAuth calls to FB or Twitter from the mobile app
Proxy the oAuth calls through my existing nodejs web server (keeping the secret keys on the server)
Option 2 appears to be the preferred way (as it avoids having to "ship" the secret in the mobile apps).
I have the proxy approach mostly working.
I open a WebView in my mobile client and point it at http://mysever/auth/twitter
This runs through my existing passport.js code and redirects the mobile WebView over to the Twitter login page.
The user then enters their creds on the twitter webpage on the device.
Twitter then calls my oAuth callback URL (which is my nodejs web server).
My server and Twitter handle the back a fourth handshake of obtaining the user profile information (As I understand it, this is the key to this approach, my server and twitter handle the handshake, the mobile client doesn't have to do anything or pass any tokens during this process)
Here is my problem:
It is this last step that stumps me. Once the handshake is complete on my server I have the user information I need on the server and need to send it back to the mobile client application
I can't figure out any way in the WebView control to grab the response object and grab a cookie, or header value (for instance) (this seems true for Android and iOS). I don't think it is platform specific. I think I am trying to do something that a WebView widget in mobile platforms just don't suport. It makes me think I am missing something obvious.
The only thing I have figured out is to have my web server "redirect" the mobile client browser to a fake URL that has the user info in the querystring. Something like myapp://info?userid=1234
Then in the mobile app I can hijack the URL loading and grab this url and get the data I need. I can then stash this userinfo, close the WebView control and move on to a native screen in my mobile application and user the userinfo in any subsequent REST calls to my nodejs server as a means of identifying the user.
This is massively kludgy for multiple reasons. The biggest of which is that the url is sent over the wire unencrypted and has all the data in plain text.
There has to be a better way to get the data from the web server back to the mobile client?
Or am I doing it all wrong?
The most straightforward way to implement oauth for Xamarin, both for iOS and Android, is using Xamarin.Auth. The starter documentation for the client is here. I think it should maintain everything securely and you will not have to worry about having to use your node server as a proxy.
You will need to provide your Application ID as part of the calls, but I don't there are too many or any security issues to worry about there.
I know this is going against what you already have implemented, but maybe this could help simplify things a bit.
This is the same dilemma that I have been dealing with.
This is how I currently deal with it.
In my app the client can come directly or via another service such as facebook which is my main one and hence the one which I have concentrated on.
Facebook can either redirect via a POST (desk apps) or a GET (mobile).
I check the initial request so see if has a service identifier - here is the facebook GET for example.
app.get('/', function(req, res) {
var paraUrl = URL.parse(req.url,true).query;
//The fb_source is shown -
//i need to go striaght to the facebook authorization since
//its coming from
//from a mobile device.
if (paraUrl.fb_source){
res.redirect('/auth/facebook'); //this is the passport part
return;
}
res.sendfile('index.html');
}
The facebook POST is slightly different in that you get an access token encode in base64url. The GET gives you a code which you can exchange for an access token but I had problems with it and just opted for tying into the passport system.
If a client comes direct I check for the session or a encrypted cookie which ties into the local strategy. This then checks the db for an access token which can used to access the facebook api for example.
If a client is unrecognised they are given the option to authenticate via facebook, google etc.
The main thing is that only 2 pieces of information are stored with the client, the passport session id and my app user id
connect.sid - encypted cookie
userId - encypted cookie
I would be interested to find out how other people are dealing with issue

Resources