Consider this scenario: A Web App "A" wants to call an API "B" and the API "B" also needs to call the Web App "A" API, but both calls (from "A" to "B" and from "B" to "A") have to be in behalf of an user (the user is the same on both platforms but with different credentials). A and B are apps developed by different companies, so no code base is shared.
I need to design this scenario, where my app will integrate with another app and both apps will consume data from each other.
I know I could use Oauth but I am not sure what to do since it will be a bidirectional communication. I do not want to request the user to authorise both applications. Is there any design pattern or model I can use?
The API gateway pattern absolutely suitable for this use case:
read more here
The purpose of API Gateway will be to authenticate the token so that individual app do not bother about it.
Related
There is a lot of information on the web about OAuth 2, its different types of flows and where/how to use them. I find that most of these resources discuss authenticating a user for an application, but I am struggling to understand what the best/correct approach would be when consuming third party APIs (i.e. when our own API is the "middleman" between a user and their data in a third party API).
With the help of an example scenario and some diagrams, I would be really grateful for advice/opinions on how I should properly implement integration with third party APIs and what the pros & cons of each approach are.
Starting point
As a starting point, suppose we have a web app, structured as follows:
Frontend - SPA (Angular), hosted with AWS S3 + Cloudfront
Backend - Node, running as stateless AWS lambda functions with AWS API Gateway
Auth0 for handling auth/signin etc. The frontend uses an Implicit OAuth2 flow to obtain access_tokens, which are stored in local storage and included as a header in all requests to the backend.
Potentially also native mobile app(s), consuming the same backend API.
Goal
Now suppose that we wish to add integration with Google Sheets. The new feature would allow users to use their own Google Sheets (i.e. stored in their own Google account) as a data source, with the app having read&write access to the sheet. There may be other integrations in the future, so I am assuming that other APIs would require a similar process.
Problem statement
In addition to the existing OAuth process (which allows users to sign in to the "MyApp" frontend and communicate with the "MyApp API"), there needs to be an additional OAuth process for users to connect MyApp to the third party Google Sheets API.
The documentation has two Quickstart examples, but neither seems to quite fit my needs:
Browser - https://developers.google.com/sheets/api/quickstart/js
Node.js (console app) - https://developers.google.com/sheets/api/quickstart/nodejs
The data from the third-party (Google) API is one of potentially several integration points, so intuitively it seems more logical (and more secure) that all communication with the Google Sheets API should happen in the MyApp API, and not on the frontend/client side. The MyApp API would fetch data, process/manipulate/format it in some way and then present it for display in the frontend or mobile apps.
We require access to each user's own data, so the Client Credentials flow is not suitable. I am focussing on the Implicit or Authorization Grant workflows.
Important note: The trickiness seems to come from the fact that the MyApp API is stateless, so there is no long-lived session in which to store tokens. On that basis, it seems like tokens need to be stored either in the frontend (e.g. local storage/cookies etc) or in a backend database.
Below is my interpretation of two possible approaches. I'd appreciate thoughts/corrections.
Option 1: Implicit flow - tokens stored FE, passed along to BE which then makes requests to Google
Pros:
Allows access to user's own data
Simpler flow, access_token retrieved immediately without needing the code step
Less steps to implement between initial sign-in process and actually obtaining data
No need for a backend database, can resend the token with each request
Cons:
Frontend (browser) has access to Google access_token which seems unnecessary and is a potential security concern
It seems like a strange process to pass the access_token from FE to BE, purely to allow BE to then use that token to make another request
I'm not sure how we would refresh/renew tokens since I understand that storing refresh_tokens on the client is bad practice. It would not be a good user experience if the user had to frequently sign in to reconnect their account
Option 2: Authorization Code Flow - all communication with Google via BE, tokens stored in BE database
Pros:
Allows access to user's own data
Other than the code-request / consent page, all communication with Google is implemented backend, so the tokens are not accessible on the client
Client secret can be used from the BE
Cons:
More complex flow, requires extra steps
Given that the BE is stateless, it's not clear how best to store the tokens. It seems like it would require storing them in a database which is extra complication and seems like it would have security implications - how would you properly secure / encrypt the access_token/refresh_tokens in said database?
Conclusion
Given that the data processing is to happen on the backend, option 2 seems slightly more suitable because the sensitive tokens can be hidden from the frontend app, and several clients (web frontend, mobile apps) have less obligation to be involved in the process with the exception of the initial sign in / user consent. However I’m not sure whether having a database full of user auth tokens is a good idea or how I could properly protect this database.
The good news is that both options are perfectly valid and equally secure. The concern about a short-lived Access Token being in the browser isn't an issue. Equally, if you only held the tokens on the BE, then you would need to implement your own client authentiation/session/JWT blah blah, which presents the same attack surface.
I've done both, and am currently migrating from BE to FE. In my case the reason is that everything I need to do, I can do on the FE, so I end up with no BE at all. This isn't strictly true since I do some onboarding/payment with the BE, but that's about all.
So the best approach depends on factors beyond those in your question, such as the nature of app, what the BE cost is and how important that is, what your devops skillsets look like for maintaining two environments, to what extent a BE is required anyway, vs being completely optional.
By default, TokenAuthentication creates one token for each user (User access tokens), what makes sense for an API accessed only by end users.
But to integrate with other applications, would be more suitable to authenticate the application itself (App access tokens), instead of to make the application access the API on behalf of a given user.
My question is how to achieve that with Django rest framework. Should I extend the tokens model to add a FK to the applications table or there is an "easy" way? Any tips?
If i understand your problem problem properly Instead of per user a token you would like to have per device ( app ) an authentication token. There are some well used third party app's like django-rest-knox or jwt provide that. No need to do this manually.
Though i prefer django-rest-knox as it has delete all token facility. Which is very useful in case of lost or compromise device.
I want to create a custom API that behind the scenes, call number of other APIs which use OAuth 2.0 for authentication. I want to manage this internally so that my custom endpoint somewhat abstract this.
Or to begin with I want to do what app like buffer (https://buffer.com) do - where you connect to different social services and than post your status.
How can I achieve this in .NetCore ?? I don't want to login with these (a lot of samples are catering this scenario), user login is different than this. I just want to establish these connections (like API Connections if you look at Azure API Management) and then perform some operations against those endpoints.
I hope i convey my point. please let me know if this isn't clear.
Thanks
Sanjay
OAuth2 systems are all based on the same workflow.
here's an authorization url, you pass some ids in an authorization header, if everything is correct you get a token, you then use the token to do whatever you are allowed to do. What changes are the credentials you use for authentication and the urls you hit for the various parts of this workflow.
You could write your own OAuth2 library which deals with all this, that's pretty much what I did and simply changed the details for every specific system I had to interact with.
This being said you can always use one of the existing implementations to connect to the various systems you care about, they all have an API you could use, all you have to do is make sure you follow the OAuth2 flow correctly.
I have an API which I'd like to secure using OAuth. My API is accessed with a web frontend used by real human users all with their own account (a couple of thousand), and it is also used by the API of some partner companies (less than a hundred), which should also have separate accounts.
I would like to secure the API using OAuth, and I have to decide how to represent the different users. In OAuth, there are two different concepts, clients and users, where client is the higher level concept, and every user is under one of the clients.
I can think of two different ways to represent these API accounts:
Have a single client, and have a separate user for every human user, and for every partner API.
Have one client for the human users, and a separate user for every human user. And have a separate client for every partner API.
Which of the two approaches would be the more idiomatic approach in OAuth? From a technical standpoint I don't see too much advantage or disadvantage of either solution.
(I'm partly confused because the client credential flow is described to be used for API-to-API authentication, which seems to make sense for authenticating the partner APIs. However, most of the OAuth guides also say that it should only be used for trustful APIs (whatever that means), or even internal APIs, but these partner APIs are definitely not internal.)
Implementation will be unified if there is separate client behind every app (including JS one, for users accessing your API via web frontend).
Also it will be possible to manage ACL per app in this case, which will define maximum privileges for the users (users may choose to give less privileges to the app).
On the other hand, simpler approach is to use Cookies for web frontend users and OAuth for partner applications. But in this case you need to support both authentication options.
I'm building some RESTful API for my project based on Play Framework 2.X.
My focus is on the authentication mechanism that I implemented.
Currently, I make use of SecureSocial.
The workflow is:
An anonymous user calls a secured API
Server grabs any cookie Id (kind of authentication token) and checks for matching in the Play 2 cache. (cache contains an association between cookie Id (randomly generated) and the user Id, accessible from database.
If any matched, user is authorized to process its expected service.
If none matched, user is redirected to a login page, and when filled with valid credentials (email/password), server stores its corresponding authentication data on Play 2 cache, and sends the newly created Cookie containing only a custom Id (authentication token) to user and of course, secured through SSL.
While the cookie/token doesn't expire, the user can call secured api (of course, if authorized)
The whole works great.
However, after some search, I came across this post, and ...I wonder if I'm in the right way.
Indeed, dealing with cookies ("sessions" in Play's term), would break the rule Restfulness.
Because an api really considered as stateless should be called with ALL the needed data at once (credentials/tokens etc..). The solution I implemented needs both calls: one to authenticate, the other to call the secured API.
I want to make things well, and I wonder some things:
What about the use of Api keys? Should I implement a solution using them instead of this SecureSocial workflow? Api Keys would be sent at EVERY API CALL, in order to keep restfulness.
I think about it since I want my APIs to be reached by some webapps, mobiles and other kind of clients. None of all are forced to manage cookies.
What about OAuth? Should I really need it? Would it replace totally the usage of simple api keys? Always with this objective of several clients, this known protocol would be a great way to manage authentication and authorization.
In one word, should I implement another mechanism in order to be Restful compliant?
this is quite an old Q, but still worth answering as it may interest others.
REST does mandate statelessness, but authorization is a common exception when implementing.
The solution you described requires a single authorization process, followed by numerous service calls based on authorized cookie. This is analog to api keys or OAuth. There's nothing wrong with cookies as long as the service isn't of high-security nature and that you expire then after a reasonable time.
Integrating OAuth into your service sounds a bit of an overkill and is recommended only if you expose the API to 3rd parties (outside your organization).