How to authenticate REST API with Stormpath Facebook integration - facebook

I am designing a simple REST API with Stormpath Facebook integration and wondering what would be the best pattern for user authentication. Currently I do not have any endpoint for user creation, so all requests to my endpoints are authenticated like this:
Get Stormpath Application object based on API_ID and API_SECRET configured in my app
Get Stormpath Account object based on Facebook token specified in every request
Based on account status authenticate request or reject
This follows more or less official guide and works fine because even though user account does not exist it will be created upon first get account request to Stormpath. Does it make sense and is it safe enough? I was looking for some documentation or best practices but could not find anything.
I would also need to get / generate unique user ID so I can make some relations with user data in my system - so another question, what is the best approach here:
Generate some unique ID, associate it with user email got from Stormpath and save in my system - I think this violates a little bit idea of such a service like Stormapth which encapsulates all user data
Do the same as above but store it in Stormpath Account customData
Use Stormapth user resource ID which can be obtained from user URI
Please advice.
Just for the record I am using Stormpath Java SDK and designing the API to be a backend for mobile social app so security is quite important for me.

Full disclosure, I manage Product # Stormpath. I'll be using your feedback to enhance the documentation.
It is hard to say if it is safe or not, without understanding the REST API you are building. If you made a REST API for cat pictures, my answer would be different compared to medical / financial information. One way to look at it, is that Facebook has the Graph API (REST) and they protect access requiring the same access token you are using. There are other flags that would cause me to say it isn't safe, like if you were using HTTP with no TLS.
To your second question, how to link Stormpath with your data. I wouldn't say you would violate anything about Stormpath by modeling out your application that makes sense to you and your app. Stormpath has customers that store EVERYTHING about their users in Stormpath. Stormpath also has customers that use Stormpath solely for authentication and authorization data and use customData to draw the link between a Stormpath user account and their data.
How / where you store the information is based on your needs. If you are starting with authenticating the user account with Stormpath, it would make sense to put the unique identifier / primary key in the user account's customData. If you are starting with querying your data store for the user data and need to get the Stormpath user account, then you will need to store the href for the user account in your data store.
A nice feature in the Stormpath SDK for Java is that when you do authenticate with Facebook, the returned object will disclose if the account was newly created or if Stormpath has existing account for the access token:
https://docs.stormpath.com/java/apidocs/com/stormpath/sdk/provider/ProviderAccountResult.html
This means that you will know when you need to create a record for the account in your data store and connect the two using customData and/or the user account href.

Related

Securing an API called by the end users of a client

I am building an API meant to be sold to various clients. These clients will be given an API Key or something similar and they'll use the API in a widget on their website.
The end users of the clients' website must be able to use the widget anonymously (no login).
Workflow:
My current idea is to have the Client's server retrieve a temporary key and use that in the webpage. The End user's browser will use that temporary key to call our API.
Is there any reason why this is not a good practice and/or insecure?
Or is there a better good practice solution? Can I for exmaple use OAuth 2 for this?
You need to secure your API from the clients app. So, for that you can use OAuth 2 with Client Credentials grant type and setup each client as an app so they each get their own set of key/secret credentials.
Since you don't know anything about the end user, but still need to track them, require an endUserId custom header on every request to your API and you'll just have to trust the client to provide you with a valid id for the end user making the request.
To setup OAuth, use an existing library or OAuth service. I don't recommend writing your own. If you can spend some money, Okta and Auth0 are good choices. If your API is written in .net, you can use IdentityServer as a free option.

Forcing external apps to use the API

I have a website allowing authenticated users to submit and edit data. I also want to offer a REST API as part of a chargeable service.
Now the problem is that a non-paying user could theoretically use the same calls my website uses as API for authentication and sending data from his external application since it is very easy in the browser to see the endpoint what and how exactly the data is being sent to a website.
How can I protect my website from such usage and force the user to use API for external access?
Actually you cannot prevent people making requests to a public API. You can just validate the user when a request arrives. So there are more than one approach to solve this problem.
I would provide a token per session for each user and validate the rest API request at back-end.
Use OAuth2. So you will give paid user secret id and key then they will ask for the access token to access the API's using secret id and key.
Read about public/private key encryption https://en.wikipedia.org/wiki/Public-key_cryptography
Read about oAuth
https://oauth.net/2/
I have used passport to implement oAuth2 in laravel. passport is oAuth2 implementation and available in other languages also.

General API security tips and info on how tokens work

So I want to understand a little more about authentication in an API. I know very little about how security works.
I am using Auth0 for my app and it supports only logging in from a social media site. My API checks if a user is authenticated and checks data that is being sent to avoid wrong stuff to be saved in the database(mongodb). That is all I have currently implemented to secure my API. Is it possible that a user can take his own token that he got from logging in and post information to a different account by simply guessing a different user _id.
For example, an article receives all its content and the id of the article author.
If this is possible what are some solutions on securing my API.
Any other tips on making an API secure are appreciated!
Auth0 supports logins with anything , not just social networks. You can login with username/passwords, LDAP servers, SAML servers, etc.
A token is a secure artifact. An author cannot change the id in a token without compromising the token itself (e.g. the digital signature will fail), so impersonating someone else is not that easy. The very first thing your API would need to do is checking the integrity of the token being added to the request, and reject any that contains an invalid one (bad signature, expired, etc).
It is a question that requires a lot of content, so I would recommend starting here: https://auth0.com/docs/api-auth

IdentityServer 3 securing webAPI with User Informatioin

We have a need to secure our .net web api using open id and OAuth standards. IdentityServer 3 is perfect for us as we have to use our existing user store.
Edited for more clarity:
Our company services multiple customers. Each of our customers have their own database. In our home grown client application when a customer user enters their user/password, we do a lookup to authenticate and that also determines what backend database the app connects to.
We now have a need to allow a couple of trusted partners to access our database resource for specific needs. We have created a web api for them to make specific calls. The web api needs to know what customer the partner is making the call for. The partner is calling the api from services on their side so there is no user interaction.
I am trying to determine the flow to use to accomplish this. I found some pretty good info on flows at https://gist.github.com/jawadatgithub/638c11f08ecc0d76b05c.
If I define the client using the Client Credentials flow, I don't know how for them to pass the customer they are making the calls on behalf of. I don't think we want to definate a "Client" for every partner/customer combination, but is this the correct way?
What we had thought of initially is to give an additional user/password or secret key that would tell us the customer, but I am not sure what "flow" for the client would allow this.
Any help or direction would be greatly appreciated.
In case this helps anyone else, we decided to go with a Hybrid flow for these types of requests. We considered designating a service account (user/pw) for each of our customer databases that would give this trusted 3rd part access to them by requesting tokens with the Resource Owner Password Credential flow, but decided against it. We decided against it for all the reasons the standards say not to use it for this use.
If the 3rd party wants to interact with us on the behalf of one of our customers, then they will need to build the UI on their side to redirect to us for user/pw authentication and consent.

Possible approach to secure a Rest API endpoints using Facebook OAuth

I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.