Which OAuth2 grant type should I use? - perl

I'm maintaining SReview, a mojolicious-based webapp which needs to run a lot of background tasks that will need to change database state. These jobs require a large amount of CPU time and there are many of them, so depending on the size of the installation it may be prudent to have multiple machines run these background jobs. Even so, the number of machines that have access to the database is rather limited, so currently I'm having them access the database directly, using a direct PostgreSQL connection.
This works, but sometimes the background jobs may need to run somewhere on the other side of a hostile network, and therefore it may be less desirable to require an extra open network port just for database access. As such, I was thinking of implementing some sort of web based RPC protocol (probably something with JSON), and to protect the access with OAuth2. However, I've never worked with that protocol in detail before, and could use some guidance as to which grant flow to use.
There are two ways in which the required credentials can be provided to the machine that runs these background jobs:
The job dispatcher has the ability to specify environment variables or command line options to the background jobs. These will then be passed on to the machines that actually run the jobs in a way that can be assumed to be secure. However, that would mean that in some cases the job dispatcher itself would need to be authenticated with OAuth2, too, preferably in a way that it can be restarted at will without having to authenticate again and again.
As the number of machines running jobs is likely to be fairly limited, it should be possible to create machine credentials for each machine. In that case, it would be important to be able to run multiple sessions in parallel on the sale machine, however.
Which grant flow would support either of those models best?

From overview of your scenario it is clear that interactions occur among system to system. There is no end user (a human) user interaction.
First, given that your applications are executed in a secure environment (closed) they can be considered as confidential clients. OAuth 2.0 client types explain more on this. With this background, you can issue each distributed application component a client id and a client secret.
Regarding the grant type, first I welcome you to get familiarize with all available options. This can be done by going through Obtaining Authorization section. In simple words it explain different ways an application can obtain tokens (specially access token) that can be used to invoke OAuth 2.0 protected endpoint (in your case RPC endpoint).
For you, the best grant type will be client credential grant. It is designed for clients which has a pre-established trust with OAuth 2.0 protected endpoint. Also it does not require a browser (user agent) or an end user compared to other grant types.
Finally, you will require to use a OAuth 2.0 authorization server. This will registered different distributed clients and issue client id, secrets to them. And when a client require to obtain tokens, they will consume token endpoint. And each client invocation of your RPC endpoint will contain a valid access token which you can validate using token introspection (or any specific desired method).

Related

Encrypted Password Accessible via API Call, Is this Secure?

I am working through some security concepts right now and I was curious if this method has been tried and/or if it is safe taking into consideration "Brute Forcing" is still possible.
Take for example a Microsoft WebAPI Template in Visual Studio where you access a endpoint using a "GET".
The Endpoint would be accessible by any user/application
The String value that a user/application would get from this endpoint would be the password they need, but encrypted using a "KeyValue"
After a TLS Transmission of this Encrypted Value, the user/application would decrypt the String using their "KeyValue"
Is this a secure practice?
Thanks for indulging me and look forward to your responses.
EDIT: Added Further Clarification with Image to Help Illustrate
Suppose the following 2 Scenarios:
Communication between Server and Client
a. Your Server serves the Client application with an encrypted password.
b. The Client can request any password.
c. The passwords are encrypted with a shared Key that is known by both server and client application
As James K Polk already pointed out:
A knowledgable Attacker can and will analyse your deployed application and at some point will find your hardcoded decryption key ("KeyValue"). What prevents him from requesting every password that is stored on the Server?
Rule of thumb here would be: "Do not trust the client side."
Communication between Server and Server
a. You have 2 server applications. Application A is acting as some kind of database server. Application B is your Back-End for a user application of some kind.
b. Application A serves paswords to any requester, not only Server B. With no type of authentication whatsoever.
c. Confidentiality is guaranteed through a shared and hard-coded Key.
I think you are trying to overcomplicate things hoping that no one is able to piece together the puzzle.
Someone with enough time and effort might be able to get information about your server compilation and/or be able to get the Code of Application B. Which again defaults in the scenario of 1. Another point is that there are enough bots out there randomly scanning ips to check responses. Application A might be found and even-though they do not have the shared key might be able to piece together the purpose of Application A and make this server a priority target.
Is this a safe practice?
No. It is never a good idea to give away possibly confidential information for free. Encrypted or not. You wouldn't let people freely download your database would you?
What you should do
All Authentication/Authorization (for example a user login, that's what I expect is your reason to exchange the passwords) should be done on the server side since you're in control of this environment.
Since you didn't tell us what you're actually trying to accomplish I'd recommend you read up on common attack vectors and find out about common ways to mitigate these.
A few suggestions from me:
Communication between 2 End-points -> SSL/TLS
Authorization / Authentication
Open Web Application Security Project and their Top 10 (2017)

How to handle username/pass changes in a distributed REST application?

I have a distributed REST application, written in C++, with an integrated SQLite DB. The application is self contained - no apache or iis server, and no external mysql. The application is the logic behind a hardware sensor: the application monitors sensor(s), identifying and storing data of interest, and generating "events" when data of interest repeats. The creation of data of interest is synchronized across the Internet to multiple instances of the application using REST to communicate the synchronization.
Using basic authentication over https, each instance maintains a local key/value store of remote instances' user/pass authentication data. This is necessary because each communication with a remote instance of the application requires authentication.
My question is how to handle the situation when the human operator changes either the username or password in the application, while the application is in active synchronization with remote instances.
I'm thinking this is really no different than any other material application data changing - when a local username / password changes, a REST communication is posted to each synchronization instance containing the changed data for that remote's local key/value store. Any communications that fail get queued for when that remote is back, as that is material information the remote needs to maintain synchronization.
Because the communications occur over https, the fact that authentication data is being passed around is okay.
I thought I might need special logic to handle the race condition where one instance tries to communicate with another, but the other has just changed its authentication fields. The sender will queue with my current logic, and when the remote sends it's updated authentication data, the locally queued failed communications will start succeeding. So that does not appear to be an issue.
I guess this is a request for anyone that's been here before, what did you do? Maybe my search terms are weak here, because I'm not finding discussion of this issue.

Is it insecure to use a root user for mongodb?

I have an app that connects to different databases on a mongodb instance. The different databases are for different clients. I want to know if my clients data will be compromised if I used a single user to login to the different databases. Also, is it a must for this user to be root? to readWrite role will do the trick. I'll be co connecting to the databases through a java backend.
There is no straightforward answer to this. It's about risk and cost-benefit.
If you use the same database user to connect to any database, then client data separation depends much more on business logic in your application. If any part of your code can just decide to connect to any client database, then a request from one client may (and according to my experience, eventually will) end up in a different client's database. Some factors make this more likely to happen, like for example if many people develop your app for a longer time, somebody will make a mistake.
A more secure option would be to have a central piece or component that is very rarely changed with changes strictly monitored, which for each client session (or even request) would take the credentials accroding to the client and use that to connect to the database. This way, any future mistake by a developer would be limited in scope, they would not be able to use the wrong database for example. And then we haven't mentioned non-deliberate application flaws, which would allow an attacker to do the same, and which are much more likely. If you have strong enforcement and separation in place, an malicious user from one client may not be able to access other clients data even in case of some application vulnerabilities, because the connection would be limited to the right database. (Note that even in this case, your application needs to have access to all client database credentials, so a full breach of your application or server would still mean all client data lost to the attacker. But not every successful attack ends in total compromise.)
Whether you do this or not should depend on risks. One question for you to answer is how much it would cost you if a cross-client data breach happened. If it's not a big deal, probably separation in business logic is ok. If it means going out of business, it is definitely not enough.
As for the user used for the connection should be root - no, definitely not. Following the principle of least privilege, you should use a user that only has rights to the things it needs to, ie. connecting to that database and nothing else.

Where exactly is REST authentication used?

I've been reading for hours, yet failed to find clear and understandable explanation. Where exactly is REST authentication used?
Between browser and server (to replace something like PHP session/browser cookie combo)?
Between server and another server?
Between nodes/modules on the same server?
Let's say I'm developing a system from scratch and instead of having some monolith MVC on the server side I'd like to use twitter's example - make "all things REST" - system of distributed independent modules speaking to each other via REST. Can REST (authentication) then also be used between browser and server?
In order to further improve behavior for Internet-scale requirements,
we add layered system constraints (Figure 5-7). As described in
Section 3.4.2, the layered system style allows an architecture to be
composed of hierarchical layers by constraining component behavior
such that each component cannot "see" beyond the immediate layer with
which they are interacting. By restricting knowledge of the system to
a single layer, we place a bound on the overall system complexity and
promote substrate independence. Layers can be used to encapsulate
legacy services and to protect new services from legacy clients,
simplifying components by moving infrequently used functionality to a
shared intermediary. Intermediaries can also be used to improve system
scalability by enabling load balancing of services across multiple
networks and processors.
The primary disadvantage of layered systems is that they add overhead
and latency to the processing of data, reducing user-perceived
performance [32]. For a network-based system that supports cache
constraints, this can be offset by the benefits of shared caching at
intermediaries. Placing shared caches at the boundaries of an
organizational domain can result in significant performance benefits
[136]. Such layers also allow security policies to be enforced on data
crossing the organizational boundary, as is required by firewalls
[79].
The combination of layered system and uniform interface constraints
induces architectural properties similar to those of the uniform
pipe-and-filter style (Section 3.2.2). Although REST interaction is
two-way, the large-grain data flows of hypermedia interaction can each
be processed like a data-flow network, with filter components
selectively applied to the data stream in order to transform the
content as it passes [26]. Within REST, intermediary components can
actively transform the content of messages because the messages are
self-descriptive and their semantics are visible to intermediaries.
You should really read the layered system part of the Fielding dissertation.
Where exactly is REST authentication used?
It is used between a REST client and a REST service (the client sends requests - containing auth headers - to the service). A REST client can be on a browser, on another server, on your server (e.g. a load balancer), etc... It depends on the current context what is a REST client and what is a REST service. By REST you have a layer hierarchy in which the upper layer contains the clients which call the services of the next layer below, and so on... The components (clients, services) of this structure does not know of the existence of the layer hierarchy...
So for example it can happen, that a proxy relays the requests to the next layer without authorization, because authorization will be done by other components. It can happen that you authenticate your clients and add a secondary auth header with user identity, or permissions, so the layers below don't have to process username and password again. There are many options...
Just to talk about oauth. It is for authorizing access of 3rd party (non-trusted clients) to user accounts. So in that case the client runs on a different server, and it sends an access token (instead of username and password) registered by an user. This 3rd party client uses the allowed part of the permissions of that user. Many user can register the same 3rd party client with different access tokens ofc.
REST is an architectural style and REST has nothing to with Authentication/Authorization. That said, there are authentication/authorization mechanisms that provide a RESTFul APIs for REST style of consuming the services: OpenID and OAuth/OAuth2. They are designed to used between client and server, and more (you can read more about them).
Also you may be interested in reading 'whats-the-difference-between-openid-and-oauth'
Hope this help!

Multitenancy using LDAP Integration

I need your suggestion for the following stuff of Multitenancy:
Actually I need to achieve multitenancy for my app. I've got it for using traditional flow with use of DB/Schema (eg. separate schema for each tenant).
Now I need to integrate user validation from LDAP and multitenancy stuff as well.
So What I am thinking is that If I store User info + DB/Schema info (DB connectivity info) in LDAP Server for more dynamic nature of the app. Because with this I would be able to connect any DB/Schema (irrespective of their physical location).
What's your opinion for this approach, Would it be really feasible?
If there is any cons in your mind, please share.
Thanks & Regards.
It sounds like you are trying to host multiple clients' systems on your system and each client may have multiple connections from multiple locations. From your question it sounds like you are putting one customer per database though databases may not be on the same cluster.
The first thing to do is to lock down PostgreSQL appropriately in the pg_hba.conf and expose only those database/user combos you want to expose. If you are going this route, LDAP sounds sane to me for publishing the connection info, since it means you can control who can access which accounts. Another option, possibly closely tied, would be to issue SSL certs and use certificate authentication by clients, so they can be issued a cert and use it to connect. You could even authenticate PostgreSQL against LDAP.
So there are a lot of options here for using these two together once you have things otherwise properly secured. Best of luck.