I am trying to design REST APIs to support various mobile clients (iOS and Android apps). These apps will let user login using facebook login along with our own email authentication. You can refer to the diagram below to understand my design
There are two levels of authorization take place:
First one is "Client (or App) Authorization" that uses OAuth2. So when user install our app on mobile device, and starts app, then very first thing, app makes "Client (App) Authorization" as shown in above diagram (1st image). And server sends back an long-lived access_token
to client to use for all subsequent calls. Here my question are:
Q1) You can see client is sending client_key
and client_secret
and I am storing them in client_info
table. Should this secret be in plain text or it should be in decryt-able format? If I encrypt it, I still need to keep encryption key somewhere in my system. So how it will make it secure? Also in every call, decryption will be an overhead.
Q2) Is it ok to cache access_token
for the client in plain text format in redis and use that cache first?
Q3) In order to be extra safe, I am asking clients to send appsecret_proof
to make sure the access_token, they are sending belongs to this client only. It uses the same concept as Facebook https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof. And it is hash_hmac('sha256', access_token, client_secret)
Q4) We will only have our own 2 mobile app (each for iOS and Android) and not providing third party to use our API to develop other apps. That means, our client_info
table will only have two rows one for each type of apps. So is it okay, that in app code, we keep client_key
and client_secret
hardcoded? If yes, then in future when we have to invalidate and use new secret then how will we achieve replacing those info?
Q5) Since it is our own apps for couple of years, so there would be multiple access_token will get created against same client_key
and client_secret
. In order to save all of them, is it a good idea to store client_key
as key and an array of all access_tokens
as value in redis. In future, when we will open our API to third party, then this redis storage design can still scale?
=================
Later on, user decides to perform some actions on my app, for that we need user to login to his account. For that user click on "facebook login". My app gets facebook access_token
and fb user's id from facebook and pass those info to API server (as shown in 2nd diagram). API server takes that token and call facebook API to validate its access_token
. Once token is validated, server uses some metadata related to that user along with FB access token to generate our own user_access_token
, lets say utoken
. And pass that utoken
back to client to pass back in every subsequent user specific API calls. Here my questions are:
Q1) Is it ok to save that utoken
in database, user_token
table. Should this utoken
be in plain text or it should be in decryt-able format? If I encrypt it, I still need to keep encryption key somewhere in my system. So how it will make it secure? Also in every call, decryption will be an overhead.
Q2) In every user specific API calls, should I call facebook every time to check facebook access_token
is still valid? I believe I should not, as that is not going to get anything to me. Please note, Facebook is ONLY used for "facebook login".
Q3) What are the information I should encrypt to generate utoken
? I am thinking to have a hash or associative array of user's email
, user id
, role
and facebook token
and then serialize that data structure and finally encrypt it. Do you think that would be good enough. I understand its per my requirement, but as a standard or common app, are they good enough? Or is there any best practice?
Q4) Should client store utoken
in its cookie/cache? Isn't that scary?
Q5) Please note user may have multiple devices, logged in with same user credential. That means, in user_token table, we would have to store multiple utokens
for those logged-in session, while all of them will belong to the same user. Does that sound right?
A design proposal somewhat smiliar to mine REST API for website which uses Facebook for authentication