@@ -46,7 +46,9 @@ import Brig.User.Auth.Cookie.Limit
46
46
import qualified Brig.User.Auth.DB.Cookie as DB
47
47
import qualified Brig.ZAuth as ZAuth
48
48
import Cassandra
49
+ import Control.Error.Util
49
50
import Control.Lens (to , view )
51
+ import Control.Monad.Trans.Maybe
50
52
import Data.ByteString.Conversion
51
53
import Data.Id
52
54
import qualified Data.List as List
@@ -105,31 +107,35 @@ nextCookie ::
105
107
MonadClient m
106
108
) =>
107
109
Cookie (ZAuth. Token u ) ->
110
+ Maybe ClientId ->
108
111
m (Maybe (Cookie (ZAuth. Token u )))
109
- nextCookie c = do
112
+ nextCookie c mNewCid = runMaybeT $ do
113
+ let mOldCid = ZAuth. userTokenClient (cookieValue c)
114
+ -- Keep old client ID by default, but use new one if none was set.
115
+ let mcid = mOldCid <|> mNewCid
116
+
110
117
s <- view settings
111
118
now <- liftIO =<< view currentTime
112
119
let created = cookieCreated c
113
120
let renewAge = fromInteger (setUserCookieRenewAge s)
114
- -- TODO: Also renew the cookie if it was signed with
115
- -- a different zauth key index, regardless of age.
116
- if persist c && diffUTCTime now created > renewAge
117
- then Just <$> getNext
118
- else pure Nothing
119
- where
120
- persist = (PersistentCookie == ) . cookieType
121
- getNext = case cookieSucc c of
122
- Nothing -> renewCookie c
123
- Just ck -> do
124
- let uid = ZAuth. userTokenOf (cookieValue c)
125
- cid = ZAuth. userTokenClient (cookieValue c)
126
- trackSuperseded uid (cookieId c)
127
- cs <- DB. listCookies uid
128
- case List. find (\ x -> cookieId x == ck && persist x) cs of
129
- Nothing -> renewCookie c
130
- Just c' -> do
131
- t <- ZAuth. mkUserToken uid cid (cookieIdNum ck) (cookieExpires c')
132
- pure c' {cookieValue = t}
121
+ -- Renew the cookie if the client ID has changed, regardless of age.
122
+ -- FUTUREWORK: Also renew the cookie if it was signed with a different zauth
123
+ -- key index, regardless of age.
124
+ when (mcid /= mOldCid) $ do
125
+ guard (cookieType c == PersistentCookie )
126
+ guard (diffUTCTime now created > renewAge)
127
+ lift $ do
128
+ c' <- runMaybeT $ do
129
+ ck <- hoistMaybe $ cookieSucc c
130
+ let uid = ZAuth. userTokenOf (cookieValue c)
131
+ lift $ trackSuperseded uid (cookieId c)
132
+ cs <- lift $ DB. listCookies uid
133
+ c' <-
134
+ hoistMaybe $
135
+ List. find (\ x -> cookieId x == ck && cookieType x == PersistentCookie ) cs
136
+ t <- lift $ ZAuth. mkUserToken uid mcid (cookieIdNum ck) (cookieExpires c')
137
+ pure c' {cookieValue = t}
138
+ maybe (renewCookie c mcid) pure c'
133
139
134
140
-- | Renew the given cookie with a fresh token.
135
141
renewCookie ::
@@ -139,13 +145,13 @@ renewCookie ::
139
145
MonadClient m
140
146
) =>
141
147
Cookie (ZAuth. Token u ) ->
148
+ Maybe ClientId ->
142
149
m (Cookie (ZAuth. Token u ))
143
- renewCookie old = do
150
+ renewCookie old mcid = do
144
151
let t = cookieValue old
145
152
let uid = ZAuth. userTokenOf t
146
- cid = ZAuth. userTokenClient t
147
153
-- Insert new cookie
148
- new <- newCookie uid cid (cookieType old) (cookieLabel old)
154
+ new <- newCookie uid mcid (cookieType old) (cookieLabel old)
149
155
-- Link the old cookie to the new (successor), keeping it
150
156
-- around only for another renewal period so as not to build
151
157
-- an ever growing chain of superseded cookies.
0 commit comments