Server-side Google Sign-In, way to encrypt/decrypt data with Google-managed secrets? - authentication

It's rather straightforward to use the Google Sign-In library on the server side and attain a GoogleIdToken to validate a user's identity. However, I'd like to encrypt per-user data in my database with a secret that's unique to every user. Is there an easy way to do this? If not using Google Sign-in, you can derive keys from a user's password, but that's obviously not possible here.

Well, first of all, you're drawing a parallel to using the user's password to derive an encryption key, but since you're talking about that as an alternative if you weren't using Google Sign-On, that implies your talking about using the password that users would authenticate with. That's a bad idea.
Users need to be able to change their authentication password, and that will be a major hassle for you if you're encrypting with it. It will require you to decrypt everything with the old password and then re-encrypt it with the new one.
So what you need to find is something that you can pull out of the GoogleIdToken that will never change. Email addresses change, so I wouldn't use that. Perhaps the user id, which you can get with GoogleIdToken.getPayload().getSubject() is what you want. Then what you would want to do is derive a key from that. I would look for ways to combine it with other information that the user gives you that really is secret, though.

The information you receive during a Google sign on is intended for authentication purposes. The id token is encoded as a Json Web Token. There is nothing secret in a JWT.
The information is cryptographically signed by the authentication provider, so you can verify the information. This is of no help for deriving secrets, though.
Looks like you'll have to find another way.

There's no way to do this with just Google Sign-In, but you can use Firebase to convert user authentication credentials (with Google or other systems) into storage restricted to access by the user.
You can do this by using Firebase Authentication; you can authenticate your users from your backend, then store the encryption key for the user in User private objects. (Or possibly just store the data you wanted to secure in those objects.)
Then your server can be set up to not have the access rights to read user data unless those users are logged in, although you will still have administrative ability to read all user data.

Related

Storing API key

I am building a website that’s gonna have a pay system that works with the mollie API. In particularly the website needs to send users a payment link for their ordered products. To accomplish that mollie needs to authenticate with a api key. So I need to store the api key somewhere safely.
So my idea is to use AES Symmetric Cipher encryption when the admin registers his api key (CMS). With this encryption I need only one key to decrypt and encrypt the api key. I was thinking of using the plain text password of the admin as the key, because I don’t store this value (I hash the passwords) so it’s only available when then admin types his password. So when the admin wants to send a payment to an user the website will ask his password.
So my question is: Is this is a safe way of storing the api key?
Sorry for my bad English, it's not my native language.
First. API secrets and passwords have different lifecycles (key rotation & password change policies), and possibly different complexity requirements.
Second, The admin's plaintext password shouldn't be used for anything other than signing the admin in. Don't put all your eggs in one basket - you want to limit the scope of damage in case a secret gets compromised.
You would be better off just creating a separate secret for API key encryption/decryption, and storing it in some secret management e.g. Vault, AWS secrets, etc.
If you want to avoid storing the API key altogether, and you're fine with the admin just remembering it, then you can have the admin manually enter the secret, like a second password, but in any case it would be bad practice to couple it with the admin's sign-in password.

Encoding and Decoding API Access token with keys

I am planning to secure my rest API in django with a ACCESS_TOKEN.
When ever user is logged in using their username and password, once they are authenticated, I generate a ACCESS_TOKEN and passed to frontend be it Website or Native application. and then later used that ACCESS_TOKEN for further communication.
I am generating this token based on some user data and then encrypting this with public key. Later when application send this for in any request, I decrypt the ACCESS_TOKEN with private key and extract user data data and process the request. This is something similar to session where session data is in encrypted form in ACCESS_TOKEN and only private key and decrypt the ACCESS_TOKEN. This is what I am planning to do.
Please suggest me for following questions:-
1. Is is the best way to secure my REST API? I want to use my API in same way from Web-application(AJAX calling) and NATIVE application(Android/IOS etc) ?
2. What is the best way to expire the token? Do I need to keep track of access token at my end in order to expire them?
Also I do want to use the Oauth in my API.
Most people I see use JWT's that are signed but not encrypted so they store non-PI data like user_id or session_id. I guess you could encrypt it if needing to store personal information but I don't see any other reason. Assuming you are using HTTPS, then only the end client would have access to the information. Sounds like asking for trouble if the secret gets leaked so you would want a really good key rotation scheme since you may not even know its leaked until too late.
Many people using JWTs do so because they don't want a centralized auth server, thus the token is short lived like a few hours or days. If you need really tight control on expiring tokens, you can take a blacklist approach where a blacklist of JTI's (JWT Ids) are stored in a K/V to be checked against. https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/

Storing API keys on server

I have a service where users each have an API key. I need to store the keys so that they can be used to validate API requests.
If I store the keys in plaintext in my database, I'm worried about the scenario of someone getting access to the db, grabbing all the plaintext api keys, then using them to impersonate others (there will likely be bigger problems if someone got access to the db, though).
This is similar to storing user passwords, where you just store the hash and validate using that - however most APIs let you view your API keys, which means they need to be stored in some recoverable way.
Is there a best practice for this?
The threat that someone gets the database and gets the keys means they can use the api keys to access the data in the database, which they already have, so no win there.
The threat that someone can access the database, get the passwords, means they can reuse those passwords on other web sites with the same user name because people tend to reuse their passwords.
Another reason having passwords in the clear or easily reversable is someone in your company could get a hold of the passwords, and start to do bad stuff acting as the user. Which IS a risk you might have if your API keys are in the clear.
Typically, HMAC is a solution for cryptographically computing a secure value from a single secret key, and some public value.
Have a look at HMAC. With HMAC, you can load a secret key into memory with the app (config file, read off of amazon KMS, typed in on app start, or however you want to get that secret key there).
In the database, store a token. Token = UUID() for example. The token should be unique to the user, the token could be versioned in case you need to regenerate, and the token could be random (like UUID). The token is not secret.
The API key is computed using the secret key (SK) and user token (UT) as follows:
API_SECRET = HMAC(SK, UT)
Then distribute that UT (More commonly called API_KEY) and API_SECRET to the user, and when the user tries to connect, you compute the API_SECRET:
Get user record from database (you're probably already asking the user to provide their username)
Compute the API_SECRET from the UT in the database:
API_SECRET_DB = HMAC(SK, UT)
Compare the computed API_SECRET_DB to the one provided in the request:
if (API_SECRET_DB == API_SECRET_FROM_REQUEST){
//login user
}
Bottom line, you only protect the Secret Key, and not every single credential.
I did an update to some library written in PHP which made it using an Impersonate Protection Algorithm (IPA). that lead to not saving the Token itself inside a database.
For more info check this https://github.com/vzool/api-hmac-guard
Hope it helps, Thanks

Can I Firebase createUser with an arbitrary ID instead of an email address

I'm using Firebase for an Atlassian Connect AddOn. I want to use Firebase users to secure the data.
The users will be identified by a clientKey provided by Atlassian (probably after I fudge it a bit) - NOT BY EMAIL.
Ideally, I don't want to have to do my own authentication here, as the Firebase.createUser method would suffice entirely if I could provide something other than an email to it, but I can't find anything like that in the documentation.
Is there a way I can create Firebase users WITHOUT AN EMAIL (just an ID and password), without going to all the way into oAuth and all that jargon to create my own custom authentication?
A Firebase user must have an email. If that is a problem then we can't use a Firebase "user", but instead a "token" (which must have a UID as part of it's payload and hence behaves the same way in terms of security once it reaches their datastore).
If you don't need a password, then "instead of double-authenticating and duct taping" as #Kato kindly pointed out, you can generate your own Firebase tokens and serve them to the client.
If you require the user to provide a password then you'd have to implement your own verification before you generate the token and serve it to the client. Since there's no Firebase user involved anymore, but rather a token your privileged server can arbitrarily create and serve, it's your responsibility to ensure you're doing that at the right time (i.e. when a user has provided your server with an adequate ID and password).
Read more about Custom Authentication here and tokens.

IBM Worklight. Is it possible to store user credentials securely and recover them without user interacton?

There is a common requirement of storing user credentials securely (user id / user password) in the App and use them automatically next time the App starts, but I'm not being able to figure out how to do this without user interaction.
Using JSON Store I need a password to encrypt the information, so if I store user credentials in the JSON Store I will need to ask to the user for the password used to encrypt the information.
A solution I figure out is to store the user id in a JSON Store without encryption and the password in a JSON Store encrypted with the user id as password. May be this solution provide a bit more security than not to encrypt anything but I think is not a complete solution.
As explained in the comments this is a really bad idea.
Is there any solution to store user credentials securely and recover them without user interaction?
You can use the Keychain API on iOS. Android doesn't seem to have an equivalent API.
The most complete solution I figure out is to store the user id in a JSON Store without encryption and the password in a JSON Store encrypted with the user id as password. May be this solution provide a bit more security than not to encrypt anything but I think is not a complete solution.
I would strongly advise against doing that, if you store the encryption key (the user id) in plain text, then the attacker can simply use that to get to the password.
Update (Aug 27, 2014)
You should consider:
Hashing - You could hash values you want to protect. These are one-way functions, so you can't get the password back once you hash it. However, you can verify that the user provided the correct password. For example: First login you store( hash(password) ) then on next logins you compare if hash(password_provided) == stored_password_hash. If it matches, the user provided the same password. You should also use a salt.
You could give the user the ability set a pin using some library like ABPadLockScreen (you could probably find or implement something similar for Android too). You can then use the pin as the PBKDF2 input to generate an encryption key (JSONStore will do this for you when you pass the pin as the password). I would advise in favor of letting users only try a small amount of incorrect pin numbers, especially if the pin is only numeric and short, that way they can't easily guess the pin by trying various combinations. The idea here is that a pin will be easier to remember and type than their password.
FYI - There's a Stack Exchange site similar to StackOverflow but for security questions here.