Get session variable using session uuid - lua

How am i able to get session variable using just session uuid (using lua).
So for example, we have session of leg_a (when someone connect sip phone). When other side answers, we will be within other session (session of leg_b).
Using just,
session:getVariable("variable_name")
will not help in that case because session refers to the current session.
How am i able to use lua to get variable name when i know session uuid. (so i can get other sessions variable, even we are within current session which is different)
Is there some kind of function where I am able to provide two parameteres, variable name and session uuid?

you need to execute the API call uuid_getvar.
value = api:execute("uuid_getvar", "UUID VARNAME");
(I forgot how to concatenate strings in Lua, but you should get the idea)

Related

Storing instance of a Class in a Rails session causes TypeError exception

In our Rails application we want to store an instance of a class in a session. This is because we want to set the class with some parameters when the user first logs into the application and then re-use this class by pulling it back out of the same session. When their session expires or they log out, this instance of the class is destroyed.
We're doing this to avoid using a Singleton class because that would live at Application-level and be available on different processes and stick around longer than the user's session, and have security implications due to it also being available to other users who haven't created a session yet.
So this is how it works:
session[:example_class] = ExampleClass.new(field_one: 'field_one', field_two: 'field_two')
This works fine!
However if I then do this:
current_instance = session[:example_class]
current_instance.do_something
session[:example_class] = current_instance
Whereby I am calling a method on this instance or whatever and then want to push that updated instance back into the session again so it's stored somewhere... we get this error:
TypeError in HomeController#index
ExampleClass can't be referred to from /Users/cameron/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/bundler/gems/activerecord-session_store-376ed7f7aba1/lib/active_record/session_store.rb:64:in `dump'
And that method that is failing in session_store.rb is:
def self.dump(value)
::Base64.encode64(Marshal.dump(value))
end
And the value it's trying to store is:
{"_csrf_token"=>"nrw4m2ZAECwD3TiaPZoaSt4vL1DvjO+COnBpUQGwpXs=", "example_class"=>#<ExampleClass:0x00007f7fa7b1b998 #field_one="field_one", #field_two="field_two">}
Why can I write the class in the first time around... but afterwards it throws that error?
And how we get around this?
I can't answer you fully why it fails, but I wouln't rely on implicit serialization of Ruby objects.
I would find a way to serialize the object of ExampleClass explicitly (similar to as_json) - convert to a hash, then store the hash in the session. When you need this object again, initialize ExampleClass instance with the params from session and then serialize it back to session.
I don't have an answer for why the above error happened but it turns out if you're storing an instance of a class inside the session, you're in fact storing the instance and not just the current state of the class as I originally thought it was doing.
This basically means that whenever you interact with that class and change it's attributes the session is still reading from the same instance you are interacting with and therefore has the same information without having to write back into the session.
In short you have the behaviour of a Singleton class but using a session to maintain state.

ADALiOS - how to refresh accessToken silently?

I'm using ADALiOS v3.0.0-pre.2 to connect to Azure AD B2C and authorize a given user. I successfully obtain an accessToken for the user, who gets prompted with UI to login in the process. I use the acquireTokenWithScopes method on ADAuthenticationContext instance to do so.
Somewhere down the line, I want to make sure that the accessToken I obtained earlier is still valid and hasn't been revoked. So, I use acquireTokenSilentWithScopes to check. However, I get an immediate error back saying:
Error raised: 10. Additional Information: Domain: ADAuthenticationErrorDomain Details: The user credentials are need to obtain access token. Please call the non-silent acquireTokenWithResource methods.
What's the right usage of this API such that the token gets silently refreshed or throws an error only when it has been revoked on the server side?
I've managed to beat acquireTokenSilentWithScopes into submission by making the following changes to ADALiOS v3.0.0-pre.2.
Change #1:
ADUserIdentifier has the following class method:
+(BOOL) identifier:(ADUserIdentifier*)identifier matchesInfo:(ADProfileInfo*)info
In it, there are the following lines of code:
NSString* matchString = [identifier userIdMatchString:info];
if (!matchString || [matchString isEqualToString:identifier.userId])
{
return YES;
}
For one reason or another, matchString can sometimes come back as NSNull and calling isEqualToString: method on it will throw. I changed it thusly:
id matchString = [identifier userIdMatchString:info];
if (!matchString || ![matchString isKindOfClass:[NSString class]] || [matchString isEqualToString:identifier.userId])
{
return YES;
}
This seems like a legit bug in the framework that's worth fixing.
Change #2:
When a token is received from AD, ADALiOS tries to store that value in the cache. At some point, it calls ADTokenCacheStoreItem's userCacheKey property, which is defined as follows:
-(NSString*)userCacheKey
{
switch (_identifierType)
{
case OptionalDisplayableId:
case RequiredDisplayableId:
return _profileInfo.username;
case UniqueId:
return _profileInfo.subject;
}
}
In my case, I use RequiredDisplayableId to identify users. In the switch statement above, that translates to _profileInfo.username, which, in turn, returns the preferred_username value from the user profile dictionary. For me that value is not set. So, userCacheKey returns NSNull and the caching mechanism fails.
The values that are set in the user profile dictionary are name and tid. This could be a server misconfiguration, but I worked around the issue by changing the return value of this method to _profileInfo.friendlyName (which maps to name in the user profile dictionary).
Change #3:
The ADKeychainTokenCacheStore, which I use as the concrete ADTokenCacheStoring cache of choice, exposes a sharedGroup property that allows multiple applications to share common keychain secrets. By default, sharedGroup is set to com.microsoft.adalcache. However, since the class is currently private, there is no way to override this value. Also, having that value set requires the iOS app to declare the shared group name in its entitlements. Without these entitlements properly configured, setting values into the keychain fails. So, to work around this issue, I manually set the default sharedGroup value to nil in the ADKeychainTokenCacheStore class itself. I suspect eventually this class will be exposed by the framework as public, but currently that's not the case so I had to hack into it.
Change #4
When I request an auth token from the AD server via the ADALiOS framework, I do so using a policy and a set of scopes. The framework code uses this policy/scope pair to create a lookup key and see if any tokens for that key have already been cached. If none are found, the code contacts the server as expected. Once the server returns an auth token, the framework attempts to cache the value. It constructs a brand new policy/scope key object. However, this time, it uses the policy and scope values that are returned by the server, not the ones I passed in. And, for some reason, the server returns those values to nil. As a result, the new policy/scope key that gets constructed for storage is valid but different from the one I used to look up the cached token initially. So, while the caching operation succeeds, next time I try to look up the auth token using my valid policy/scope pair, the lookup fails.
This may, once again, be a server misconfiguration issue.
Regardless, to fix the problem, I now reset the policy and scope values in the response from the server to the original values I used to generate the server request in the first place. This happens in the following method in ADAuthenticationContext(TokenCaching):
- (void)updateCacheToResult:(ADAuthenticationResult*)result
cacheInstance:(id<ADTokenCacheStoring>)tokenCacheStoreInstance
cacheItem:(ADTokenCacheStoreItem*)cacheItem
withRefreshToken:(NSString*)refreshToken
After all these changes, getting the AD auth token and refreshing it silently seems to work as expected. I'm a little worried about how much I needed to hack into the codebase to make it work. It would be helpful if some MS folks could direct me as to whether these changes were warranted or whether there is a more straight-forward solution.
UPDATE:
It turns out that you don't need to hack into ADKeychainTokenCacheStore directly (change #3 above). The ADAutheticationSettings class exposes a method for you to do so thusly:
[[ADAuthenticationSettings sharedInstance] setSharedCacheKeychainGroup:nil];
I'm Brandon Werner from the Azure Active Directory team. I answered this question here: https://stackoverflow.com/a/44170226/1232116 for the specific question asked.

Facebook returning random string instead of "state" param

I am using Omniauth for Facebook connect in a Rails app. Facebook auth connects properly, but the "state" param - through which I should be able to pass data to retrieve on callback - is returning a string I can't decipher.
For example, authorizing through "/auth/facebook?display=popup&state=19422"
ends up returning a state of "ecae4f444fb248944083db0623c9a86f3f75dff36006be7e"
Any idea why this is happening?
The state param is not supposed to be used to pass data around. That param is only to be used to stop CSRF vulnerabilities. That randomly generated string is being used in background to prevent those types of attacks.
You can pass your custom data by simply using any other param. OmniAuth is already kind enough to persist in the session any extra params you may send in your request.
So instead of passing data with
request_url?state=data
and getting it with
data = params[:state]
You can pass it with
request_url?whatever=data
and get it with
data = request.env['omniauth.params']['whatever']
And you can even omit the request and get the data with:
data = env['omniauth.params']['whatever']

need session variables in valueUnbound?

I am using valueUnbound method of HttpSessionBindingListener to release lock(an entry from the database), before session is about to expire:
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
String user = (String) event.getSession().getAttribute("currentUsr");
removeLock(user);
}
When the lock is set, I am setting up the username as a session variable.
I need this "username" in my remove lock method. But the getAttribute is throwing an exception:
java.lang.IllegalStateException: getAttribute: Session already invalidated
I need help in getting the session variable?? or is there any other way to get the username?
No, since session has been invalidated.
Although, I figured out the solution, I am setting the attribute via servlet context in
valueBound method and getting it through the : event.getSession().getServletContext().getAttribute("cUser");
it works fine. Thank You EJP
I got your point EJP, you are right , I am making it complex, I can get it from event.getValue() . +1 to your answer, Thank You.
Although, I figured out the solution, I am setting the attribute via servlet context in valueBound method and getting it through the : event.getSession().getServletContext().getAttribute("cUser");
So.. You are storing session scoped data in the application scope. Do you realize that this way the data is shared among all visitors of the webapp? Visitor X would then see the attribute set by visitor Y which has visited the website at a later moment. It makes the problem only worse.
Anyway, as to the concrete problem, as the exception message is trying to tell you, the session has already been invalidated at that point. There are two ways to solve this:
Make currentUsr a property of the class which is implementing HttpSessionBindingListener, so that you don't need to grab it as a distinct session attribute.
Use a HttpSessionListener instead. The sessionDestroyed() method is called right before invalidation, so you should still have access to all attributes.

Selectively prevent Session from being created

In my app, I have an external monitor that pings the app ever few minutes and measures its uptime / response time Every time the monitor connects, a new server session is created, so when I look at the number of sessions, it's always a minimum of 15, even during times where there are no actual users.
I tried to address this with putting the session creation code into a filter, but that doesn't seem to do it - I guess session automatically gets created when the user opens the first page?
all() {
before = {
if (actionName=='signin') {
def session = request.session //creates session if not exists
}
}
}
I can configure the monitor to pass in a paramter if I need to (i.e. http://servername.com/?nosession, but not sure how to make sure the session isn't created.
Right now there is nothing you can do to prevent the session creation. See: http://jira.codehaus.org/browse/GRAILS-1238
Fortunately, until you are hitting high numbers of requests per second, this isn't a huge problem. One thing we did to get around the false data in our "currently active users" report, was to log the sessions to the database. We create a session record only when the user logs in. Then on specifically mapped URLs, we will "touch" that session record to update the last accessed time. The session record keeps track of user agent, IP, etc and is useful for many reasons. Doing something like this would get around the bogus session count.

Resources