bungle / lua-resty-session Goto Github PK
View Code? Open in Web Editor NEWSession library for OpenResty – flexible and secure
License: BSD 2-Clause "Simplified" License
Session library for OpenResty – flexible and secure
License: BSD 2-Clause "Simplified" License
Hello,
I am not sure about the situation so I thought about asking the author.
I am testing your library with Redis storage. I understand that $session_cookie_lifetime translates into Redis TTL expiry for the key (and this is what I want).
I am not sure where the $session_cookie_renew fits in this. Reading the manual it mentions about renewing the TTL of the cookie.
From what I see, on each "open" request, the Redis TTL of the session is updated to my $session_cookie_lifetime (as expected also since if the user has come back, I want his session to extend).
Since I'm using session cookies (ie the default of the library) with a lifetime of browser being open, is renew really used for the cookie? Or only the Redis TTL is honored (which is what I need actually)? I'm a little confused whether my understanding is correct in this particular scenario.
What I understand for my specific scenario is: the browser cookie does not expire so $session_cookie_renew is not applicable. The session expires when the key is removed from Redis (on TTL or destroy session). The browser cookie will be removed when browser is closed. If session is removed from Redis then the cookie will remain but session is invalid - ie I have to trap it in my code and do "start/save" for a new session.
Can you please clarify? Probably I'm reading things and the code wrong so please verify or correct my assumptions and my question.
Thanks
I have installed nginx on a clean Debian 9 machine and got initially the following error:
2017/07/05 20:59:03 [error] 7838#7838: *1 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/resty/session.lua:20: module 'resty.random' not found:
no field package.preload['resty.random']
no file './resty/random.lua'
no file '/usr/share/luajit-2.0.4/resty/random.lua'
no file '/usr/local/share/lua/5.1/resty/random.lua'
no file '/usr/local/share/lua/5.1/resty/random/init.lua'
no file '/usr/share/lua/5.1/resty/random.lua'
no file '/usr/share/lua/5.1/resty/random/init.lua'
no file './resty/random.so'
no file '/usr/local/lib/lua/5.1/resty/random.so'
no file '/usr/lib/x86_64-linux-gnu/lua/5.1/resty/random.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
no file './resty.so'
no file '/usr/local/lib/lua/5.1/resty.so'
no file '/usr/lib/x86_64-linux-gnu/lua/5.1/resty.so'
no file '/usr/local/lib/lua/5.1/loadall.so'
stack traceback:
coroutine 0:
[C]: in function 'require'
content_by_lua(default:17):2: in function <content_by_lua(default:17):1>, client: 127.0.0.1, server: localhost, request: "GET /start HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
Steps to reproduce:
Clean Debian 9 machine
sudo apt-get install nginx-extras
sudo apt-get install luarocks
sudo luarocks install lua-resty-session
replace the file /etc/nginx/sites-available/default by the content of the "Hello World" example (only the "server"-content)
sudo systemctl restart nginx-extras
browse to http://localhost:8080
clicking on "Start the test!"
500 Internal Server Error appears
/var/log/nginx/error.log shows the error message shown above.
By installing:
this error can be resolved.
But now the same trial delivers the following error in /var/log/nginx/error.log:
2017/07/05 21:15:20 [error] 12961#12961: *1 lua entry thread aborted: runtime error: /usr/local/share/lua/5.1/resty/aes.lua:170: /usr/lib/x86_64-linux-gnu/libluajit-5.1.so.2: undefined symbol: EVP_CIPHER_CTX_init
stack traceback:
coroutine 0:
[C]: in function '__index'
/usr/local/share/lua/5.1/resty/aes.lua:170: in function 'new'
/usr/local/share/lua/5.1/resty/session/ciphers/aes.lua:46: in function 'encrypt'
/usr/local/share/lua/5.1/resty/session.lua:156: in function 'save'
/usr/local/share/lua/5.1/resty/session.lua:344: in function 'start'
content_by_lua(default:17):2: in function <content_by_lua(default:17):1>, client: 127.0.0.1, server: localhost, request: "GET /start HTTP/1.1", host: "localhost:8080", referrer: "http://localhost:8080/"
Obviously this is a linker error for the libssl-dev. Several trials, for example installing
sudo apt-get install libssl-dev
did not help.
So it appears that the documentation (or the package itself) are missing important dependencies and some linking to openssl is not working out of the box on Debian 9?
Hi,
I want my clients to stay logged in next time they open the browser, but I see that you specifically say: no persistent cookies. Why, what's the downside?
Thanks,
Cosmin.
Using the default cookie storage it may happen that the size of the cookie runs over browser limits when a lot of data is stored in the session. Adding support for chunked cookies would mitigate this somewhat. See: zmartzone/lua-resty-openidc#33
Using the example from https://github.com/bungle/lua-resty-session#hello-world-with-lua-resty-session on a site where there is a hyphen in the host name fails.
To reproduce set up a test site such as test-site.mydomain.com
Set a session secret explicitly:
set $session_secret 623q4hR325t36VsCD3g567922IC0073T;
And try the example.
If the server need to run for a long time without restarting, server secret will need to be renewed periodically.
So, will lua-resty-session do it automatically, or does it provide a way to do that ?
Hi, I met a issue. I found cookie will lose when nginx redirect . For example , GET / HTTP/1.1 just redirect to /index.html. cookie in var[concat(n)] (session.lua function getcookie) will lose, this drives me crazy. Can you help me.
redis cluster support?
From a quick look at the code it wasn't clear if session expiration is enforced on the server side or if it entirely relies on the client cookie expiration.
This can pose issues when an expired cookie is still recoverable on disk when using persistent sessions (through either disk forensics, or because the browser has not been started since the cookie expired).
I imagine this would affect the stateless cookie backend more so than others.
Hi Bungle, thanks a lot for all your work.
I ran into a problem and it took me a long time to figure it out, so I just want to document it in case somebody sees something similar.
Basically, the problem is that sessions don't work unless I explicitely set the 'secret' , even though I don't use lua_code_cache off;
In my setup, I have various nginx locations with content_by_lua_file <whatever.lua> and on those lua files I have:
local SESS = require "resty.session"
so I can use the session functionality in my scripts.
On a login page, I set up a session:
local session = SESS.start({ name = "mysession" })
session.data.type = 'gui'
session.data.tenant_id = tenant_id
session:save()
On another script (actually in an access_by_lua_file) , I do check for the existence of a session, like so:
local SESS = require ('resty.session')
local session, present = SESS.open({ name = "mysession" })
if not session.present then
return ngx.exit(ngx.HTTP_FORBIDDEN)
end
And this worked erratically... sometimes it worked (got the session established previously) but most of the time, the session was not detected (even though the cookie was there).
I debugged and I found that the 'problem' was in this line :
if d and hmac(k, concat{ i, e, d, self.key }) == h then
The second condition was always false. Even using
cipher = "none"
the problem was there.
I discovered that the secret was being generated on every request. This problem is explained in the documentation here , but since my app is NOT turning off the cache, I thought this didn't apply to me.
As soon as I created my sessions with a specific secret, and opened them with that secret, everything worked fine
SESS.open({ name = "mysession" , secret = "mysecretwhateverblah" })
I'm not really sure why the secret was being re-generated each time... even with cache "on" ... but my suggestion is to change the documentation to say that setting the 'secret' is not only a good idea... but that it should always be done... more like a requirement.
How to open session by session id? For example, I want to destroy session by session id.
It would be great if it was possible to use hostnames for memcache server and not only ip.
line 38 of lua-resty-session/lib/resty/session/ciphers/aes.lua
:
size = CIPHER_MODES[a.size or defaults.size] or 256,
should be:
size = CIPHER_SIZES[a.size or defaults.size] or 256,
Originally this library was implemented according to Secure Cookie Protocol. This is quite adequate still, but it seems security community has now settled on slightly different approach. The main difference is that people mostly promote these days approach called Encrypt-Then-MAC or a cipher that supports a thing called AEAD aka Authenticated Encryption using Associated Data (using different keys for signing and encryption). We may want to modify this library to support different strategies.
I write an func:
function UtilityService:setSession(key, value)
local session = require "resty.session".start{ secret = "623q4hR325t36VsCD3g567922IC0073T" }
session.data[key] = value
session:save()
end
function UtilityService:getSession(key)
local session = require "resty.session".open{ secret = "623q4hR325t36VsCD3g567922IC0073T" }
if key == nil then
return session.data
else
return session.data[key]
end
end
In my page:
utilityService:setSession("username", "admin")
utilityService:setSession("password", "password")
utilityService:setSession("is_admin", true)
utilityService:setSession("login_time", os.time())
local cjson = require "cjson"
ngx.say(cjson.encode(utilityService:getSession()))
Output:
First time: {}
Second time and later: {"login_time":1460522907}
Why?
For this great project i have some question,
Sorry for my poor English.
as you know, <iframe> maybe caused generate a new session even if the domain not changed. So I need the id of parent frame, then page in <iframe> can open the same session. How to get such a "id"?
It seems for me, that sometimes encryption fails.
The best way to reproduce is to try access Nagios and use nginx's oauth plugin: https://github.com/vladimir-smirnov-sociomantic/nginx-oauth-on-dotcloud (mine fork, because not all changes are merged for now).
With debug log I've found that sometimes I receive data from redis/cookies, but they fail to decrypt
My understanding from the documentation was that, in cases where session.cookie.persistent = off
, that $session_cookie_lifetime
is ignored for that cookie. Indeed when I start a session with session.cookie.persistent = off
andset $session_cookie_lifetime 600;
the browser shows that the cookie is a Session
cookie and does not show an expiry time/date.
However, in testing, resty-session seems to consider that cookie invalid after 600 seconds.
Have I misread the documentation, or is this an issue in resty-session?
I just lost a couple hours to debugging why my sessions would suddenly fail to decrypt, sometimes a few seconds after starting the server, sometimes 10 minutes later, with no logging output about why. I had to disable $session_check_ssi
.
I think there's a strong case to be made for that not to be the default. Some of the other checks are suspicious, too, like the remote_addr
one (clients do rehome), but $session_check_ssi
was definitely a big burden until I realized what was going on.
Can you consider logging when $session_check_ssi
fails, or default to not doing it at all? Thanks!
We're using lua-resty-openidc in a clustered environment (multiple ingress servers), using a single redis as a session store.
We're experiencing a problem where a race condition occurs when multiple requests are made simultaneously after the access token has expired: both requests will trigger a refresh, obtain a new access token, and store the token to the redis session. Storing the session updates the hmac section of the session cookie, and sets a new session cookie on the response.
The problem seems to be that the request which is last to set the session access-token is not always the last to return the response with the new session cookie, which means that the hmac section in the client side cookie does not correspond with the cookie from the redis session store on the following requests, causing 401 errors.
Is there a good way to resolve this?
Relevant code-section (decrypt returns null):
lua-resty-session/lib/resty/session.lua
Line 287 in 4429a06
set $session_secret <secret>;
set $session_cookie_renew 900;
set $session_check_ssi off;
set $session_storage redis;
set $session_redis_prefix sessions;
set $session_redis_host redis-master.${OPENSHIFT_NAMESPACE}.svc.cluster.local;
set $session_redis_port 6379;
set $session_redis_auth ${REDIS_PASSWORD};
set $session_redis_uselocking on;
set $session_redis_spinlockwait 10000;
set $session_redis_maxlockwait 30;
set $session_redis_pool_timeout 45;
set $session_redis_pool_size 10;
set $session_cookie_samesite off;
lua-resty-session/lib/resty/session.lua
Line 132 in fbc1057
Happens when $session_secret
is not set in nginx.
Hi! I have this issue, I dont know what's cause an issue.
request to the redirect_uri_path but there's no session state found
I see there are these variables when using cookie storage
set $session_cookie_renew 600;
set $session_cookie_lifetime 3600;
Are there analogous ones when using storage like Redis? How can I set the number of seconds after which an inactive session expires? and how long is the session life extended when session is accessed?
Thanks.
This is not a bug report, but wishful thinking :)
I had extreme problems reading the code. A short comment for the most important methods would be useful. More importantly variable names could be a lot more helpful.
A lot of variable names are reused for different meanings (d
in the example) which makes it even harder to grasp the code.
Example:
lua-resty-session/lib/resty/session.lua
Lines 309 to 315 in d006e52
What is the reason for the current naming? Performance improvements?
hello, i am new bb to web serivce , i am having problems using lua-resty-session, i am trying to verify the session that the browser sended is origina from the nginx resty part or it is not .I have been searching for some time I cant find a good example to follow. here are my codes:
local session = require "resty.session".start
{
secret = "623q4hR325t36VsCD3g567922IC0073T",
cookie = { persistent = true, lifetime = 280 }
}
session.open()
if session.present then
-- ngx.print(session.data.name)
args.sessionids=session.data.name
args.testsession=1
args.datasession=session.data
local ret=rpccall(red, ' LogininfofromSession', 100, args)
end
local ret=rpccall(red, 'LoigininfofromPasswordandUsername', 100, args)
if(ret=='yes')then
local session = require "resty.session".start
{
secret = "623q4hR325t36VsCD3g567922IC0073T",
cookie = { persistent = true, lifetime = 280 }
}
session.open()
session.data.name = "OpenResty Fan"
session:save()
end
i try to debug by step to find when the sentence session.present wil be l steped into。 And i find everytime even it is not original from resty session it will step into 。what i want is simple.When the session sended is original from openresty calling LogininfofromSession" function.When then session sended is not from orignal just skip this part ,and it call LoigininfofromPasswordandUsername function;And additionally how can I get session id from javascript?Can anyone show me an easy example ,thank you so much !
Here are the settings I have:
lua_shared_dict sessions 10m;
ssl_session_timeout 24h;
ssl_session_cache shared:SSL:20m;
set $session_cookie_renew 12h;
set $session_cookie_lifetime 24h;
I want the session to expire ONLY in one of the following cases:
Are my settings correct/optimal for this use case? Thanks.
if i have 2 nginx webserver running behind a Load Balancer, is it possible to replicate sessions between 2 servers?
Hi,sorry to bother ;
i want to get the session id, but the result i can't recognize, like this 'l 3霫Ն', in nginx.conf i have already add 'charset utf8' ,my openResty version is '1.11.2.1'.
An question:can i use the session.id to identification the same user from explorer?
If you reply and give my question an answer ,i will grateful for this.
Hi:
how can switch my redis database,your connect only use default database '0' .
Hi,
I am trying to figure out an issue with my web application. I think the issue is that the wrong data is stored in the session so I was wondering if there is an easy way that I could inspect the content of my (encrypted) session cookie. I mean something like a command line that would receive as arguments the cookie(s) content and the session secret and display the content of the session?
Cheers,
Tom
in https://github.com/bungle/lua-resty-session/blob/master/lib/resty/session.lua#L141-L197
no place set self.redis
, but in redis.new(conf)
need it. Can fix it like this?
diff --git a/lib/resty/session.lua b/lib/resty/session.lua
index 1691ac5..95fe486 100644
--- a/lib/resty/session.lua
+++ b/lib/resty/session.lua
@@ -151,7 +151,8 @@ function session.new(opts)
if not o then
g = require "resty.session.identifiers.random"
end
- local o, h = pcall(require, "resty.session.storage." .. (y.storage or z.storage))
+ local s = y.storage or z.storage or "cookie"
+ local o, h = pcall(require, "resty.session.storage." .. s)
if not o then
h = require "resty.session.storage.cookie"
end
@@ -189,7 +190,8 @@ function session.new(opts)
ua = c.ua or d.ua,
scheme = c.scheme or d.scheme,
addr = c.addr or d.addr
- }
+ },
+ [s] = y[s]
}
self.storage = h.new(self)
self.cipher = k.new(self)
@@ -310,4 +312,4 @@ function session:destroy()
return setcookie(self, "", true)
end
We are storing session data inside Redis.
Can we disable session data encryption?
With the newest version of lua-resty-string the following error is given by the resty.aes module:
error: salt must be 8 characters or nil
causing the sample code to fail (aes object is nil).
See this commit:
openresty/lua-resty-string@82ff0e3
"lua_code_cache off" effect session. I think it is may simular like session off.
So if you check it as same as i say , it could mention on Readme.md. :)
Hi,
I've got some problems (maybe related to my setup, not to the plugin), but even when using server with ssl, session cookies don't have "Secure" flag (ngx.var.ssl_session_id is always nil).
I've tried Nginx both 1.6.2 and 1.7.7 with lua-nginx-module 0.9.12 and 0.9.13 installed. ngx_devel_kit is latest 0.2.19.
Hi there,
I am facing a problem right now. Herer is how I set my session:
local session = require "resty.session".start()
session.data.name = credentials.username \n
session:save()
When I try to grab it from another page upon ngx.redirect
I have a nil value for session.data.name
Here is how I try to grab it:
local session = require "resty.session".open()
ngx.say("<p> session.data.name </p>")
Thanks in advance.
local session = require "resty.session".start{ secret = "623q4hR325t36VsCD3g567922IC0073T" }
local session = require "resty.session".new()
session.secret = "623q4hR325t36VsCD3g567922IC0073T"
I use thie first line to init session is correct, but use the second two lines get an error:
session.lua:86: attempt to concatenate local 'i' (a nil value)
Is this a bug?
Is there an example of how to write a session id generator?
I want to create a JWT as the session id.
I'd very much like to see server side support for session storage as listed in the roadmap. Any chance that this will move forward in the near future? FWIW: I'd be willing to contribute to the backends themselves (shm, files, memcached, redis...) but I don't feel comfortable to make the changes to the core infrastructure to start supporting those.
Hi,
I'm trying to use lua-resty-session, but it doesn't work. I'm having these errors in my error.log (I'm using Openresty):
[error] 2542#0: 12456 failed to run header_filter_by_lua: /path/to/openresty/libs/resty/session.lua:134: expecting one argument
If session.check.scheme
is enabled, it is expected that the scheme is checked.
Currently the code looks at the header X-Forwarded-Proto
to determine the scheme
lua-resty-session/lib/resty/session.lua
Line 270 in d006e52
If lua-resty-session
is not behind a reverse proxy the X-Forwarded-Proto
header will not come from a trusted source but may instead be user-supplied or injected by MitM. This way the determined scheme
might be different from the actual scheme
between user and the server.
It is not clear to me if this might lead to the server sending out confidential payload over http in edge cases.
I would propose that the reverse proxy headers should only be trusted, if a corresponding opt-in flag is set.
Request by http,session data cannot be read and set.
I have been trying a lot to figure out why my cookies were not working. I followed the documentation and still something seems to be going wrong when I 'open' a cookie before starting it. It would fail every time. I decided to test your code in the example and it is not working either. I just get "Anonymous" every time. Why is that? Thanks.
Use case: When a session is create I would like to load session data from storage such as mysql. This data may include user profile data such as first and last name.
Currently I can do this using Lua at the time when a session is created. However I want to treat session creation as "non-functional" and generic, while still giving each application an ability to populate the session with "functional" information.
One thought I have is to configure an internal location block, e.g. set $session.loader _my_session_loader;
, and then at some point in the session lifecycle, we can make a subrequest to the loader. The result of the loader will be stored in the session.
Thoughts?
Hi.
I've been using your library and I've noticed that when I do session.start() for the first time it will set a Set-Cookie in header, because it calls method regenerate. This is not desired when I just want to read and check if session exists. I could do this by first checking if a cookie named session is present, but I think it would be best to delegate this to resty-session, especially since we could change the name of the key and so on, so for now I removed the save instruct on regenerate (since I don't use it directly and I end up calling save after setting some data anyway). What do you think is the best way to proceed?
Thanks for the awesome library btw.
I am checking for valid sessions and in some situations new credentials are provided. In this situation I am choosing to regenerate the session instead of destroying and creating a new one (my understanding was that regenerate already did that). It is failing to regenerate though.
Here is the stack trace:
2015/10/15 21:15:14 [error] 25755#0: *980 lua entry thread aborted: runtime error: /usr/share/luajit/share/lua/5.1/resty/session.lua:101: attempt to call field 'destroy' (a nil value)
stack traceback:
coroutine 0:
/usr/share/luajit/share/lua/5.1/resty/session.lua: in function 'regenerate'
/usr/share/luajit/share/lua/5.1/resty/session.lua:282: in function 'regenerate'
/etc/nginx/scripts/combined.lua:61: in function </etc/nginx/scripts/combined.lua:1>, client: 10.129.253.131, server: , request: "GET /?accesskey=dd37a772-a0b3-49b9-bd7f-2ce217427f15 HTTP/1.1", host: "10.129.22.47", referrer: "http://localhost:8080/"
Any help would be appreciated. Thanks.
Hi! i'm try to use this library with the Nginx Openresty For Windows and show me this error.
2016/08/30 15:36:29 [error] 9084#3740: *1 lua entry thread aborted: runtime error: C:\Users\pablo\Desktop\nginx-1.11.3//resty\session.lua:30: cannot resolve symbol 'RAND_bytes': No se encontr proceso especificado.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.