DataSnap and Database Connection / Login - delphi

I am trying to work out the "right" way to establish a connection to my database from the server of my DataSnap application.
Each (most) of my tables in the database have fields (whose values are set via a trigger on insert and update) called Updated and Created (this is the current time stamp when the record is written) and updated_by and created_by which (should) contain the currently logged in user.
I want the user to 'login' from the client side such that these fields reflect the user who has logged in (and by extension, I'll get user authentication from the database, not just from the server). I can handle the authentication to the server itself from the client ok handling the OnUserAuthenticate and OnUserAuthorize events on the server. I am trying to then pass the credentials to my database so that the triggers can set the fields stated above correctly.
So what is the way to approach this scenario? I am wonder if the DSAuthProxyUser and DSAuthProxyPassword from the client can be used but I can't find much (any) documentation on how I would use that. Do I establish a new connection for every user who connects? This seems most logical to me. I'm not going to have a lot of concurrent users. Tops 30. Most likely 5-10. But what is the "normal" way this is done? I don't want to (hope I don't have to) pass in the username to each of my insert/updates to set the values in the tables.
I hope I have explained my situation clearly.
Thanks

I haven't used it yet, but it looks to me that the RDB$SET_CONTEXT() and RDB$GET_CONTEXT() introduced in Firebird 2 are what you need. Using these functions, you can set (and get) additional information specific to the user session (namespace USER_SESSION) or the current transaction (namespace USER_TRANSACTION). You can also retrieve additional system information for the current session (namespace SYSTEM), but that is probably not relevant for your case.
What you would need to do is call the RDB$SET_CONTEXT() method in that OnUserAuthorize event, eg using (as a query):
SELECT RDB$SET_CONTEXT('USER_SESSION', 'actualuser', '<name of user')
FROM RDB$DATABASE
Here 'actualuser' is the context variable we use. In your triggers you can then retrieve the name (assuming PSQL, with a declared variable actualuser)
actualuser = RDB$GET_CONTEXT('USER_SESSION', 'actualuser');
You can then use actualuser in the rest of your trigger. Just make sure you also account for the case where the context variable is not set (eg an administrator making direct changes to the database or something like that).

Firebird has the CURRENT_USER keyword which can be used in SQL.
The example below is based on http://www.firebirdsql.org/refdocs/langrefupd15-current_user.html
create trigger bi_customers for customers before insert as
begin
New.created_by = CURRENT_USER;
end
To have the user name for updates, simply declare a before update trigger like
create trigger bi_customers for customers before update as
begin
New.updated_by = CURRENT_USER;
end
This solution requires a 1:1 mapping of database users to external users. In the most simple implementation, it means that the DataSnap session authenticates the user credentials against the database.
In your description however, it seems to be a two step authentification (first against the DataSnap layer, then against the database). I am not sure how this can be done regarding safe password handling, and if you plan to have a separate user/password table only for the first authentication stage (DataSnap) and a user login mapping from DataSnap to database as some kind of 'decoupling'.

Related

Can I safely tell Rails to remember the result of an expensive instance method?

My current_user has a has_privilege? method which calls the database to check whether this user has a certain admin privilege or a superceding one (system is similar to Wordpress privileges). As has_privilege? gets called several times per page, can I tell Rails to remember the result for as long as the instance exists, using the method explained at How can I save the value of an instance method?, or would this make the app insecure? It's a bad idea to put this information into the session variable or cache, right?
as long as the instance exists
It depends what you mean by that.
Rails treat each HTTP requests in a separated process so you can cache the has_privilege? method output for the current request (so calling many times the method will query the DB only the first time), but on the next request, it will be executed again and then cached (and actually you want that as you may change the permissions and don't want the user to keep the old permissions).
In order to do so you can use this simple trick:
class User < ActiveRecord
def has_privilege?
#has_privilege ||= begin
# You code here. The returned value will be cached in #has_privilege.
end
end
end
So the first time the method is called, #has_privilege is nil for your instance of the user, so the || will its right side part which is the = begin ... end.
Excepted if the code return nil, the value will be assigned to #has_privilege.
On the next call, #has_privilege is no more nil, therefore || will no trigger its right side part and return immediately.
I need a cross request cache
In this case, you have to go with JWT and save the value in the token.
JWT is a token generated and signed by the server, and it must be sent back in to each requests, otherwise the server will reject it.
As only the server can sign the token, in the case the user tries to change it, the server will reject and sign out the user.
You can read more on their website, it's quite simple to use.

Ruby Rails: passing session info in a thread to a Oracle db connection

Our app holds a user id in the session and we need to pass that along to an oracle connection so that the user id can be logged in oracle with each user operation. This needs to be done per request. The OCI8 gem we are using has a client_identifier property we could set. We just need to know how and where.
Can we access a threads database connection in a method in the application controller (triggered in a before_filter) and if we did would the connection expose its adapter's methods and/or attributes? Would those attributes be passed with a subsequent ping or sql operation?
Something like this:
ActiveRecord::Base.connection.client_identifier = session[:user]
Maybe?
Thanks
Looks like we needed to grab the raw connection which allowed us to set the client id in a before filter in the application controller. Kinda like this:
ActiveRecord::Base.connection.raw_connection.client_identifier=user_id

Adding User-Agent & IP to a stored Session -RecordNotSaved -Rails

I'm currently building an in-house analytics system which tracks where a visitor clicks throughout each session, whether they are logged into a User account or are a visitor without an account.
I am currently saving my sessions to the database thanks to changes made through sessions_store.rb, however in addition to the session_id, I am trying to figure out how to add both UserAgent details and a visitor's IP to the sessions table.
I've tried a couple solutions but all have failed - my current solution appears to be the closest, however I keep encountering an ActiveRecord::RecordNotSaved error after updating the Session's attributes.
I am currently using a before filter in application controller:
before_filter :set_useragent_and_ip_in_session
def set_useragent_and_ip_in_session
if session
sess = request.session_options[:id]
#session = Session.where(session_id: sess).first
#session.update_attributes(:ip=>request.remote_ip, :user_agent=>request.user_agent)
#session.save!
else
end
end
I've inserted a debugging statement in my views and have played around the code in pry - the #session is valid and displays the #session.user_agent properly .... however when saving to the DB it justs rollsback.
When I use save!, I receive a Completed 422 Unprocessable Entity in the logs in addition to the following (pasted to gist to conserve space):
https://gist.github.com/anonymous/8019c2426334f395a5fd
Thanks! Any help would be very appreciated.
I would recommend rethinking your schema. A session can last many requests and you want a record per request. Also notice how your moving data off the request object and trying to store them into a session table. Instead make your very own request table and make a before filter that moves all the data you want from the request object to the request table. Now a session will have many requests.
I'm not sure why your record isn't saving however I would wager naming a model Session is conflicting with rails. By that same token when you make your request table you should give it a unique name like maybe SessionMeta and RequestMeta. Then SessionMeta could have many RequestMeta.

Passing a token securely from one controller method to another

I want to generate a random token for my user. For UX reasons, I want to generate this token in MyController#new in order to show it in new view. Then I need to pass it to create method. However, I want to prevent user from changing it.
I know of 3 ways to do it:
pass it as hidden field
pass it through sessions
write it to database, marked as incomplete, then set it to complete in create method
The first two approaches are not secure, while the last is overkill.
Is there a way to securely pass a parameter from new to create method in controller?
Sessions in Rails and # and above are very very secure because they are hashed. The official library says there are no practically evidences of session hash been compromised so the user can only delete that token from the browser but they can't change it to a logically correct value.
What you can do is save the value in sessions and make a hash value yourself from that token and save it also in session then on the receiving side you can regenerate the hash from the session and verify the value.
no user can edit both the session values that they match. If its not matching you can discard the values and throw to an error page.
I hope i answered you, if there is any misunderstanding pls ask.

sfGuardAuth across multiple apps

I've got 3 apps: Backend, Frontend and Members.
And I've got 2 credentials: Administrators and Members.
Administrators are imported by default but Members are created in the Backend.
When a Member is created, an event handler also inserts this Member as a sf_guard_user and of course, the proper relations in sf_guard_user_group and sf_guard_user_permission.
That's the boring part, now the fun:
Frontend is not secured, but Members is and using these credentials: [administrator, member].
According to all this, Members created in the Backend that also get inserted (correctly as far as I can tell) should be able to login to the Members secured app, since they get the member group/permission/credential.
This is not happenning, the only ones that can login to the Members app are the administrators, which is not wrong, but either is the fact that correctly created Member users can't login to it.
The error thrown by the guard is the classic: The username and/or password is invalid.
Now that I edit the error, the salt comes to mind: How would one emulate the inserting of the salt as the guard does it? Maybe that's what I'm not inserting correctly (or inserting at all) and thus the password invalid error (and in fact everythine else I've described is ok! omg)
And that's my problem.
Thanks in advance :)
[administrator, member] means both are required, I believe.
I think you want [[administrator, member]] for the credential requirement.
Also, yes, you will want to make sure you use a salt, and set the algo.
parent::_set('password', call_user_func_array($algorithm, array($salt.$password)));
Salt before password, as well.

Resources