Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: XSRF header for servant-auth clients #48

Open
3noch opened this issue Oct 5, 2017 · 6 comments
Open

Discussion: XSRF header for servant-auth clients #48

3noch opened this issue Oct 5, 2017 · 6 comments

Comments

@3noch
Copy link
Collaborator

3noch commented Oct 5, 2017

servant-auth-server by default expects that the [browser] client will add an X-XSRF-TOKEN header with the contents of the XSRF-TOKEN cookie for authenticated requests. I have a PR servant-auth to make this configurable, but regardless it would be nice if servant-reflex made this easier. Now that we have #47, we can actually do this manually. In fact, that may be the only way currently. The reason is that servant-auth doesn't "advertise" in the types the name of the XSRF cookie or the header it expects. The server and the client need to negotiate that out-of-band (so to speak).

Thoughts?

@3noch
Copy link
Collaborator Author

3noch commented Feb 1, 2018

BTW this extra header can be added by using clientWithOpts.

@finlay
Copy link

finlay commented Feb 1, 2018

Hi

We made this work using the Web.Cookie (cookie) library to parse the cookie text. The following example is based on a Servant authentication API derived from servant-auth-server:

type Authenticated = Auth '[Cookie] User
type SetCookies = Headers '[ Header "Set-Cookie" SetCookie
                           , Header "Set-Cookie" SetCookie
                           ] NoContent
type AuthApi
    =  "login" :> ReqBody '[JSON] LoginInfo :> PostNoContent '[JSON] SetCookies
  :<|> Authenticated :> "user" :> Get '[JSON] User

This is the Servant.Reflex code required to get the cookie, and put it into the request header:

    -- Get the XHR-COOKIE if set
    let getToken = lookup "XSRF-TOKEN" . parseCookiesText . T.encodeUtf8
    xsrfToken <- liftJSM $ getToken <$> (currentDocumentUnchecked >>= getCookie)

    -- API access functions
    let tweakRequest = ClientOptions $ \r -> do
          return $ r & xhrRequest_config 
                     . xhrRequestConfig_headers 
                     . at "X-XSRF-TOKEN" .~ xsrfToken
        pm = Proxy :: Proxy m
        pn = Proxy :: Proxy ()
        bp = constDyn (BasePath "/")
        login :<|> user  = clientWithOpts api pm pn bp tweakRequest

@3noch
Copy link
Collaborator Author

3noch commented Feb 1, 2018

@finlay Thanks for the full example! Is it possible to put the getToken bit into tweakRequest itself so you can derive these functions once and reuse them again for different tokens?

@finlay
Copy link

finlay commented Feb 1, 2018

I think the issue is that the currentDocumentUnchecked function needs the MonadJSM context, which IO doesn't have.

And the ClientOptions type wraps a function in IO.

We could change the ClientOptions type a little perhaps. @hamishmack was wondering about that.

F

@3noch
Copy link
Collaborator Author

3noch commented Feb 1, 2018

There is a way to get the JSM context and regain it again but I can't recall how. I'm sure @hamishmack knows.

@imalsogreg
Copy link
Owner

@finlay @3noch changing the type of ClentOptions sounds promising.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants