Search code examples
f#suave

How do I store data in Suave userstate?


I have a web part that handles an OAuth callback request.

After getting access tokens and the user's id from the API, I want to store it in the session state. But when reading the session on subsequent requests, I only see a value for the "Suave.Auth" key.

Here is my web part for the OAuth callback:

path "/oauth" >=> context (fun ctx ->
        let req = ctx.request
        match (req.queryParam "code", req.queryParam "error") with
        | Choice1Of2 code, _ ->
            let id = completeOAuth code
            Authentication.authenticated Session false
            >=> Writers.setUserData "user-id" id
            >=> Redirection.redirect "/view"
        | _, Choice1Of2 error -> RequestErrors.UNAUTHORIZED error)

How can I make sure the "user-id" value is in the session on other requests after this one?


Solution

  • Writers.setUserData stores data in a map that only exists for the duration of the request.

    To store data across requests you need to use statefulForSession like this.

    let app = 
      statefulForSession >=> context (fun x ->
        match HttpContext.state x with
        | None ->
          // restarted server without keeping the key; set key manually?
          let msg = "Server Key, Cookie Serialiser reset, or Cookie Data Corrupt, "
          + "if you refresh the browser page, you'll have gotten a new cookie."
          OK msg
        | Some store ->
          match store.get "counter" with
          | Some y ->
            store.set "counter" (y + 1) >=> OK (sprintf "Hello %d time(s)" (y + 1))
          | None ->
            store.set "counter" 1 >=> OK "First time")