I am trying to integrate third-party (TP) APIs (https://api.icicidirect.com/apiuser/ICICIDirectAPIDOC.htm) in my react/node.js app. The APIs use OAuth 2 for authentication and after authentication.
The sequence of actions is something like this - a user clicks on the TP image on my react app and gets redirected to the TP's login page. After authentication, TP does a redirect with a form post. Based on my current understanding, only the backend server can host a post method where the TP can post the form. From here, it is not clear how to trigger the react app to detect that the user has logged in and render their dashboard.
I have two questions:
Assuming I register a frontend URL as the redirect URL, is there a way I can capture this form post on the frontend?
If #1 is not possible, what's the most elegant way of letting the frontend know that the login was successful, after receiving the redirect on the backend?
I would check a couple of things since it seems your app needs to use OAuth tokens as well as to sign in:
Is PKCE used and / or a client secret? This will determine whether you can complete the login in the browser and swap the code for tokens.
Can you add a response_mode=query query parameter when you trigger the redirect, which will make the response a GET (if the provider supports it).
Q1
The usual solution is to return the authorization result on this type of URL, which is SPA friendly. The browser cannot receive POST requests.
GET https://www.example.com?code=xxx&state=yyy
The SPA can then perform one of these actions and get tokens:
Exchange the code for tokens if PKCE (a runtime secret) is used
Otherwise proxy the request via an API, which attaches the client secret
Q2
If the provider only supports POST responses you can can write a small amount of code in the web host (as a workaround) when it serves the index.html page. This could check whether it is a login response, and if so trigger a redirect with the above query parameters.
WEB HOST RESPONSE PROCESSING
Do the login response processing and code exchange in the web host, then redirect the SPA to a location such as https://www.example.com/loggedin, which will notify the SPA so that it can update its UI state.
ALTERNATIVE OPTION: OUT OF INTEREST
The above could require quite a bit of code in the web host, which could potentially impact your web deployment options, eg if you wanted to serve web static content from a Content Delivery Network.
So another option the web host could use is to just perform a redirect to https://www.example.com?code=xxx&state=yyy. The SPA could then call an API to complete the OAuth processing. This requires more security due diligence (eg ensure that PKCE is used), but is how a Back End for Front End SPA solution would work.
I'm new to Python, but have previous experience writing .Net web apps.
I'm working on a website written in Python using Flask-WTF (html pages with forms and individual routes for GET and POST requests). The app makes calls against a Python Flask API that talks to a MySQL db for user authentication (user table with names and hashed passwords). Everything the user sees is handled by the web app UI, and all the logic is handled by the API.
I followed Miguel's Mega-Tutorial (https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) to learn the basics of the Python language and how to solve a number of problems along the way.
I need my users to log in once a day (set tokens to expire every 12-24 hours or so), but then have access to the app to perform whatever actions they need. I have a Login form that grabs username/password and submits that to an API endpoint. The API verifies the user data against the db, generates JWTs (access and refresh tokens), and writes them to cookies in the response. I am able to see that the cookies are set in the web app after the initial login and verified the contents using https://jwt.io. The only thing I need from the user login after verification is the username for when a user makes a change to database entries.
The Problem: How do I actually use the info in the cookies to call subsequent #jwt_protected methods in the API? When I add the #jwt_required to a post(self) function and try to access it I'm getting back a 401 with { "msg": "Missing cookie "access_token_cookie"" } that appears to be coming from the jwt_flask_extended library. I used "access_token_cookie" as the name of the cookie for the JWT token. Are the tokens magically handled by FlaskWTF/flask_jwt_extended and I'm just using it wrong? Do I need take the info out of the cookie and add it as a header on subsequent requests? If I send the info in a header, how does the API know where to look? I have a feeling it's something minor where I'm just not connecting the obvious dots.
I'll create a standalone app to test out just the authentication features between UIs and APIs that can be shared as opposed to trying to rip out existing code minimize the existing app and api to the bare minimums in case anybody else comes across a similar problem. This might also show me what my problem really is.
The final version of the app and api will both be hosted in a Cloudfoundry environment in case that has any bearing on suggestions.
I have a rather conceptual question, I'm sure it's fairly stupid, but I can't figure it out.
So I am building a simple node.js app to learn, I want to make a web app which is has a set of REST web APIs for everything (including authentication), and then the presentation.
For authentication I am using token-based auth with PassportJS.
So when a user wants to access the site, he'll obtain a token from the authentication API, in turn he'll need to pass this token in a HTTP Header on each request to the app.
My question is, how is this handled in the code? When the app gets the token (for example from a login page which hits the auth API), should it attempt to store it in the local machine (for example LocalStorage, or Cookie) and then on each new page fetch it and use it in a Header? Should each page's javascript attempt to load the token from the local storage automatically? I tried looking for an example, but haven't found a complete one that deals with how you handle navigation when you're depending on sending a header on every single request (that you want authenticated).
Thanks!
Once the user is authenticated return a secure session cookie which will be stored by the user's browser. Now on every request, this cookie will be sent by the browser to your application automatically, which you can check in your backend code (typically controller) to verify the existence of user session.
I have a web client that talks to a .NET webservice for data and control of various household systems. I want to expose nest thermostat control in the web client via the .NET webservice. I understand the typical auth process requires "users" to authenticate a client using the provided "works with nest" page to get a code and then use that code to get a token. In my case the .NET webservice is the client and there is no user or UI to allow a user to "accept" and thus I need a way to get the auth token (or pin) without pushing a webpage in front of a user? Is this possible? thanks
UPDATE:
I manually went through the process of generating a token and discovered the expires number to be rather large (10 years). Given that is there any reason I can't just use that token in my .NET app with all future rest calls?
The token will only allow you to access the approving account, so if this application is for your personal use, then yeah, just hard code the token.
If you .NET service can handle an oAuth callback (A little confused about how you would have a webservice that can't serve HTML) then you can enter the callback URI into your client settings on developer.nest.com and the PIN will be returned directly to the service for you. The callback URI must start with https:// or http://localhost though.
Just a note, if you're using a web service, specifically a SOAP service, then XML will be returned on the callback, not HTML. In the case of the nest API, JSON is returned.
In the case of oAuth, it's done on the lower level protocol of http using headers, URIs and the like. Here is the link to the standard:
https://www.rfc-editor.org/rfc/rfc5849
I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.
As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.
That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:
I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.
On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.
On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.
I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.
You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.
Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.
Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.
There's an open standard now called "JSON Web Token",
see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating tokens that assert some number of claims. For example, a
server could generate a token that has the claim "logged in as admin"
and provide that to a client. The client could then use that token to
prove that they are logged in as admin. The tokens are signed by the
server's key, so the server is able to verify that the token is
legitimate. The tokens are designed to be compact, URL-safe and usable
especially in web browser single sign-on (SSO) context. JWT claims can
be typically used to pass identity of authenticated users between an
identity provider and a service provider, or any other type of claims
as required by business processes.[1][2] The tokens can also be
authenticated and encrypted.[3][4]
Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.)
Check this var on the server-side on every API call.
P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.
Excuse me #MarkAmery and Eugene, but that is incorrect.
Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:
First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password.
Before authentication the calls to the API are not accepted.
During authentication a "token" is returned.
After authentication only API calls with the authentication "token" will be accepted.
Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.
Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.
Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.
So you do not have to worry that this may be an unauthorized user without credentials.
(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)
Here's what I do:
Secure the API with an HTTP Header with calls such as X-APITOKEN:
Use session variables in PHP. Have a login system in place and save the user token in session variables.
Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.