I am trying to find a solution to prevent race conditions in my application logic (specifically when renewing an OAuth access token) and my back-end database happens to be mongodb.
Coming from a MySQL background, I'm used to using GET_LOCK and it's related functions to handle blocking in PHP. Does Mongo have any analog to MySQL's GET_LOCK function, or will I have to use PHP's file locking or something similar?
Is flock() a good (or proper) alternative for this situation, or is that meant only for use when reading and writing to files?
Edit:
The race condition I am trying to prevent is the following:
Instance A notices OAuth access token nearing expiration
Instance B notices OAuth access token nearing expiration
Instance A requests refreshed OAuth access token from remote server and obtains one
Instance B requests refreshed OAuth access token from the same server and is rejected (server potentially invalidates access token from step 3 as security precaution)
Instance A saves result back to database
Instance B saves result back to database
If you want to simulate a named mutex or lock using MongoDB, I would suggest using findAndModify by creating a special collection for it and having a document, you can even call it db.my_lock.
db.my_lock.save({"IMREFRESHINGAUTHTOKEN":false});
Now, between steps 2 and 3 add a findAndModify to grab the "lock":
db.my_lock.findAndModify(
query: {"IMREFRESHINGAUTHTOKEN":false},
update: {$set: {"IMREFRESHINGAUTHTOKEN": true}, ...}
);
If you get to the "lock" first, you will get back this object (and you will get to set the first field to true - I recommend setting a second field with timestamp or connection number or process ID or some other identifier which will allow cleaning up after a crashed process so it won't hold a lock forever).
If you "lose" the race you will get back nothing that matches "IMREFRESHINGAUTHTOKEN":false and you'll know you lost the race and give up (or check the timestamp of the lock and maybe try to see if it's old and stale).
This describes a stand-alone single lock on the whole "collection" - of course you can implement this as an extra field on the stored OAuth token and have as many of them being refreshed at a time as there are threads noticing they are expiring.
Hope this helps.
Related
Two HTTP requests received by a server with a PHP app that uses Laravel 5.2. Both fired the same type of Event. Both events intercepted by a single Listener.
Q1: Will events processed one after another in the order they were received by Listener (synchronously) or they will process concurrently?
Q2: Does there a way (or to do it in another way if Q1 answer is sync) synchronize any function between requests? I mean to be sure that no matter how many requests were received simultaneously, the function can be executed only by one request at the time
UPD. The issue what I'm trying to solve: my app should authenticate in a 3d party service. This is critical to establish only one session which will be used by other parts of the application. I want to store an access token for a session in DB. So this operation is not atomic:
1. Try to get token from DB.
2. If token does not exists:
2A. Authenticate and receive token.
2B. Store token in DB.
3. Return token
Events are not a good way to fire functions in series. However, in PHP (and also Javascript) event callbacks are executed in the order their events have been triggered (so 1 -> 2 results in a -> b).
You'll have to elaborate on why you want to execute a function only by one request at a time. Likely you are looking for a locking or transaction mechanism, which is a RDBMS/SQL feature that prevents editting of records while they have not yet been saved. That way, when 2 requests happen to reach the same PHP function at the same time, you can have them wait on the database until a certain transaction completes, such that no overlap in reads or writes can take place.
See https://laravel.com/docs/5.8/queries#pessimistic-locking and https://laravel.com/docs/5.8/database#database-transactions for the Laravel implementation. There is more information on the MySQL website (assuming InnoDB is being used) :
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
I am trying to work out what is the best and most efficient way of storing authentication token to get instant access next time I make a request.
Usually my initial request to obtain authentication token takes longer (1.5 seconds). Which means I can save a lot of time if I do that only once. All requests are done via CURL library (in my case its Guzzle but that does not matter).
My application is written in PHP and my options are
Storing token using Redis and access it quickly - it should be quick as it Redis works "in memory"
MySql - it is installed already and I may just need to create additional table
Any other ideas?
Of course whenever I store authentication I am going to encode it and request for a new token once a day (not sure whats current ttl for the token but it doesnt matter).
I do care about access time (the quicker "read" the better)
Maybe it's a stupid question. But anyway here is my problem. I have multiple classes in my project.
At the beginning the constructor of the class Calculate($param1, $param2...) is called.
This Calculate class is called multiple times via jQuery Events (click, change..) depending on which new form field is filled.. The prices and values are calculated in the background by php and are represented on the website via AJAX (live while typing).
The connection between the AJAX and the Calculate class is a single file (jsonDataHanlder) this file receives the POST-values from the AJAX and returns a JSON-String for the website output. So every time I call this jsonDataHandler a new Calculate object is beeing created. With the updated values, but never the first created object. I am experiencing now multiple problems as you may can imagine.
How can I always access the same object, without creating an new one?
EDIT: because of technical reasons, I cannot use sessions..
Here is the php application lifetime:
The browser sends an http request to the web-server
Web-server (for example Apache), accepts the request and launches your php application (in this case your jsonDataHandler file)
Your php application handles the request and generates the output
Your php application terminates
Web-server sends the response generated by php application to the browser
So the application "dies" at the end of each request, you can not create an object which will persist between requests.
Possible workarounds:
Persist the data on the server - use sessions or the database (as you said this is not an option for you)
Persist the data on the client - you still create your object for each request, but you keep additional information client-side to be able to restore the state of your object (see more on this below)
Use something like reactphp to have your application running persistently (this also can be not an option because you will need to use different environment). Variance of this option - switch to another technology which doesn't re-launch the server-side application each time (node.js, python+flask, etc).
So, if you can't persist the data on the server, the relatively simple option is to persist the data on the client.
But this will only work if you need to keep the state of your calculator for each individual client (vs keeping the same state for all clients, in this case you do need to persist data on the server).
The flow with client-side state can be this:
Client sends the first calculation request, for example param1=10
Your scripts responds with value=100
Client-side code stores both param1=10 and param1_value=100 into cookies or browser local storage
Client sends the next calculation, for example param2=20, this time the client-side code finds previous results and sends everything together (param1=10¶m1_value=100¶m2=20)
On the server you now can re-create the whole sequence of calculation, so you can get the same result as if you would have a persistent Calculate object
Maybe you should try to save the values of the parameters of Calculate object in database, and every you make an AJAX call you take the latest values from the DB.
I've built a class that provides some basic "can I do this?" authorization functions for my site, stuff like "can this user view this resource?" or "can this user add an image?"
So the class object is instantiated in quite a few pages (potentially, every page that has a user interaction) using $authorize = new myAuthorizationClass();
The myAuthorizationClass class then looks up the user's ID and check their access level.
I can then say something like
if ($authorize->canAddImage()){
// do image add stuff
}
Is it possible, secure and "best practice" to store this $authorize object into the session? Is there another way to avoid the overhead of building this auth object on every page, and doing the DB interactions etc?
I don't think it can be as simple as just saying "set the user's auth level to A, B, or C, and set that in their session!" since their access to a particular resource depends on who owns the resource, what role the user has in the site, etc. and we have to check a few different things depending on what type of resource is being accessed.
Thanks
Storing user data within a session (not cookie) is acceptable, as this data is stored on the server side and randomly generated for every user, and as long as your session handling storage is protected, will not be accessible to other users.
If you want to reduce database load by not having to look up the users role/access for every page request, you may want to consider pulling the information upon successful login then storing the (in serialized format) into a session variable. Then, for protected resources, you can unserialize the data stored within the variable, do your check, and proceed accordingly.
I believe it is considered bad practice to store authorization data within sessions.
The reason is quite simple, while the data itself is stored on the server side, where it's safe, the weaker link is actually still (like always) on the client.
The server must identify the client who owns the data somehow, that is usually done in a form of a session_id cookie sent to the user. That cookie will be sent to the server in each request, and the server will be able to figure out who you are by the (very random) ID.
However, over an unsecured WiFi (or a computer), that cookie can be rather easily stolen by an attacker, which will cause the server to identify him as you.
There is no simple way around this, other then SSL and user education. If your site requires very high security (such as money transactions or critical database operations), inform the users about it and advise them to confirm their local security measures.
Also, if your site deals with critical database operations, don't allow anything critical (deletion, table drops etc) done from the web application. Only via the root user.
My question is if a user comes along and uses an Object Oriented PHP application, how are those objects tied to the user and what happens to them once the user leaves?
I understand how OO
PHP is a shared-nothing architecture, which means that for every HTTP request the browser makes, the application starts with an empty sheet (so far as PHP internals such as variables and loaded classes are concerned). Every PHP object disappears at the end of the request. Permanent data needs to be stored elsewhere (typically a database plus possibly a key-value based cache such as memcached). How user-related data is handled in those outside storages depends entirely on the application.
Objects are not really ever tied to a user... It sounds like you are talking about sessions variables. You can store some information for an individual user by adding it to the php $_SESSION variable like this for example: $_SESSION['user_id'] = 5. Once the user leaves, that information will still be accessible until it expires (You can set the expiration date, or typically it will expire when the user closes their browser). For most web applications dealing with users, the user will be asked to log in and when they do, information about that user gets stored in the session. This allows a user to stay signed in across multiple pages of the pages application. Then if the user decides to log out, this is when you unset or destroy that session data.
When an HTTP request is received, PHP is fired up, sets up the runtime environment for your code and runs it. Afterwards all of this is torn down, to be re-created from scratch on the next request.
So unless you take explicit steps to persist your objects (or any other type of variable, really) to e.g. disk and then read them back on a subsequent request, there will be no trace of objects created in the past at all.