appleboy / gin-jwt

JWT Middleware for Gin framework
MIT License
2.73k stars 382 forks source link

Option to set a session cookie #289

Open k0mmsussert0d opened 2 years ago

k0mmsussert0d commented 2 years ago

Hi! While using this code in my project I noticed there is no explicit option to omit both Max-Age and Expires parameters in a cookie handed-out when SendCookie parameter is set to true making it a session cookie. After looking through the code briefly I found CookieMaxAge parameter inside GinJWTMiddleware struct, unmentioned in the README. At the first glance, setting it to "0" might seem to be a good idea for this purpose. However, the way the flag is used during cookie generation concerns be a bit.

https://github.com/appleboy/gin-jwt/blob/22d2e6198bd396d324936a5d990b327a792bffe8/auth_jwt.go#L507-L509

Let's assume default mw.TimeFunc() implementation, which is time.Now. Max-Age attribute is calculated as duration difference between (time.Now() + CookieMaxAge) and (time.Now()) to the nearest second. Evaluating deductible and deductive is based on two separate calls to mw.TimeFunc() later converted to Unix timestamp. This might cause an inconsistency if system clock flips by one second between those two calls.

Step-by-step scenario:

According to net/http package documentation passing a negative value as MaxAge parameter for http.Cookie struct effectively results in a cookie with Max-Age: 0 attribute. This causes the cookie to be considered as expired [at] the earliest representable date and time, which is significantly different behavior compared to what's achieved with the lack of Expires and Max-Age attributes.

Excerpt from net/http documentation:

// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'
// MaxAge>0 means Max-Age attribute present and given in seconds

Supposing time did not change between mw.TimeFunc calls, this would yield maxage := 0, which is correct MaxAge value to pass to http.Cookie to make the Max-Age attribute unspecified in the output cookie.

I propose to improve the cookie expiration timeout evaluation method by making sure mw.TimeFunc is called only once. On top of that, I'd see a separate config flag like SessionCookie boolean overriding CookieMaxAge and Timeout as a huge convenience for this kind of use case.

Could you please share your thoughts on my proposal? I'm wiling to implement it if you decide you'd like it in the project.

Thanks!