I wish to implement sessions in webapp2. From research, I have found this code sample using webapp2_extra.sessions, and a few articles which mentions deprecated or unmaintained session libraries.
I currently lack the knowledge of how sessions work conceptually. This is what I understand so far:
We can include a dispatch() method to a request handler which allows us to create/update a session object; it is during the login phase of the app, the session is created. (Question: how is session stored? In the app's memory or in datastore?)
When a user makes a request to the app, the dispatch() method checks to see if an existing session exists for the user. (Question: How exactly does this validation work? Is there a token inside the request.body or cookie that sessions look for?)
When a user logs out, the session is deleted.
Is my understanding correct? Or perhaps I am missing something important? There seems to be little guidance on this subject on the internet. Thank you for the assistance.
Technically the dispatch() method is not added, it's just overwriting the one that webapp2.RequestHandler already provides, extending it to add session support. If you take a closer look at that method you see that it still calls the original one to do the actual dispatching:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
Which could be re-written, if you want, as:
super(BaseHandler, self).dispatch()
All that the extended dispatch() does is picking up the session info from the store making it available to the handler code before dispatching the request (which BTW includes the request processing) and saving it back afterwards, when the request processing completes (when changes to the session info may have been done). For every request! Simply a way to persist info across requests.
The session support is simply that - support - your app is still the one responsible for controlling what info is stored in the webapp2's session dictionary, when is that info added/modified/deleted and how is that info used.
In other words webapp2 itself has no clue what's login/logout/user session, etc (So no, nothing that you mention in #1, #2 and #3 happens in webapp2 itself). It is your app's responsibility to:
set/delete inside the session dictionary the info that represents your "user session" (whatever that means for your app) - typically in the user login/logout request handlers, respectively
use that info as it sees fit while handling incoming requests between the login and the logout one - when the info from the session dictionary represents the "current user session".
For storing the session info webapp2 supports cookies (default), memcache and datastore (ndb). From Sessions:
It has three built-in backends: secure cookies, memcache and
datastore. New backends can be added extending
CustomBackendSessionFactory.
The session store can provide multiple sessions using different keys,
even using different backends in the same request, through the method
SessionStore.get_session(). By default it returns a session using
the default key from configuration.
Related
I am using watson assistant with flask framework. Once the session expires i get the following error
ApiException(response.status_code, error_message, http_response=response)
ibm_cloud_sdk_core.api_exception.ApiException: Error: NotFound: session id ba62bf14-87e-4c7b071b591e for agent instance 0e5c653c-9-b4e0-5a597c3e541e, Code: 404 , X-global-transaction-id: ffea409d54977b49
127.0.0.1 - - [03/Jul/2019 11:27:47] "GET / HTTP/1.1" 200
Refreshing the page does not create a new session
How to create a new session on this exception, so that I need not restart the local server ?
You mention a 5 minute session timeout.
Watson Plus trial has this set for just testing, and is not intended to be production level. It cannot be changed.
Standard version and lite can use session but both were originally stateless. You should use the V1 API for these. You will have to manage the state, but you will no longer have a time out.
If you are using the paid version of Watson Plus, or premium you can change the time out within the assistant settings.
You need to provide code, as any response will be blind and based on guesswork on what errors you have made, and there are many. But based on the fact that you failed to provide code, and still raised the question expecting someone to tell you what you did wrong then let's go with a rookie error.
I think you are creating the session as a global in your flask app, and maybe saving it it the app object. You probably have a route for the dialog, which makes use of the session. The code in this route, needs to catch the error, or test if the session is still valid, and recreate it. If you are catching the error, and trying to recreate the session, then you may have fallen foul of Python's global variable restrictions. Essentially if in a function you have a variable as the right side of an assignment, then its scope will be limited to the function.
Refreshing the web page, will not force the flask app to re-create the session. As you probably have that logic outside of any routes.
i have been reading on IdentityServer4 and my understanding is that (at a high level) once IdentityServer4 is set up, a registered client can make API calls to API resources that are defined, if the client has been granted that access.
Using C#, i can:
1. Make a request for an access token from IdentityServer4, and then,
2. Pass this token along with my request to an API.
My question is, since the token has a defined lifetime, say 3600 seconds, is it correct to say that the client needs to store this token locally and use it for all its API calls within the 3600 seconds? If so, this would mean the client should somehow know when the token has expired. How would this be achieved?
Another question i have is how the 'Refresh' tokens work. When do they 'kick-in' in this whole process.
Thanks
Long story short, it's up to the client to be responsible for renewing tokens it uses. This can be based on the known expiry time (with a bit of a buffer) but OAuth also defines standard error responses from API endpoints that can indicate to a client that a new token is required. Clients should respect these and act accordingly.
It depends on the grant type being used to. E.g. using client credentials, although maybe not the most efficient, it may be desirable to get a new token for every call or "session" (i.e. multiple calls related to processing a given task) to avoid this complexity.
I've read quite a few SO threads about authentication and authorization with REST and Angular, but I'm still not feeling like I have a great solution for what I'm hoping to do. For some background, I'm planning to building an app in AngularJS where I want to support:
Limited guest access
Role-based access to the application once authenticated
Authentication via APIs
All of the calls to the REST API will be required to occur over SSL. I'd like to do build the app without breaking RESTful principles, namely not keeping session state stored on the server. Of course, whatever is done vis-a-vis authorization on the client-side has to be reinforced on the server side. Since we need to pass the entire state with each request, I know I need to pass some sort of token so that the backend server receiving the REST request can both authenticate and authorize the call.
With that said, my main question is around authentication - what are the best practices here? It seems there are lots of different approaches discussed, here's just a few that I've found:
http://broadcast.oreilly.com/2009/12/principles-for-standardized-rest-authentication.html
http://frederiknakstad.com/2013/01/21/authentication-in-single-page-applications-with-angular-js/
http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html
There was a similar question asked (AngularJS best practice application authentication), but unless I'm misunderstanding the answer, it seems to imply that a server session should be used, which is breaking RESTful principles.
My main concern with the Amazon AWS and the George Reese article is it seems to assume that the consumer is a program, rather than an end user. A shared secret can be issued to a programmer in advance, who can then use it to encode calls here. This isn't the case here - I need to call the REST API from the app on behalf of the user.
Would this approach be enough? Let's say I have a session resource:
POST /api/session
Create a new session for a user
To create a session, you need to POST a JSON object containing the "username" and "password".
{
"email" : "austen#example.com",
"password" : "password"
}
Curl Example
curl -v -X POST --data '{"username":"austen#example.com","password":"password"}' "https://app.example.com/api/session" --header "Content-Type:application/json"
Response
HTTP/1.1 201 Created {
"session": {
"id":"520138ccfa4634be08000000",
"expires":"2014-03-20T17:56:28+0000"
}
}
Status Codes
201 - Created, new session established
400 - Bad Request, the JSON object is not valid or required information is missing
401 - Unauthorized, Check email/password combo
403 - Access Denied, disabled account or license invalid
I'm leaving out the HATEOAS details for clarity. On the backend, there would be a new, limited duration session key created and associated with the user. On subsequent requests, I could pass this as part of the HTTP headers:
Authorization: MyScheme 520138ccfa4634be08000000
Then the backend servers would be responsible for digesting this out of the request, finding the associated user and enforcing authorization rules for the request. It should probably update the expiration for the session as well.
If all this is happening over SSL, am I leaving the door open to any kind of attacks that I should be protecting against? You could try to guess session keys and place them in the header, so I suppose I could additionally append a user GUID to the session key to further prevent brute force attacks.
It's been a few years since I've actively programmed and I'm just getting back into the swing here. Apologies if I'm being obtuse or unnecessarily reinventing the wheel, just hoping to run my ideas by the community here based on my reading thus far and see if they pass the litmus test.
When someone asks about REST authentication, I defer to the Amazon Web Services and basically suggest "do that". Why? Because, from a "wisdom of the crowds" point of view, AWS solves the problem, is heavily used, heavily analyzed, and vetted by people that know and care far more than most about what makes a secure request than most. And security is a good place to "not reinvent the wheel". In terms of "shoulders to stand on", you can do worse than AWS.
Now, AWS does not use a token technique, rather it uses a secure hash based on shared secrets and the payload. It is arguably a more complicated implementation (with all of its normalization processes, etc.).
But it works.
The downside is that it requires your application to retain the persons shared secret (i.e. the password), and it also requires the server to have access to that a plain text version of the password. That typically means that the password is stored encrypted, and it then decrypted as appropriate. And that invite yet more complexity of key management and other things on the server side vs secure hashing technique.
The biggest issue, of course, with any token passing technique is Man in the Middle attacks, and replay attacks. SSL mitigates these mostly, naturally.
Of course, you should also consider the OAuth family, which have their own issues, notably with interoperability, but if that's not a primary goal, then the techniques are certainly valid.
For you application, the token lease is not a big deal. Your application will still need to operate within the time frame of the lease, or be able to renew it. In order to do that it will need to either retain the user credential or re-prompt them for it. Just treat the token as a first class resource, like anything else. If practical, try and associate some other information with the request and bundle it in to the token (browser signature, IP address), just to enforce some locality.
You are still open to (potential) replay problems, where the same request can be sent twice. With a typical hash implementation, a timestamp is part of the signature which can bracket the life span of the request. That's solved differently in this case. For example, each request can be sent with a serial ID or a GUID and you can record that the request has already been played to prevent it from happening again. Different techniques for that.
Here is an incredible article about authentication and login services built with angular.
https://medium.com/opinionated-angularjs/7bbf0346acec
This SO question do a good job of summing up my understanding of REST
Do sessions really violate RESTfulness?
If you store a token in a session you are still creating state on the server side (this is an issue since that session is typically only stored on the one server, this can be mitigated with sticky sessions or other solutions).
I'd like to know what your reasoning is for creating a RESTful service though because perhaps this isn't really a large concern.
If you send a token in the body along with every request (since everything is encrypted with SSL this is okay) then you can have any number of servers (load balanced) servicing the request without any previously knowledge of state.
Long story short I think aiming for RESTful implementations is a good goal but being purely stateless certainly creates an extra layer of complexity when it comes to authentication and verifying authorization.
Thus far I've started building my back-ends with REST in mind, making URIs that make sense and using the correct HTTP verbs, but still use a token in a session for the simplicity of authentication (when not using multiple servers).
I read through the links you posted, the AngularJS one seems to focus just on the client and doesn't seem to explicitly address the server in that article, he does link to another one (I'm not a Node user so forgive me if my interpretation is wrong here) but it appears the server is relying on the client to tell it what level of authorization it has which is clearly not a good idea.
User makes HTTP-request to the server. This request is processed with an object of some class, let's call it "Processor". Then the same user in two minutes makes another HTTP request. And I want it to be processed with the same instance of Processor as the first one. So basically I want to keep the state of some object among several requests.
I know that I can save it each time to the datastore and then load back, but this approach seems to be very slow. Is there a way to store objects in some RAM place?
How about using memcache?
You can't ensure that consecutive requests to your app will go to the same instance, but memcache can help reduce or eliminate the overhead of accessing the datastore for each request.
It sounds like you are describing is a session.
I am not sure which language runtime and web framework you are using, but it is sure to include support for a sessions. (If you are using Java you will need to enable it.)
The standard session mechanism puts a small ID in a cookie that is stored in the user's browser. On every request, each of which could be go to a different application server, this ID is used as a key to read and write persistent information from the data store.
If the datastore accesses are too slow for you I would suggest not using memcache for this session storage, because memcache is by design unreliable, so the user's session information could disappear at any time, which would be a bad experience for them.
If the amount of data you want to store is less than about a few kilobytes, then I recommend doing what Play Framework does, which is to encrypt your session data and store it directly in a cookie stored in the user's browser. This is fast and truly stateless.
If you have more data than can be stored in a cookie, and you don't want to use the data store, you could could use JavaScript local storage on the browser, and use AJAX calls to communicate with the server. (If you want to support older browsers you may need to use the jStorage wrapper library.)
If memcache isn't enough, you could use backends to maintain state. Use a resident backend (or a set of them) and route incoming requests from the frontend to the backend machine that has the state.
Docs: Python Java
After reading about how CodeIgniter handles sessions, it has me concerned about the performance impact when sessions are configured to be stored and retrieved from the database.
This is from the CI documentation: "When session data is available in a database, every time a valid session is found in the user's cookie, a database query is performed to match it."
So every AJAX call, every HTML fragment I request is going to have this overhead? That is potentially a huge issue for systems that are trying to scale!
I would have guessed that CI would have implemented it better: include the MD5 hash to cover both the sessionID+timestamp when encoding them in the session record. Then only check the database for the session record every X minutes whenever the sessionID gets regenerated. Am I missing something?
You can make your AJAX requests use a different controller, for example Ajax_Controller instead of MY_Controller. MY_Controller would load the Session class but the Ajax_Controller doesn't. That way when you call to your AJAX, it doesn't touch session data and therefore doesn't make any erroneous calls to the database that aren't necessary.
If you are autoloading the Session class, maybe you can try unloading it for the AJAX requests? I've never tried it but it's talked about here http://codeigniter.com/forums/viewthread/65191/#320552 and then do something like this
if($this->input->is_ajax_request()){
// unload session class code goes here
}