<div dir="ltr">Hi Kamal,<div><br></div><div>Each client gets their own token and they refresh the tokens independently. Last session refresh in the user session is the last time any clients in that user session refreshed the token. It&#39;s used to know if a users session is active or not and we don&#39;t care what client it was the user used.</div><div><br></div><div>With regards to refresh tokens we need to expire/invalidate the last refresh for a specific client session within the user session. So we would need a note on each client session when they refreshed last.</div><div><br></div><div>If we did what you proposed it would basically break SSO and only one client would be able to maintain a working session.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On 13 October 2015 at 02:26, Kamal Jagadevan <span dir="ltr">&lt;<a href="mailto:j.kamal@ymail.com" target="_blank">j.kamal@ymail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div style="color:#000;background-color:#fff;font-family:times new roman,new york,times,serif;font-size:13px"><div>Hi Stian/Marek,</div><div>  Thanks for your attention in the matter.</div><div>Probably you are referring to one other issue in client level, but Mike &amp; I are referring at User level within or across client.</div><div dir="ltr"><br></div><div dir="ltr">User John Doe authenticates with his credentials and obtains token pair <b>A1R1</b></div><ol dir="ltr"><li>After A1 expires, app refreshes the token pair to <b>A2R2 </b>USING R1<br></li><li>After A2 expires, app refreshes the token pair to <b>A3R3 </b><b><span style="background-color:rgb(253,239,43)">USING <font color="#cd232c" size="3">R1</font></span></b><font size="3"><b> </b></font>(ideally it is should use R2 as it is the latest refresh token)<br></li></ol><div dir="ltr">     <br></div><div dir="ltr">In order to achieve this functionality, I was wondering why can&#39;t we use existing last refresh time from User session rather then checking it in the client session.</div><div dir="ltr">IMHO, adding one more validation in the ValidateToken method in TokenManager class like this should resolve the problem.<br></div><div dir="ltr"><br></div><div dir="ltr">        // after userSession is determined either for offline token or online token...<br></div><div dir="ltr">        if(oldToken.getIssuedAt() &lt; userSession.getLastSessionRefresh()) {<br>            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, &quot;Stale refresh token - already used&quot;);<br>        }<br><br></div><div dir="ltr"><br></div><div dir="ltr">Please let me know if you see any pitfalls other than the backward compatibility for existing keycloak users. I can work with you to merge this change &amp; test it in the master.</div><div dir="ltr"><br></div><div dir="ltr">Best</div><div dir="ltr">Kamal<br></div><div><br></div><div><span></span></div><br>  <div style="font-family:times new roman,new york,times,serif;font-size:13px"> <div style="font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px"> <div dir="ltr"> <hr size="1">  <font face="Arial" size="2"> <b><span style="font-weight:bold">From:</span></b> Stian Thorgersen &lt;<a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>&gt;<br> <b><span style="font-weight:bold">To:</span></b> Marek Posolda &lt;<a href="mailto:mposolda@redhat.com" target="_blank">mposolda@redhat.com</a>&gt; <br><b><span style="font-weight:bold">Cc:</span></b> &quot;Jagadevan, Kamal&quot; &lt;<a href="mailto:kamalakannan.jagadevan@hpe.com" target="_blank">kamalakannan.jagadevan@hpe.com</a>&gt;; &quot;<a href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a>&quot; &lt;<a href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a>&gt; <br> <b><span style="font-weight:bold">Sent:</span></b> Wednesday, October 7, 2015 8:38 AM<div><div class="h5"><br> <b><span style="font-weight:bold">Subject:</span></b> Re: [keycloak-dev] Same Refresh token can be used multiple times to obtain access token<br> </div></div></font> </div><div><div class="h5"> <div><br><div><div><div dir="ltr">You&#39;re right, we&#39;d have to introduce a lastRefresh on ClientSession</div><div><br><br></div><div><div><br clear="none"><div>On 7 October 2015 at 14:35, Marek Posolda <span dir="ltr">&lt;<a rel="nofollow" shape="rect" href="mailto:mposolda@redhat.com" target="_blank">mposolda@redhat.com</a>&gt;</span> wrote:<br clear="none"><blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div><span>
    </span><div>On 07/10/15 14:23, Stian Thorgersen
      wrote:<br clear="none">
    </div>
    <blockquote type="cite">
      <div dir="ltr">We should make this configurable. For those worried
        about security they can enforce new refresh tokens as well as
        offline tokens will replace the old tokens. It would be fairly
        simply to implement. If enabled we would only allow refresh
        token where iat is &gt;= the last session refresh time.</div>
    </blockquote>
    I was also thinking about this possibility. However if you have 2
    clients and you refresh the token for client1, the refresh token of
    client2 won&#39;t be valid as his &quot;iat&quot; will be older. Also SSO login
    currently refreshes lastSessionRefresh on UserSession. However maybe
    we can introduce lastSessionRefresh to ClientSession as well?<span><font color="#888888"><br clear="none">
    <br clear="none">
    Marek</font></span><div><div><br clear="none">
    <blockquote type="cite">
      <div dir="ltr">
        <div>I wouldn&#39;t make it default behavior for two reasons:
          <div><br clear="none">
          </div>
          <div>* It would break existing clients if they expect to
            continue using the old refresh token</div>
          <div>* It comes at a performance cost as clients will have to
            store the new refresh tokens and offline tokens each time
            they refresh the token</div>
          <div>* For offline tokens Keycloak would also have to persist
            the last refresh time each time the offline token is
            refreshed</div>
          <div><br clear="none">
          </div>
          <div>I think we&#39;d need to make it a realm wide configuration
            option.<br clear="none">
            <div><br clear="none">
              <div>On 7 October 2015 at 14:12, Marek
                Posolda <span dir="ltr">&lt;<a rel="nofollow" shape="rect" href="mailto:mposolda@redhat.com" target="_blank">mposolda@redhat.com</a>&gt;</span>
                wrote:<br clear="none">
                <blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
                  <div>
                    <div>The points are valid and security can be always
                      improved, however sometimes improving security
                      makes things complicated with the not-so-big
                      advantage... IMO admin should always protect the
                      machine to make sure that nobody unauthorized has
                      access to refresh tokens. And for the transport,
                      HTTPS should be always used. But feel free to
                      create JIRA and we will see...<br clear="none">
                      <br clear="none">
                      When user or client is deleted, all
                      refresh/offline tokens will defacto become invalid
                      as well and can&#39;t be used anymore. You&#39;re right
                      that offline token is still valid after user
                      logout. User can revoke it manually in account
                      management or admin can revoke it in admin
                      console. However refresh token is invalid after
                      user logout. All refresh/offline tokens for
                      particular client can be revoked by admin by set
                      notBefore policy to now, which can be done in
                      admin console in &quot;Revocation&quot; tab of particular
                      client.<span><font color="#888888"><br clear="none">
                          <br clear="none">
                          Marek</font></span>
                      <div>
                        <div><br clear="none">
                          <br clear="none">
                          On 07/10/15 04:27, Raghuram Prabhala wrote:<br clear="none">
                        </div>
                      </div>
                    </div>
                    <div>
                      <div>
                        <blockquote type="cite">
                          <div style="color:#000;background-color:#fff;font-family:Courier New,courier,monaco,monospace,sans-serif;font-size:13px">
                            <div><span>Very valid points Mike and even I
                                have similar concerns. But please do
                                understand that even if the refresh
                                token is stolen or compromised,it cannot
                                be used by any client unless both the
                                client_id and client_secret are also
                                compromised/stolen. But nevertheless, it
                                is a good practice to assume the worst
                                and add in protective measures to
                                minimize the chances. </span></div>
                            <div><span><br clear="none">
                              </span></div>
                            <div>Marek/Bill/Stian - Even our
                              organization is very particular that such
                              potential security issues be addressed.
                              Can this be taken up? BTW I am not sure if
                              you have an API/End point to invalidate
                              tokens for those that are either
                              compromised or must be invalidated as
                              either the user or client is no longer
                              active. If you do not have one then it is
                              a good idea to make one available.</div>
                            <div><br clear="none">
                            </div>
                            <div>Thanks,</div>
                            <div>Raghu</div>
                            <br clear="none">
                            <div style="font-family:Courier New,courier,monaco,monospace,sans-serif;font-size:13px">
                              <div style="font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px">
                                <div dir="ltr">
                                  <hr size="1"> <font face="Arial" size="2"> <b><span style="font-weight:bold">From:</span></b>
                                    &quot;Kuznetsov, Mike&quot; <a rel="nofollow" shape="rect" href="mailto:mikhail.kuznetsov@hpe.com" target="_blank"></a><a rel="nofollow" shape="rect" href="mailto:mikhail.kuznetsov@hpe.com" target="_blank">&lt;mikhail.kuznetsov@hpe.com&gt;</a><br clear="none">
                                    <b><span style="font-weight:bold">To:</span></b>
                                    <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">&quot;keycloak-dev@lists.jboss.org&quot;</a>
                                    <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">&lt;keycloak-dev@lists.jboss.org&gt;</a>
                                    <br clear="none">
                                    <b><span style="font-weight:bold">Cc:</span></b>
                                    &quot;Jagadevan, Kamal&quot; <a rel="nofollow" shape="rect" href="mailto:kamalakannan.jagadevan@hpe.com" target="_blank"></a><a rel="nofollow" shape="rect" href="mailto:kamalakannan.jagadevan@hpe.com" target="_blank">&lt;kamalakannan.jagadevan@hpe.com&gt;</a>
                                    <br clear="none">
                                    <b><span style="font-weight:bold">Sent:</span></b>
                                    Tuesday, October 6, 2015 4:34 PM<br clear="none">
                                    <b><span style="font-weight:bold">Subject:</span></b>
                                    Re: [keycloak-dev] Same Refresh
                                    token can be used multiple times to
                                    obtain access token<br clear="none">
                                  </font> </div>
                                <div><br clear="none">
                                  <div>
                                    <div>
                                      <div>
                                        <div><span style="color:windowtext">Hello,</span></div>
                                        <div><span style="color:windowtext">  </span></div>
                                        <div><span style="color:windowtext">The
                                            reason I brought this up is
                                            that we are currently
                                            working on migrating out
                                            authentication from a
                                            commercially available
                                            product called Ping to
                                            Keycloak. We noticed that
                                            Ping invalidates the refresh
                                            token after it is used once,
                                            while Keycloak does not.</span></div>
                                        <div><span style="color:windowtext">  </span></div>
                                        <div><span style="color:windowtext">I
                                            and my colleague, Kamal are
                                            concerned that by not
                                            invalidating the refresh
                                            token after first use, we
                                            may be opening a security
                                            hole. While SSL may protect
                                            the token in transit, we can
                                            see a scenario where the
                                            refresh token would be
                                            compromised or stolen from
                                            the client itself. In this
                                            case, the stolen refresh
                                            token could be used to get
                                            new access tokens without
                                            the owner of the client
                                            machine knowing. </span></div>
                                        <div><span style="color:windowtext">  </span></div>
                                        <div><span style="color:windowtext">However,
                                            if the behavior was changed
                                            so that the refresh token
                                            could only be used once,
                                            then either:</span></div>
                                        <div><span style="color:windowtext"><span>1.<span style="font:7.0pt">      

                                              </span></span></span><span style="color:windowtext">If
                                            the owner of the client
                                            machine would use the
                                            refresh token first, then
                                            the stolen refresh token
                                            could not be used</span></div>
                                        <div><span style="color:windowtext"><span>2.<span style="font:7.0pt">      

                                              </span></span></span><span style="color:windowtext">If
                                            the stolen refresh token
                                            would be used first, then
                                            the client machine would not
                                            be able to use it and the
                                            user of that client machine
                                            could be alerted that
                                            something was wrong. This
                                            user could then reset their
                                            password or invalidate all
                                            of their access and refresh
                                            tokens.</span></div>
                                        <div><span style="color:windowtext">  </span></div>
                                        <div><span style="color:windowtext">Furthermore,

                                            we are concerned about this
                                            same scenario, but with the
                                            offline token. My
                                            understanding is that the
                                            offline token does not
                                            expire and that it can’t be
                                            invalidated by logging out
                                            the user or changing the
                                            user’s password. Have you
                                            thought about this scenario?</span></div>
                                        <div><span style="color:#1f497d">
                                             </span></div>
                                        <div>Thank You,</div>
                                        <div><span style="font-size:9.0pt"><br clear="none">
                                          </span><b><span style="font-size:10.0pt">Mikhail

                                              Kuznetsov</span></b></div>
                                        <div><span style="font-size:9.0pt">Software
                                            Engineer</span></div>
                                        <div><span style="font-size:9.0pt">Hewlett
                                            Packard Enterprise</span></div>
                                        <div><span style="color:#1f497d">
                                             </span></div>
                                        <div><br clear="none">
                                          <br clear="none">
                                        </div>
                                        <div>
                                          <div>
                                            <div style="border:none;border-top:solid #e1e1e1 1.0pt;padding:3.0pt 0in 0in 0in">
                                              <div><b><span style="color:windowtext">From:</span></b><span style="color:windowtext"> Marek Posolda [<a rel="nofollow" shape="rect" href="mailto:mposolda@redhat.com" target="_blank">mailto:mposolda@redhat.com</a>]
                                                  <br clear="none">
                                                  <b>Sent:</b> Tuesday,
                                                  October 06, 2015 1:16
                                                  PM<br clear="none">
                                                  <b>To:</b> Raghu
                                                  Prabhala<br clear="none">
                                                  <b>Cc:</b> Kuznetsov,
                                                  Mike; <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank"></a><a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br clear="none">
                                                  <b>Subject:</b> Re:
                                                  [keycloak-dev] Same
                                                  Refresh token can be
                                                  used multiple times to
                                                  obtain access token</span></div>
                                            </div>
                                          </div>
                                          <div>  </div>
                                          <div>
                                            <div>Hi Raghu,<br clear="none">
                                              <br clear="none">
                                              &gt;From the specs, it
                                              looks to me that this is
                                              not anything mandatory.
                                              The paragraph is starting
                                              &quot;For example&quot;. Feel free
                                              to create JIRA, but I
                                              personally can&#39;t promise
                                              anything regarding this...<br clear="none">
                                              <br clear="none">
                                              Marek<br clear="none">
                                              <br clear="none">
                                              <br clear="none">
                                              On 06/10/15 17:37, Raghu
                                              Prabhala wrote:<span style="font-size:12.0pt"></span></div>
                                          </div>
                                          <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                                            <div>
                                              <div>Hi Marek - section
                                                10.4 of rfc6749 mentions
                                                that the prior refresh
                                                token should be
                                                invalidated but retained
                                                by the server - to
                                                handle compromise of
                                                refresh tokens as they
                                                are long lived. </div>
                                            </div>
                                            <div>
                                              <div>  </div>
                                            </div>
                                            <div>
                                              <div>Thanks,</div>
                                            </div>
                                            <div>
                                              <div>Raghu<br clear="none">
                                                <br clear="none">
                                                Sent from my iPhone</div>
                                            </div>
                                            <div>
                                              <div style="margin-bottom:12.0pt"><br clear="none">
                                                On Oct 6, 2015, at 10:53
                                                AM, Marek Posolda &lt;<a rel="nofollow" shape="rect" href="mailto:mposolda@redhat.com" target="_blank"></a><a rel="nofollow" shape="rect" href="mailto:mposolda@redhat.com" target="_blank">mposolda@redhat.com</a>&gt;

                                                wrote:</div>
                                            </div>
                                            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                                              <div>
                                                <div>
                                                  <div>You&#39;re right,
                                                    same refresh token
                                                    can be used more
                                                    times. However it is
                                                    still better to use
                                                    refresh token R2 in
                                                    your step 3 instead
                                                    of using old refresh
                                                    token R1 because R2
                                                    has updated
                                                    timestamp (each
                                                    token is valid just
                                                    for 30 minutes or
                                                    so, depends on the
                                                    configured SSO
                                                    session idle
                                                    timeout).<br clear="none">
                                                    <br clear="none">
                                                    Or are you referring
                                                    that this is
                                                    security issue and
                                                    potential
                                                    possibility to Man
                                                    in the middle? If
                                                    you use HTTPS (which
                                                    is recommended for
                                                    production
                                                    environment, and
                                                    especially if you
                                                    have
                                                    unsecured/untrusted
                                                    networkl), this
                                                    shouldn&#39;t be an
                                                    issue.<br clear="none">
                                                    <br clear="none">
                                                    Marek<br clear="none">
                                                    <br clear="none">
                                                    On 06/10/15 16:34,
                                                    Kuznetsov, Mike
                                                    wrote:</div>
                                                </div>
                                                <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                                                  <div>Hello,</div>
                                                  <div> </div>
                                                  <div>I noticed that
                                                    with Keycloak, it
                                                    seems that refresh
                                                    tokens are still
                                                    valid after they are
                                                    used once. This
                                                    means that Keycloak
                                                    does <b>not</b>
                                                    invalidate Refresh
                                                    Tokens after they
                                                    have been used once.</div>
                                                  <div> </div>
                                                  <div>I am able to
                                                    successfully execute
                                                    the following flow:</div>
                                                  <div><span>1.<span style="font:7.0pt">      

                                                      </span></span>Obtain
                                                    Access Token (A1)
                                                    and Refresh Token
                                                    (R1)</div>
                                                  <div><span>2.<span style="font:7.0pt">      

                                                      </span></span>Use
                                                    Refresh Token (R1)
                                                    to obtain new Access
                                                    Token (A2) and
                                                    Refresh Token (R2)</div>
                                                  <div><span>3.<span style="font:7.0pt">      

                                                      </span></span>Use
                                                    same Refresh Token
                                                    (R1) again to obtain
                                                    new Access Token
                                                    (A3) and Refresh
                                                    Token (R3)</div>
                                                  <div> </div>
                                                  <div> </div>
                                                  <div>Can you please
                                                    tell me if this is
                                                    the intended
                                                    functionality?</div>
                                                  <div> </div>
                                                  <div>Thank You,</div>
                                                  <div><span style="font-size:9.0pt"><br clear="none">
                                                    </span><b><span style="font-size:10.0pt">Mikhail

                                                        Kuznetsov</span></b></div>
                                                  <div><span style="font-size:9.0pt">Software

                                                      Engineer</span></div>
                                                  <div><span style="font-size:9.0pt">Hewlett

                                                      Packard Enterprise</span></div>
                                                  <div> </div>
                                                  <div><span style="font-size:12.0pt"><br clear="none">
                                                      <br clear="none">
                                                      <br clear="none">
                                                    </span></div>
                                                  <pre>_______________________________________________</pre>
                                                  <pre>keycloak-dev mailing list</pre>
                                                  <pre><a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a></pre>
                                                  <pre><a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></pre>
                                                </blockquote>
                                                <div><span style="font-size:12.0pt">
                                                     </span></div>
                                              </div>
                                            </blockquote>
                                            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
                                              <div>
                                                <div><span style="font-size:12.0pt">_______________________________________________<br clear="none">
                                                    keycloak-dev mailing
                                                    list<br clear="none">
                                                    <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank"></a><a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br clear="none">
                                                    <a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank"></a><a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></span></div>
                                              </div>
                                            </blockquote>
                                          </blockquote>
                                        </div>
                                        <div><span style="font-size:12.0pt">  </span></div>
                                      </div>
                                    </div>
                                  </div>
                                  <br clear="none">
                                  <div>_______________________________________________<br clear="none">
                                    keycloak-dev mailing list<br clear="none">
                                    <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br clear="none">
                                    <a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></div>
                                  <br clear="none">
                                  <br clear="none">
                                </div>
                              </div>
                            </div>
                          </div>
                          <br clear="none">
                          <fieldset></fieldset>
                          <br clear="none">
                          <pre>_______________________________________________
keycloak-dev mailing list
<a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a>
<a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></pre>
                        </blockquote>
                        <br clear="none">
                      </div>
                    </div>
                  </div>
                  <br clear="none">
                  _______________________________________________<br clear="none">
                  keycloak-dev mailing list<br clear="none">
                  <a rel="nofollow" shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br clear="none">
                  <a rel="nofollow" shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a><br clear="none">
                </blockquote>
              </div>
              <br clear="none">
            </div>
          </div>
        </div>
      </div>
    </blockquote>
    <br clear="none">
  </div></div></div>

</blockquote></div><br clear="none"></div></div></div></div><br><div>_______________________________________________<br clear="none">keycloak-dev mailing list<br clear="none"><a shape="rect" href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br clear="none"><a shape="rect" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></div><br><br></div> </div></div></div> </div>  </div></div></blockquote></div><br></div>