Heyho, hope you been doing great since we last spo...
# general
j
Heyho, hope you been doing great since we last spoke. Hope you had a good news years. Can someone explain to me how the accessToken payload within a session is updated? The docs say here https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/sessions/with-jwt/custom-claims that "The result is that the access token payload is updated in the database and in the user's browser cookies. The change is instantly visible on the frontend and the subsequent backend API calls." But thats not happening in my case. I have a verified Session and its sessionContainer and everything. My Steps are: 1.) Verify User Session 2.) call
sessionContainer.SetClaimValue
3.) print
sessionContainer.GetAccessTokenPayload()
to see that it works. 4.) Do another api request with the exact same cookies and although I see the
jwt_user_payload
updated within the
session_info
table, I get the old outdated accessTokenPayload. Am I missing something? Ah, yeah and using golang sdk with self-hosted Or is it supposed to be solved by manually calling
session/refresh
r
hey @Jonny
when you call
sessionContainer.SetClaimValue
, the cookies are updated. This is done by the backend SDK sending the set-cookie header back to the browser. Subsequent API calls use the new access token
if you are querying the API with the same access token as before, it will still have the older payload in the sessionContainer.
So make sure to query the API with the new tokens.
j
Okay, I'm getting closer now but still I'm still a bit puzzled by the problem. I can verify with Postman, that the Backend response in fact doesn't have the headers necessary to send the new cookies back to the frontend. And I have working theory now, why that is the case: I'm using Go-Fiber which isn't a normal Go framework based on the
net/http
library. Go-Fiber is based on the
fastHttp
library which has a completely different interface for the request object and the response object of an incoming httpCall. A few months ago, I already opened a ticket to further fix your GoFiber Example within your supertokens-golang repo and in the end we settled on this version of the verifySession wrapper: https://github.com/supertokens/supertokens-golang/blob/master/examples/with-fiber/main.go#L121-L136 That is all fine and well working but I think, this now is the problem. I've spotted in your code that this line might be it, where you are setting the newly updated accessToken to the Header of the Response: https://github.com/supertokens/supertokens-golang/blob/2d77314f116312e5b6b90e41c5682225f64f5b27/recipe/session/session.go#L101 And by already seeing that the
response
argument to which the Header is written, is of the type
http.ResponseWriter
(notice how its from the
net/http
lib again) I can't help but feel, that this hacky middleware implementation isn't enough because after the request handler has run and
sessionContainer.SetClaimValue
has been called, I never transfer the written Header back to my real
ResponseWriter
which is not from the lib
net/http
but from
fastHttp
.
I hope to validate this over the next days
r
Hmm. Interesting. Tagging @sattvikc here who can help
s
hi @Jonny , Thank you for the detailed explanation. I think what was still wrong in the solution we settled for is calling the
c.Next()
outside of the adaptor. The problem with that is that the session container is till working with http Request and and Response objects that were created inside the adaptor, but now no longer in use. I think the right thing to call the next from within the adaptor itself. Here's an updated implementation of verifySession which you could try.
Copy code
go
func verifySession(options *sessmodels.VerifySessionOptions) fiber.Handler {
    return func(c *fiber.Ctx) error {
        var errFromNextHandler error
        err := adaptor.HTTPHandlerFunc(session.VerifySession(options, func(rw http.ResponseWriter, r *http.Request) {
            c.SetUserContext(r.Context())
            errFromNextHandler = c.Next()

            if errFromNextHandler != nil {
                // just in case a supertokens error was returned, we call the supertokens error handler
                // also, if supertokens error was handled, we don't want to return it, hence updating errFromNextHandler
                errFromNextHandler = supertokens.ErrorHandler(errFromNextHandler, r, rw)
            }
        }))(c)

        if err != nil {
            return err
        }
        return errFromNextHandler
    }
}
I have tried out a few cases, for which it seems to work as expected. I will update our repo once have tested exhaustively on this.
j
Thank you for looking into it @sattvikc I have to admit, that I'm currently a bit out of the topic again, but I remember putting up an issue back then and a PR to propose exactly the change of NOT calling the
c.Next()
within the adaptor.HTTPHandlerFunc. PR: https://github.com/supertokens/supertokens-golang/pull/195 where also the issue is linked. So based on the PR I would want to specifically test for, these issues that the mentioned PR tried to fix: - If the GoFiber ErrorHandler is still called (maybe with the only exception, when Supertokens error returned) - If any Header or StatusCode written within the
c.Next()
function will appear in the response Because looking into the implementation of
adaptor.HTTPHandlerFunc
, after it is done executing the
session.VerifySession
function argument, it will take whatever Headers and Codes have been written to
rw http.ResponseWriter
and copy them over onto
c *fiber.Ctx
and basically overwrite any Headers and StatusCodes that I already have set within
c.Next()
. Take your middleware in front of a handlerFunc where you call
ctx.Context().Response.Header.SetContentType(fiber.MIMEApplicationJSON)
and you'll probably don't see that header in the response, because the
http.ResponseWriter
headers take precendence - And if I'm not wrong, your current implementation will not catch unauthenticated requests. See again this issue: https://github.com/supertokens/supertokens-golang/issues/199 because the
err = adaptor.HTTPHandlerFunc
actually doesn't say anything about the verification status and is always nil. See issue for full explanation More and more I get why this issue is damn nasty because HTTP
adaptor.HTTPHandlerFunc
is just a poor adaptor for
fasthttp
->
http.ResponseWriter
. But maybe there is somewhere a solution that fixes all the above 3 issues while also carrying over any cookies the sessionContainer has set onto
http.ResponseWriter
.
I sadly am so swamped at work right now, that I only can complain about your solution and can't work on a solution on my own 😅 . For now I'm using the simple work around of manually calling
/session/refresh
to fetch the newest cookie from within the frontend sessionClaimValidator. I hope by next month I have more time to assist you in finding a fix. Thanks for all the effort already though 🙏
s
thank you for your detailed explanation, I have tested some of the cases you just mentioned. I have too have to admit that the adapter has limitations. I'll try to share examples and explanations for all the scenarios mentioned as soon as I can.
j
Can it also be, that my current wicked implementation of the
session.VerifySession
function, causes two
Front-Token
headers to be sent back after an automatic frontend-lib triggered call to
session/refresh
? I'm more than baffled, why the header is twice on the response. Completely identical, the jwt createt at timestamp from one header only slightly after the jwt timestamp of the first. Found a hacky workaround for now, since two headers cause the supertokens axios librarys
atob
for parsing the
Front-Token
to fail. I so hope, that all that goes away once I have proper implementation of that verification middleware. Hope you have a great week
r
Hmmm. This shouldn’t happen. Can you please open a GitHub issue about this describing what happens and how to reproduce it? We will fix it
2 Views