PHP REST API Key and User Token Authentication - security

I wanted to check with you guys if my API Key and user Authentication scheme makes sense or not. My server side code is in PHP and the Database is MySQL. This is the scheme I have in mind:
I am implementing a REST API in a backend server that will be called by a Mobile App (for now). At this point, I only want known Mobile Apps to connect to this API. So I am using a one-time API Key that has been given to the Mobile App during installation. Every request from the App passes the API Key that my API checks before going further. This Key is stored in a Database table. This completes my API Key checking and seems to allow only known Apps from calling my APIs.
Next, I also have certain services after calling the API which only authenticated users are supposed to get access to. For this, the Mobile App logs in with a Username and password which is authenticated in the User table of my Database. If it passes, the server generates a User Token and passes it to the Mobile App. The User Token is also saved in the User table against that User. All subsequent requests from the App (which requires user authentication) passes this User Token which is checked in the User table in the Database for User Authentication. If the Mobile App logs out, this User Token is deleted from the User table. I also have provision to add "TimeToExpire" for this User Token which I will implement later.
I would be really grateful if you guys could tell me the following:
Does the above structure makes sense for App Authentication and User Authentication?
I am a little lost as to what will happen if I ever need to change the API Key (for whatever reason). Not sure how that will be sent to all the Apps. Google Messaging seems like one possible way to handle that.
For the App Authentication, does it make sense to keep the API Key in a Memcached object? Since all requests from the Apps are authenticated, I don't want to go to the DB everytime. And pros/cons?
Along the same lines, does it also make sense to have the User Token in a Memcached object as well? Pros/cons?

Related

validate userId given by okta

I have an app which consists of frontend server and a backend server.
front end server connect to corporate OKTA mechanism so that user logins through their corporate ids into my app.
After this step, frontend server connects with some backend work at backkend server (node js). Their it passes in the request body the user id so that we can finally log that the below processing is happening due to user X.
Now suppose user A logs into the app . Now during the APi call to backend server, he can modify the arguments being passed to the api and somehow change the userID.
Is there some way by which backend server validate that userID is not compromised ?
Regards
If your front-end app uses OIDC to log a user in, then you should be able to get back an id_token, which has user identity in it. You can pass this token to your back end app for API calls. This approach is not ideal though, as your backend will still have issues with trust, as it does not know if the token presented by the front-end app is a legitimate one and not stolen.
Other way is to harness traditional authorization_code flow (again, assuming you can do OIDC with you company's identity provider). There your back-end would retrieve the tokens for you directly from authorization server and can get a user's identity from it. Based on that it can then create a session and embed user info into it. It's a bullet proof approach lacking trust issues from above.

Express backend with Firebase auth and my own database to persist users

I'm creating a system where the client in React will implement Firebase authentication, so Firebase will signIn users, but I have a backend server with Express and I need those users in my own DB (postgresql). I can use firebase-admin in the backend to verify the token sent from the client on each request, and from this token, extract user data, as well as its uid. So I could create a user in my own database with these information.
The problem is that since I'm not handling user signup in my own server, I would have to add a verification in the authentication middleware. Each time the user makes a request to the server, the backend verifies the token (with firebase-admin) and checks if the user already exists in my own database, because if it doensn't, then create this user.
I wanted to see if there is another way to handle this, since every request is not only going to verify a token but also query the database looking for the user.
Verifying the ID token in the backend code is pretty much how all Firebase backend services handle it too. They receive the ID token, request the public key from the project, decode the token, and then validate that the user is authorized for the action they're performing.
You seem to want to create a record for the user in some shared database however, which I'd typically recommend against as it affects scalability. The only thing most Firebase backend services cache is the project keys (as those require an expensive HTTP lookup) and recent encoded/decoded token pairs. But there are caches on each server separately, so it's quite different from having shared state in a database as you seem to want.

Retrieving user data securely when user authenticates

After spending some time reading about authentication and noticing it is pretty hard to do it well, I have decided to use firebase-authentication to authenticate my users in my vue app.
I'm listing the technologies and flow I use in this app to show each part interaction and clear things up:
I use Vue for my client javascript client
The client log-in users using firebase-authentication.
When user log-in, a call to a node.js rest api is done and a json is retrieved with its user data.
When the data is retrieved by the client, the app shows some parts and hides other depending on user privileges
So, in my Vue application I show a custom login form and use it to authenticate users through firebase. After the user log-in, I retrieve some data from my own server (just a json with different user config values) that defines how the user can interact with the app (For example, what he can or can't do in my app).
How can I retrieve this information and use it in my client app in a secure way?. I mean, as an example, say I have a piece of information in that JSON that defines if the user is a regular or admin user. How can I avoid users to modify the response from the server and elevate privileges?
There isn't anything you can do to prevent client side DOM manipulation. If it's accessible via JavaScript, it's accessible to the user. It's up to you to implement your application in such a way that sensitive information and/or functionality is not dependent on client side security (if such a thing truly exists).
What you can do is prevent unauthorized access on the server. This is the purpose of defining scopes, ACLs, etc. If a savvy user does modify the response data and, say, change their role from user to admin, your response should not contain anything meant for admin users only. Rather, that information should only be accessible after making a successful API call where your server code has authenticated/authorized the request.
Never trust the client when it comes to security. That must be done on the server.

how to secure azure mobile service / html - javascript

When I call an oauth provider like gmail and I get the token back, how can I make sure that all future calls I make are from that same client that did the authentication? that is, is there some kind of security token I should pass pack? Do I pass that token back everytime?
For example, if I have a simple data table used for a guest book with first,last,birthdate,id. How can I make sure that the user who "owns" that record is the only one who can update it. Also, how can I make sure that the only person who can see their own birthday is the person who auth'd in.
sorry for the confusing question, I'm having trouble understanding how azure mobile services (form an html client) is going to be secure in any way.
I recently tried to figure this out as well, and here's how I understand it (with maybe a little too much detail), using the canonical ToDoList application with server authentication enabled for Google:
When you outsource authentication to Google in this case, you're doing a standard OAuth 2.0 authorization code grant flow. You register your app with Google, get a client ID and secret, which you then register with AMS for your app. Fast forwarding to when you click "log in" on your HTML ToDoList app: AMS requests an authorization code on your app's behalf by providing info about it (client ID and secret), which ultimately results in a account chooser/login screen for Google. After you select the account and log in successfully, Google redirects to your AMS app's URL with the authorization code appended as a query string parameter. AMS then redeems this authorization code for an access token from Google on your application's behalf, creates a new user object (shown below), and returns this to your app:
"userId":"Google:11223344556677889900"
"authenticationToken":"eyJhbGciOiJb ... GjNzw"
These properties are returned after the Login function is called, wrapped in a User object. The authenticationToken can be used to make authenticated calls to AMS by appending it in the X-ZUMO-AUTH header of the request, at least until it expires.
In terms of security, all of the above happens under HTTPS, the token applies only to the currently signed-in user, and the token expires at a predetermined time (I don't know how long).
Addressing your theoretical example, if your table's permissions has been configured to only allow authenticated users, you can further lock things down by writing logic to store and check the userId property when displaying a birthday. See the reference docs for the User object for more info.

How to authenticate requests using ServiceStack, own user repository, and device ids?

I'm building a mobile app and a ServiceStack web service back-end. The Authentication stuff in ServiceStack looks great but easy to get lost in its flexibility - guidance much appreciated. I'll be using my own db tables for storing users etc within the web service. I'd like to have a registration process and subsequent authentication something like this:
the user initially provides just an email address, my web service then emails a registration key to the user
the user enters the key. The app sends to the web service for registration: email, key & a unique device identifier.
the web service verifies the key and stores the email & device id. It responds back with an auth token that the app will use for later authentication.
Then subsequent web service requests would provide the device id and auth token (or a hash created with it). The app is not very chatty so I'm tempted to send the authentication details on each web request.
Question 1: Should I hook into ServiceStack's registration API or just add a couple of custom web service calls? e.g. without using ServiceStack's registration I would:
post to a registration web service with the email address and device id. My web service would send the registration email with a key and add a record to the user db table.
when the user enters the key it would again post to the registration web service, this time also with the key. My web service would validate the key and update the user table marking the user as registered, creating and recording the auth token & returning it to the caller
subsequent requests would be sent using http basic auth with the device id as username and the auth token as password. The service is not very chatty so creds will be sent with each request.
I'll implement a CredentialsAuthProvider that'll get the creds with httpRequest.GetBasicAuthUserAndPassword() and validate them against the db data.
But it feels like I should use registration built in to ServiceStack.
Question 2: What's wrong with passing the authentication details with each request? This would make it easier for composing my app requests but it doesn't seem 'done' based on the ServiceStack examples. Presumably that's because it's inefficient if you have lots of requests to need to re-authenticate every call - any other reasons? My app will only make a single web request at most every few minutes so it seems simpler to avoid having sessions and just re-auth each request.
Question 3: Am I on the right track subclassing CredentialsAuthProvider?
Question 4: Is there any point using the auth token to generate a hash instead of sending the auth token each time? All communication will be over https.
Answer1: It will be OK. if you give multiple call as per requirement. Normally authentication works based on cookie, now you can store it on client and/or on server and match the user with it. Again here if you are using device you, can always use device instead of user to map and authenticate user. Based on your requirement.
I will prefer to use provider as it hides many details which you need to do manually instead. You are on right track. There are many blogs specifically for authentication and how to create custom authentication with service stack. If you like let me know I have book marked some will give it you. Best way to search latest one is checkout twitter account of Servicestack.
Answer2: This is again, I say as per requirement. Now if your user will be in WIFI zone only. (Mostly true for business users), then there is not limit for calls. Just give a API call and do the authentication in background. Simple JSON token will not hurt, It is few bytes only. But again if you have big user base who is not using good internet connection then it will be better to store authentication detail on device and check against that. Just to save a network call. In any case network call is resource heavy.
Answer3: Yes you are on a right track. Still check out blog entries for more details. I don't remember the code snippet and how it works with last update so I am not putting up code here.
Answer4: This is answer is little complicated. Passing data over https and saving user from Identity fraud is little different thing. Now, if you are not generating auth token (hash based value) then you can pass user also over the http or https. Now, this can be used by another user to mock first user and send data. Even data is being passed through https but still data is getting mocked. Hashed based value is used to avoid this situation. And also there are couple of other business use cases can be covered using auth token.
Please let me know if I have understand you questions correctly and answered them?? or If any further details is required??

Resources