How to support secure creation of a user account over an external API via a queued job? - api

So this question is delving into security and encryption and the problem potentially hasn't been encountered by many. Answers may be theoretical. Let me outline the scenario...
A website frontend is driven via a backend API. The backend has an endpoint handling a generic registration form with username and password. It's using SSL.
The backend API handles registration via an async job queue. The queue does not return responses to the API server. It's a set and forget operation to queue up the registration.
Queued jobs are picked up by workers. The workers take care of creating the user account. These workers need access to the plaintext user password so that they can trigger a third-party API registration call with the password.
So the real crux of the problem is the syncing of the password to the third party API while not revealing it to prying eyes. The queue poses the problem of not having direct access to the plaintext password from global POST data anymore, meaning it needs to be stored in some fashion in the queue.
The queue can easily store the hashed password and copy it directly to the users table. This solution does not allow for syncing of the password with the third party API, however, as it's already encrypted. I toyed with two-way encryption, but am whole-heartedly concerned with leaving the password prone to decryption by an attacker.
Can anybody think of a secure way to handle this scenario of password syncing?
The queue is a requirement and it's assumed that this is readable by anyone with access to the server. The passwords don't necessarily have to be synced; the password for the third-party API could be a derivation of the original so long as there's a secure means to decrypt via the logged in user without supplying their password. This is essentially to simulate Single Sign-On with a third party API that does not support SSO.

There are a few ways to sync passwords:
Both auth stores use reversible encryption so that each system can extract the real values to send to the other system;
Both use the exact same encryption so that you send the encrypted text through and therefore can be understood by both.
One system is the "master" in which the users always authenticate through and the "slave" systems simply receive acknowledgement that the user has logged in. This can take the form of machine generated passwords created by the master for use in account creation on the slaves.
One system is the "master" that all other systems make calls into for account validation. Similar to using LDAP or MyOpenID.
There are certainly issues you can run into with a multi-master password sync'ing such as ensuring password changes are properly replicated when a user changes their password.
In your case, it sounds like the user never directly interfaces with the 3rd party API. If that's accurate, have the users authenticate against your system. Generate the 3rd party API password when needed, store it with their account and auto log them into the other system as necessary. Your primary password can be stored in irreversible encryption; however the 3rd party one would have to use reversible encryption. The Queue would never have to have the initial password and instead would simply generate a new one and store it with the local account.

Related

Login another salesforce org from salesforce record page

I was wondering if it was possible to login to different salesforce environments (Sandboxes, scratch orgs, production env, etc) using either Apex/LWC/Aura (or anything that I can make a quick action to). For example, I have a list of credential records, with the username and password, and I would like to have a login button that creates a separate tab that can automatically redirect to that specific instance and log in.
Currently, if a user wants to login to a particular instance, they have to either go to test.salesforce.com or login.salesforce.com (depending on if it's a sandbox or production) manually, then copy the password and username in. The ideal situation is to have a login button that can do this automatically from the record page where the username and password is located.
I think previously this could have been accomplished through the URL, but salesforce has recently patched this out due to security concerns. Is there another good way to do this?
It sounds like you're trying to solve two specific challenges:
Your users need to be able to manage very high volume of credentials.
You need authentication to survive password resets.
The clear solution, in my mind, is to use the OAuth Web Server flow to execute initial authentication and then store the refresh token that results from this flow. This token survives password resets, and may be used more or less indefinitely to create new access tokens - which users can then use to log in via a frontdoor link.
There's an out-of-the-box tool that does this already: the Salesforce CLI. You can authenticate orgs to its toolchain, name them, and subsequently access them with a single command (sfdx force:org:open). Users that prefer a GUI can access the exact same functions in Visual Studio Code.
If you're hellbent on doing custom development to handle this use case, you can, but you need to be very careful of the security implications. As one example, you could implement an LWC + Apex solution that executed the relevant OAuth flows against orgs and stored the resulting data in an sObject, then allowing users to click a button to generate a new access token and do a one-click login.
But... if you do this, you're storing highly sensitive credentials in an sObject, which can be accessed by your system administrators and potentially other users who have relevant permissions. That data could be exfiltrated from your Salesforce instance by an attacker and misused. There's all kinds of risks involved in storing that kind of credential, especially if any of them unlock orgs that contain PII or customer data.
One of the two best answers for that (the other one being 'pure Apex' and relatively more complex) is using Flow.
"You can use a login flow to customize the login experience and integrate business processes with Salesforce authentication. Common use cases include collecting and updating user data at login, configuring multi-factor authentication, or integrating third-party strong authentication methods.enter image description here"
"You can use login flows to interact with external third-party authentication providers by using an API.
For example, Yubico offers strong authentication using a physical security key called a YubiKey. Yubico also provides an example Apex library and login flow on GitHub. The library supplies Apex classes for validating YubiKey one-time passwords (OTPs). The classes allow Salesforce users to use a YubiKey as a second authentication factor at login. For more information, see yubikey-salesforce-client.
You can also implement a third-party SMS or voice delivery service, like Twilio or TeleSign, to implement an SMS-based multi-factor authentication and identity verification flow. For more information, see Deploy Third-Party SMS-Based Multi-Factor Authentication."
learn more here: enter link description here

Is there any way to programmatically generate a CouchDB cookie?

I'm working on an app which will use CouchDB to store some data for users. But I don't want users to log into CouchDB directly.
I will have an app client (mobile/web), an app server, and the CouchDB server. The client app will authenticate to the app server, then myy ideal scenario would be for my app server to authenticate the users programmatically, then send just the 10-minute cookie to the client app.
That is, I would like the app server to request a Cookie from the CouchDB server on behalf of the user of the app client, then send only the cookie to the app client.
The app server could just POST to _session on behalf of the authenticated user, but this requires:
maintaining a list of users' passwords in the app server
using a single, known, password for all users
resetting the password to something random for each authentication request
For security reasons, #3 seems the best, but this seems like extra work, and is an extra round-trip to the DB (albeit, not an expensive one). So my question is: Is there any, as an administrator, way to generate a cookie on behalf of a user, without using the users' password at all?
This would also potentially allow me to entirely reject requests to _session except from my app server, as an added security measure.
And for the sake of completeness, I'll also mention that I've looked at these other options, and found them wanting:
Proxy Auth
The fact that the x_auth_token never expires is worrisome to me. It means a compromised token would grant forever access to the user's data. And AFAICT, the token can't even be invalidated without changing the user name or the server secret (which would in effect invalidate everyone else's auth tokens as well). But maybe I'm missing something here?
OAuth auth
This seems to just move the problem. Now rather than storing users' passwords in my server app, I have to store OAuth secrets. Plus, now my server and client code must be more complicated.
I don't follow your exact goals. You seem to imply users might have passwords ("app server authenticating the users programmatically") but you don't want the users to "ever need to know their CouchDB password". What sort of authentication do you want?
There's two (and a half) general approaches I've taken to authentication with CouchDB:
"Man-in-the-middle[ware]" approach, where I have thin middleware in front of CouchDB. This middleware forwards username/password to the "/_session" which yields a cookie or error codes based on the CouchDB _users database. The middleware copies this cookie from CouchDB onto its own HTTP response back to the client (or displays a message in case of error). Then on subsequent requests, that need database access, it forwards the cookie (now from the client request) back again to the database.
The traditional approach, where you just use CouchDB as a data store and maintain your own "user" entries/indexes. Make sure you use current best practices for password storage/handling or use a library that takes care of those details for you. The middleware connects to the database as "itself" and handles read/write permissions with its own logic based on its own session handling.
Or — sort of a hybrid approach — you can use the "/_session" API only to see if CouchDB accepts the username+password as valid. If it does, create a separate middleware-handled session for that user. (Basically you're only using CouchDB's _user database as the "password handling library" and the rest is the traditional approach where the access control is implemented all in the middleware rather than at the database.)
For real-world production stuff, I've tended to use only the latter two (or one-and-a-half given the earlier numbering…) — the first method is kind of fun, but CouchDB's lack of document-level read permissions usually means that giving users nearly-direct access to the database server is untenable in practice.
UPDATE: your question now makes it clear that you want the client app to talk directly to both servers: the app (formerly "middleware") server and the CouchDB (database) server. I'm leaving the content above because I think it's still somewhat useful and provides a bit of background/context for this update.
You are right in your suspicions that Proxy Authentication is the wrong solution: it is not intended for end-user usage, but really to replace the cookie-forwarding "trick" portion of #1 above. That is, proxy authentication is when you fully trust one party (i.e. your middleware) to provide the user information as it works on behalf of a user. But you want the users to talk to the database directly, and you cannot trust them with the X-Auth-CouchDB-Token.
I will defer to your judgement on the OAuth option. I do think it is closer to want you want but it is clear that somehow you are authenticating users against a different service and don't need to store per-user keys in CouchDB itself. The request signing required by OAuth 1.0 does mean you'd need support in your client app's HTTP library too.
I see a few options, without building a custom CouchDB plugin, that could let your app server hand out a token to authenticated users which your database server will accept:
Proxy after all! That is, hide your database server behind your app server or another lightweight custom reverse-proxy. All this middleware needs to do is check your existing client app session (cookie or other authentication header) and if it's valid, set the internal proxy auth headers that CouchDB will accept — then it forwards the rest of the request/response verbatim.
Deterministic password, per-user if it makes you feel better. Configure your app server with a secret known only to it, then set each user password to something like HMAC(username, app_server_secret). Now when you want to generate a token for a user, your app server can generate the password on a per-user basis. Note that this really isn't any more secure than just using the app_server_secret as the password for every user — CouchDB already salts and hashes each user password independently so if someone gets a hold of the database but not your app's configuration values the attacker couldn't tell the two apart. In both cases, preventing unauthorized database usage hinges entirely on keeping app_server_secret secret.
Re-implement CouchDB's current cookie generation algorithm. CouchDB's cookie algorithm (view source) is basically data = username + ':' + timestamp; base64(data + ':' + sha_mac(data, secret)). Where secret is the couch_httpd_auth.secret value plus the user's salt value. You can tell your app server the couchdb_httpd_auth/secret value and it can follow the same steps to generate a valid cookie which you provide to the client app, and CouchDB will accept it as its own. This cookie will be valid until the timestamp + the configured couch_httpd_auth/timeout. As "hacky" as it seems, this is probably the closest to what you are asking for, although you still need to set/disable the users' actual passwords somehow.
Expanding on natevw's brilliant answer. I was having similar problems, and never would have realized option 3 was possible without having stumbled across that answer.
Here is my python3 implementation for generating a cookie (uses pycouchdb to interface with couch):
def generate_couchdb_cookie(couchAddress, couchSecret, username):
timestamp = format(int(time.time()), 'X')
data = username + ":" + timestamp
server = pycouchdb.Server(couchAddress)
db = server.database("_users")
doc = db.get("org.couchdb.user:" + username)
salt = doc["salt"]
secret = couchSecret + salt
hashed = hmac.new(secret.encode(), data.encode(), hashlib.sha1).digest()
inbytes = data.encode() + ":".encode() + hashed
result = base64.urlsafe_b64encode(inbytes)
return "AuthSession=" + (result.decode("utf-8")).rstrip('=')

Is OAuth 2.0 redundant/unnecessary if the client is the same as the resource owner?

In section 1.1 of RFC 6749, there are four roles: resource owner, resource server, client, and authorization server.
Does OAuth become redundant or unnecessary if the client and the resource owner are the same entity?
For example, I have a closed API and a front-facing web server. (The front-facing web server would be both the client and the resource owner.) I am trying to decide whether to switch to OAuth 2 authentication instead of using the current username/password authentication method. Is there any added security for moving to OAuth 2 if the API remains closed to third-party applications? (That is, no third-parties will ever have access to the API.)
Thanks!
In the case where the Resource Owner and Client/Resource Server roles coincide OAuth 2.0 may become less relevant from a security point of view, since one of the primary objectives of OAuth not to expose primary credentials of the user to the client becomes moot. That is also the reason why the so-called Resource Owner Password Credentials grant is considered to be a legacy/deprecated flow.
However, it may still make sense to follow the OAuth 2.0 pattern for a number of reasons:
the ability to leverage a standardized protocol through stock libraries and
frameworks without relying on custom code
the fact that in your case the Resource Server is still made strictly OAuth 2.0 compliant, dealing with Clients presenting access tokens, irrespective of what the Client/Resource Owner relationship/implementation is; this would make it easier to allow for 3rd-party client access in a future scenario
the fact that you concentrate verification of user credentials on a single path between Client and Authorization Server so each of your Resource Servers don't need to be bothered by checking user credentials individually, possibly dealing with different authentication mechanisms
and perhaps most importantly, also security-wise: once the user has authenticated through the Client using his primary credentials, the Authorization Server can issue a refresh token as well as an access token; the Client can store and use the refresh token to a new access token when the old one expires; this frees the Client from storing the primary user credentials if it wants to keep accessing the API for a long period of time without requiring explicit user interaction and authentication and makes the resulting system less vulnerable for leakage/loss of user credentials since the user credentials (password) are not stored in the Clients
If you have the following issue then you should use OAuth;
Let's say you a Gmail like web mail provider. Some of your users are using a third party app which logs in into your user's account and auto replies certain emails for you. Or you are Facebook like social network web site where some of your users use a third party app which analyzes your friend networks and prints a 2D graph for you. In this case your users are giving away their usernames and passwords. How would they prevent a certain third party app accessing their account after they gave away their username and password? Simply by changing their password. Now you have another problem; other third party apps won't be able to access the user's account. Then the user have to re-give away his password to other apps he trusts. Now this is problem too because it is not user friendly. OAuth is simply a temporary password that your user gives away to a third party app developer. He can revoke it whenever he wants without changing his own password.
Other than that OAuth is unnecessary. Just use a session cookie if you are not going to have third party app developers. It is a random string stored in user side. And on the server side will have whatever you want. Just look how PHP sessions are used and stored on server side. You can define their lifespan and refresh time automatically from php.ini.

Password protecting a REST service?

After creating a basic REST service, I've have come to the point where it would be appropriate to add some sort of password protection, as I need to verify that my users are both properly logged and have sufficient permissions to execute whatever action they are going to.
The REST service will mainly be accessed from a Javascript-heavy frontend and with that in mind, I have come up with the two following alternatives to solve this:
Make users login by first sending credentials to a /login page with POST. The page sets a session cookie wherein the user is
marked as logged in, along with the permission level. On each
following request, I verify that the user is logged in and his/her
permission level. When the session expires, automatically or
manually (logout, the user will have to re-logon).
Temporarily save the credentials hashed locally and send the users credentials along every single request made by the user to verify the credentials & permissions backend on a per-request basis.
Are there more ways to solve this and is there something else that I should be concerned with?
I'm currently developing a REST API along with a client (written in javascript), below I'll try to explain the methods used to protect the API against unauthorized access.
Make your REST API to require a Auth-Key header upon every request to the API, besides /api/authenticate.
/api/authenticate will take a username and a password (sent using POST), and return user information along side with the Auth-Key.
This Auth-Key is randomly generated after a call to /api/authenticate and stored in the backend users table with the specific user entry, a md5 hash of the remote ip + the user agent provided by the client.
On every request the value of Auth-Key, and the md5 sum mentioned, is searched for in users . If a valid user is found that has been active during the past N minutes the user will be granted access, if not: http return code 401.
In the REST client, first get the Auth-Key by posting to /api/authenticate, then store this value in a variable and send in on every future request.
If you want to stay true to the definition of a REST service then it should be stateless and not store any login (or other context specific) data on the server: http://en.wikipedia.org/wiki/Representational_state_transfer#Constraints
Your 2nd approach would fit this model
First decide what it is that you're protecting against:
Authentication? (Knowing who is requesting your service?)
Authorization? (Whether a given person can properly request a given service or not?)
I recommend that you provide hashed keys for your service. That way you can manage the key issue separately from the services. Or a client key and a secret, Amazon does this.
It is always easier for the client if you have a stateless protocol. And send everything through the parameters, cookies are a bother for the client too.
Remember that it is in your interest to make it as easy as possible for potential developers to use your service. A super secure service that no one uses is boring.
You can let clients choose the security level by giving them the choice of HTTP or SSL/HTTP endpoints to connect to. Client choice is a good thing.
Make users login by first sending credentials to a /login page with POST. The page sets a session cookie wherein the user is marked
as logged in, along with the permission level. On each following
request, I verify that the user is logged in and his/her permission
level. When the session expires, automatically or manually (logout,
the user will have to re-logon).
Temporarily save the credentials hashed locally and send the users credentials along every single request made by the user to verify the
credentials & permissions backend on a per-request basis.
Your first approach does not meat the statelessness constraint of REST. You cannot maintain client sessions on server side. This constraint makes REST highly scalable...
Your second solution is appropriate. The simplest way to use HTTP basic auth. You don't have to hash the password on client side. What you need is an encrypted connection. On server side you can have an [username, password] -> [identity, permissions] cache, so this solution is much faster and superior in every other way than having server side sessions.
By 3rd party (non-trusted) clients the authentication is more complex, I guess you don't need that part.
I'm no security-expert. I use the RESTful Play!-webframework and they do the following things to authenticate users.
The cookie is protected against manipulation. It is signed with a long secret key and is checked for each request. Just hashing it is not enough!
They recommend to set unique information the identify the user in the cookie. As the server should be the only one to manipulate the cookie, that's enough.
Don't put the password as credential in the cookie. If someone sniffs the cookie, not only the session can be hijacked, but also the complete account or even worse, other accounts with the same credentials.
If you want to protect the cookie against hijacking using https.

Logging my users into other services, how to store their passwords?

I am starting a service for students at my school which requires them giving me their user account information for our school's web system so that I can automate some annoying tasks for them. I will be logging them in using CURL but I am having trouble figuring out how to store their passwords in a secure method. With most web services, passwords are encrypted then stored and when logging in, we only compare the encrypted passwords. This is much different though. Since I will be sending their passwords via HTTP requests, it's required I am able to decrypt their passwords back into original text. How would you recommend I go about storing and retrieving them?
That might not be the answer you are looking at, but if you are going to store user's credentials for a third party service, there is no way to secure the storage with software only. As you mentioned it yourself, your app needs to be able to retrieve from that store the original credentials, in order to impersonate the user. And if your app can do it, so can any other code running on that box.
Thus, the only real solution is to ensure that only your software is running on the box. That assumes physical security as well, limited access to the machine, full audit and lowering the attack surface as much as possible, by turning off all unnecessary services.
On a separate note, if the school services support access delegation (through OAuth for example), you should consider going that route, and get out of the credentials storing business.