I have a simple web app built using Sinatra, with sessions enabled.
If I am understanding correctly, the session data is stored in an encoded cookie. As the session data changes, the value of the cookie will change also.
I need a unique session identifier that remains constant through the entire session. Is there such an identifier. Or must I create my own unique value and store it in the session myself?
Thanks!
EDIT: In a comment below I thought of a useful comparison. If I had a Java servlet, I would use the JSESSIONID as a unique identifier. I need a Sinatra equivalent to the JSESSIONID.
Because this is one of the first Google results for the subject and it contains no actual examples, here is a simple way to create your own SESSION_ID. We're relying on probability and cryptographically secure randomness to keep our IDs unique.
This is the only thing I put in my cookies. I keep all the other data on the back end to prevent anyone from tampering with it.
require 'sinatra'
require 'securerandom'
# The configuration here is just an example. Use your own secret, etc.
use Rack::Session::Cookie, :key => 'SESSION_ID',
:expire_after => 60*60*24, # == one day
:secret => 'This one time, at band camp...'
before do # Before every request, make sure they get assigned an ID.
session[:id] ||= SecureRandom.uuid
end
get '/' do # Show off your new ID.
"Your ID is #{session[:id]}"
end
In a sinatra app if you print out session.keys, you'll see there is a "session_id" that contains the unique id for the current session. You can access this 64 byte string as session["session_id"].
As the session data changes, the value of the cookie will change also.
This is true only if you're using cookies to store your session data, which is the default session storage used by sinatra. More details at http://rubydoc.info/github/rack/rack/master/Rack/Session.
I need a unique session identifier that remains constant through the entire session. Is there such an identifier. Or must I create my own unique value and store it in the session myself?
You can access sinatra session id using the id instance method on the session instance of Rack::Session::Abstract::SessionHash. More details at http://rubydoc.info/github/rack/rack/master/Rack/Session/Abstract/SessionHash#id-instance_method.
Example:
require 'sinatra'
configure do
enable :sessions
end
get '/' do
session.id
end
From what I can tell JSESSIONID is used to pass the session around in a query string, and Sinatra doesn't have something like that, at least not easily accessible. Sinatra uses Rack for session management, and by default uses a cookie to store all session data. There are other session options in Rack, like memcached, where a unique session id is stored in a cookie, but even there Rack abstracts that away so you don't ever need to see the session id (though it is still accessible, see the documentation).
If you want to go that route then look into messing with the Rack middleware in Sinatra, but if all you need is a unique id, then it would probably be easier to generate one yourself and store it in the session.
Related
A couple of tutorials on oAuth use the Flask session to store state parameters and access tokens in the flask session. (Brendan McCollam's very useful presentation from Pycon is an example)
I understand that Flask stores the session in cookies on the client side and that they are fairly easy to expose (see Michael Grinberg's how-secure-is-the-flask-user-session). I tried this myself and was able to see the token the expiration, etc.
Is it correct to store the state and tokens in the flask session or they should be stored somewhere else?
Code example:
#app.route('/login', methods=['GET'])
def login():
provider = OAuth2Session(
client_id=CONFIG['client_id'],
scope=CONFIG['scope'],
redirect_uri=CONFIG['redirect_uri'])
url, state = provider.authorization_url(CONFIG['auth_url'])
session['oauth2_state'] = state
return redirect(url)
#app.route('/callback', methods=['GET'])
def callback():
provider = OAuth2Session(CONFIG['client_id'],
redirect_uri=CONFIG['redirect_uri'],
state=session['oauth2_state'])
token_response = provider.fetch_token(
token_url=CONFIG['token_url'],
client_secret=CONFIG['client_secret'],
authorization_response=request.url)
session['access_token'] = token_response['access_token']
session['access_token_expires'] = token_response['expires_at']
transfers = provider.get('https://transfer.api.globusonline.org/v0.10/task_list?limit=1')
return redirect(url_for('index'))
#app.route('/')
def index():
if 'access_token' not in session:
return redirect(url_for('login'))
transfers = requests.get('https://transfer.api.globusonline.org/v0.10/task_list?limit=1',
headers={'Authorization': 'Bearer ' + session['access_token']})
return render_template('index.html.jinja2',
transfers=transfers.json())
I think some tutorials over-simplify in order to show simpler code. A good rule of thumb is to use session cookies only for information that MUST be known by your application and your user's browser, and is not private. That normally translates into a Session ID and possibly other non sensitive information such as a language selection.
Applying that rule of thumb, I'd suggest the next to each of the tokens:
Authorization Token: this data is by definition known to both the user and the application, so it shouldn't be a security concern to expose it in the cookie. However, there really is no need to keep this token once you're given an access code, so I advice against keeping it locally or in your cookies.
Access Code: this data must be considered secret, and must only be known by your application and the provider. There is no reason to make it know to any other parties, including the user, therefore it should NOT be included in cookies. If you need to store it, keep it locally in your servers (perhaps in your database, referencing your users session ID).
CSRF State Token: this data is ideally included as a hidden form field and validated against a server side variable, so cookies seem like an unnecessary complication. But I wouldn't be concerned about this data being in a cookie, since it's part of the response anyways.
Keep in mind there are extensions such as flask-sessions, with which practically the same code uses server side variables instead of cookie variables.
Our apps are using client variables management for unique identify a website visitor and eventually store it as the ID of an e-commerce order, for example.
Our customer orders table saves strings like "10000032:98517605:77134665" (cfid+cftoken) as its unique ID.
Now we need to get rid of client variables, so no more "CLIENT.cfid" in our code.
First thing that comes up to my mind is to simply replace that with "SESSION.cfid" and "SESSION.cftoken". But the big doubt is:
Will the generated id and token still be univoque against the existing ones?
Is it possible that making such a change will result in having "10000032:98517605:77134665" re-generated?
How can I make unique visitor ids, considering existing ones too?
I would set a new session value onSessionStart that you can guarantee would be unique. So in the onSessionStart method of Application.cfc, you can set something like:
<cfset Session.CustomerID = CreateUUID() />
With that, when the session begins, a UUID (guaranteed to be unique) will be put into the session scope. You can then use that for whatever you need. If this needs to be persistent, you could write it out to a cookie as well (since sessions don't persist long term like Client variables do).
If I am handling authentication manually, and am setting session like so:
session[:user_id] = authenticated.user.id
user_id does not show up in my session hash when viewed from another namespace. In this instance I have a namespace :api, and session doesn't show up at api/show/current. How do I set the session hash to be viewed in both namespaces?
The session is completely independent from namespaces, maybe there is something else wrong with your app?
where do you set the user_id?
maybe providing more code helps
I am working on a friend reference function, so I pass the user id through the url like this:
www.example.com?fid=22
I need to set this as a session or cookie with access to all modules in Drupal 6.
If i set the session it returns for the particular module. Setting the cookie is not working at all.
$user->new_property works only on the particular page where it is set, if I move to another page there is no new_property in $user variable object list.
If you want to save a variable in a users session, you can in Drupal (PHP) use the super global varaible $_SESSION.
$_SESSION['fid'] = $_GET['fid'];
The above code is an example of how this could be done.
Since you are getting the info from the URL the user can change it as his whim. So be careful what you use such data for and never trust it blindly. It could become anything, as the user always freely can alter the url any way he want.
I am working on a guess-a-number game with Ruby that will be online. I know I need to pass the SESSION somehow to keep the number that they are guessing, but I have tried a ton of methods with no luck. My code is here.
Any thoughts on what I can do get this code working? I have declared each of my sections.
A session is, usually, a combination of a cookie (session cookie), or some session id tacked onto the url, which has some unique identification of the current "session" and a way to save the data on the server and retrieve it when given the id from the cookie.
So I would set a cookie based on for example ip + Time.now.to_i and then save that ID and the values I want set into a database or a text file on the hard drive. Note that there is probably a lot better ways to create a unique ID but aim for the simple stuff first. :)
I also recommend that you look into CGI::Session which you require with require 'cgi/session'.