<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="81986" data-post-id="81986">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="amnu3387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  amnu3387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Have you tried turning off <code>HttpOnly</code> (in this case not setting it to true) when setting the cookie?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="81986" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-81986" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="81986"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="81989" data-post-id="81989">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstlroot" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstlroot/120/9945_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstlroot
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="amnu3387" data-post="12" data-topic="14220" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/a/ed8c4c/48.png" class="avatar"> amnu3387:</div>
<blockquote>
<p>Have you tried turning off <code>HttpOnly</code> (in this case not setting it to true) when setting the cookie?</p>
</blockquote>
</aside>
<p>Yes.</p>
<pre><code>  def sign_in(conn, %{"user" =&gt; user_params}) do
    case Accounts.token_sign_in(conn, user_params["username"], user_params["password"]) do
      {:ok, token, user} -&gt;
        conn
        |&gt; Plug.Conn.put_resp_cookie("token", token, http_only: false, secure: true, max_age: 604800)
        |&gt; render("signed_in.json", user: user)
      _ -&gt;
        {:error, :unauthorized}
    end
  end
</code></pre>
<p>The access_secure_data gives me exactly the same output:</p>
<pre><code>%Plug.Conn{
  adapter: {Plug.Adapters.Cowboy.Conn, :...},
  assigns: %{},
  before_send: [#Function&lt;1.92707701/1 in Plug.Logger.call/2&gt;],
  body_params: %{"withCredentials" =&gt; true},
  cookies: %{},
  halted: false,
  host: "localhost",
  method: "POST",
  owner: #PID&lt;0.799.0&gt;,
  params: %{"withCredentials" =&gt; true},
  path_info: ["api", "access_secure_data"],
  path_params: %{},
  peer: {{127, 0, 0, 1}, 47456},
  port: 4000,
  private: %{
    MyAppWeb.Router =&gt; {[], %{}},
    :phoenix_action =&gt; :access_secure_data,
    :phoenix_controller =&gt; MyAppWeb.UserController,
    :phoenix_endpoint =&gt; MyAppWeb.Endpoint,
    :phoenix_format =&gt; "json",
    :phoenix_layout =&gt; {MyAppWeb.LayoutView, :app},
    :phoenix_pipelines =&gt; [:api],
    :phoenix_router =&gt; MyAppWeb.Router,
    :phoenix_view =&gt; MyAppWeb.UserView,
    :plug_session_fetch =&gt; #Function&lt;1.45862765/1 in Plug.Session.fetch_session/1&gt;
  },
  query_params: %{},
  query_string: "",
  remote_ip: {127, 0, 0, 1},
  req_cookies: %{},
  req_headers: [
    {"host", "localhost:4000"},
    {"connection", "keep-alive"},
    {"content-length", "24"},
    {"accept", "application/json, text/plain, */*"},
    {"origin", "http://localhost:8080"},
    {"user-agent",
     "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36"},
    {"content-type", "application/json;charset=UTF-8"},
    {"referer", "http://localhost:8080/"},
    {"accept-encoding", "gzip, deflate, br"},
    {"accept-language", "en-US,en;q=0.9,fr;q=0.8"}
  ],
  request_path: "/api/access_secure_data",
  resp_body: nil,
  resp_cookies: %{},
  resp_headers: [
    {"cache-control", "max-age=0, private, must-revalidate"},
    {"vary", "Origin"},
    {"access-control-allow-origin", "http://localhost:8080"},
    {"access-control-expose-headers", ""},
    {"access-control-allow-credentials", "true"}
  ],
  scheme: :http,
  script_name: [],
  secret_key_base: "wEwpD63zVGtA3/JTdl5QBH6aZwE3FLD2gkAQWn6XD4Tfgk4lYlsDOoZHAREvfjoX",
  state: :unset,
  status: nil
}
</code></pre>
<p>Maybe something to add to the discussion, using Postman never helps either. i.e. In this case, it sees my cookie being set as expected on the sign_in call but the access_secure_data call is not sending back my cookie to the server even though I can see it in Postman…</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="81989" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-81989" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="81989"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="82000" data-post-id="82000">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="OvermindDL1" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/OvermindDL1/120/2677_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  OvermindDL1
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jstlroot" data-post="11" data-topic="14220">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstlroot/48/9945_2.png" class="avatar"> jstlroot:</div>
<blockquote>
<p>It seems like using the request header body to send the token also gives javascript access to it. There might be a way to avoid this that I don’t know of? If so, it could be a solution.</p>
<p>HttpOnly cookies are isolated from javascript and cannot be read by it, making authentication token stealing XSS attacks more complex, if not impossible. Cookies are open to other types of attacks but this is mitigated by the use of HTTPS all over. At least that’s what I understood.</p>
</blockquote>
</aside>
<p>Very very true.  Plus if you encode, say, a JWT token into a web page (as is common with ‘any’ token for phoenix websockets sadly) then a page can quite literally just read another page and parse out information from it using your auth’d user (there are hazards they have to work around to do that, but there are still ways).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82000" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-82000" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82000"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="82019" data-post-id="82019">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstlroot" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstlroot/120/9945_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstlroot
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Oh my god I found it…</p>
<p>I knew it was gonna be stupid.</p>
<p><code>put_resp_cookie(conn, key, value, opts \\ [])</code></p>
<blockquote>
<p>Options</p>
<ul>
<li><code>:domain</code> - the domain the cookie applies to</li>
<li><code>:max_age</code> - the cookie max-age, in seconds. Providing a value for this option will set both the max-age and expires cookie attributes</li>
<li><code>:path</code> - the path the cookie applies to</li>
<li><code>:http_only</code> - when false, the cookie is accessible beyond http</li>
<li><code>:secure</code> - if the cookie must be sent only over https. Defaults to true when the connection is https</li>
<li><code>:extra</code> - string to append to cookie. Use this to take advantage of non-standard cookie attributes.</li>
</ul>
</blockquote>
<p>I had <code>:secure</code> forced to true but I’m not using HTTPS  in my dev environment.</p>
<p>I hope this discussion will help others determine how they want to implement token authentification with Phoenix and Vue.js <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>Thank you all again for your time and support &lt;3</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82019" data-batch-url="/posts/batch_likers">
                        11
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-82019" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82019"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
    <div class="postbit" id="82264" data-post-id="82264">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="acrolink" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/acrolink/120/8985_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  acrolink
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a class="mention" href="/u/jstlroot" rel="nofollow">@jstlroot</a>, glad to hear it is working now. I have already implemented your ideas (in regard to secure cookie storage for the token) using <code>Phauxth</code> library. I want to ask: what <code>max_age</code> do you use for the token/cookie expiration (should it be same value)? and do you implement some refresh token mechanism server or client side (for soon to get expired tokens)? Thank you.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82264" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-82264" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82264"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="82518" data-post-id="82518">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstlroot" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstlroot/120/9945_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstlroot
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="acrolink" data-post="16" data-topic="14220" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/acrolink/48/8985_2.png" class="avatar"> acrolink:</div>
<blockquote>
<p><a class="mention" href="/u/jstlroot" rel="nofollow">@jstlroot</a>, glad to hear it is working now. I have already implemented your ideas (in regard to secure cookie storage for the token) using <code>Phauxth</code> library. I want to ask: what <code>max_age</code> do you use for the token/cookie expiration (should it be same value)? and do you implement some refresh token mechanism server or client side (for soon to get expired tokens)? Thank you.</p>
</blockquote>
</aside>
<p>Hi <a class="mention" href="/u/acrolink" rel="nofollow">@acrolink</a></p>
<p>I was out for a couple of days, hence the delay, I’m sorry.</p>
<p>To be honest, I haven’t yet decided how the session expiration will work for my app. What I’d like is for the session to expire after a week of inactivity for the account. At least, that’s what I think my customers will find appropriate.</p>
<p>Many options seem possible. One would be to refresh the token and overwrite the cookie at each request, which shouldn’t be too much of a drag for the server as this process seems very light. Another option would be to be less aggressive about it and go for daily refreshes (first request of the day refreshes the token and cookie).</p>
<p>Another more lazy way would be to set the expiration 2 weeks after cookie/token creation and refresh them when there’s less than one week remaining. The only way this option would make sense to go for is to save server load, which I think is not really an issue, so I most likely won’t go for this one.</p>
<p>I’d be interested to know our thoughts on the subject!</p>
<p>Ah, and yes, I think the cookie and token should have the same expiration value as the behavior is pretty much the same should either of them expire before the other anyway (user needing to log back in).</p>
<p>Cheers! <img src="https://forum.elixirforum.com/images/emoji/apple/beers.png?v=15" title=":beers:" class="emoji" alt=":beers:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82518" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-82518" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82518"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="82520" data-post-id="82520">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="acrolink" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/acrolink/120/8985_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  acrolink
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Would be interesting to see what the optimal solution would look like <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> If the client side is a pure JS application then it is possible to send back to the client application at authentication time (sign in) along with the cookie the value of token expiration (e.g. <code>{"expires_at": unix_time}</code>). A script running at fixed intervals on the client-side or on page navigation checks if there is say less than 24 hours to expiration. If so, a background call to the server is made which triggers the sever to issue a new cookie with new expiration time. Good to make distinction between original token and refreshed tokens since some actions may require providing username and password again.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82520" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-82520" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82520"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="82521" data-post-id="82521">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jstlroot" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jstlroot/120/9945_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jstlroot
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="acrolink" data-post="18" data-topic="14220" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/acrolink/48/8985_2.png" class="avatar"> acrolink:</div>
<blockquote>
<p>Would be interesting to see what the optimal solution would look like <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"> If the client side is a pure JS application then it is possible to send back to the client application at authentication time (sign in) along with the cookie the value of token expiration (e.g. <code>{"expires_at": unix_time}</code>). A script running at fixed intervals on the client-side or on page navigation checks if there is say less than 24 hours to expiration. If so, a background call to the server is made which triggers the sever to issue a new cookie with new expiration time. Good to make distinction between original token and refreshed tokens since some actions may require providing username and password again.</p>
</blockquote>
</aside>
<p>Yep, makes sense.</p>
<p>Your idea of making distinction between original and refreshed tokens is interesting, thank you for sharing it!</p>
<p>Don’t hesitate to poke me as needed or to share any other idea. <img src="https://forum.elixirforum.com/images/emoji/apple/smile.png?v=15" title=":smile:" class="emoji" alt=":smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="82521" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/sending-cookies-for-stateless-spa-authentication-using-jwt/14220/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-82521" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="82521"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>