-
Notifications
You must be signed in to change notification settings - Fork 26
/
Jwt.hs
51 lines (42 loc) · 1.73 KB
/
Jwt.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
module Lib.Effects.Jwt
( -- * Jwt Effect monad
MonadJwt (..)
-- * Internals of 'MonadJwt'
, mkJwtTokenImpl
, decodeAndVerifyJwtTokenImpl
) where
import Data.Time.Clock.POSIX (getPOSIXTime)
import Lib.App (App, Has (..), grab)
import Lib.Core.Jwt (JwtPayload, JwtSecret (..), JwtToken (..), jwtPayloadFromMap, jwtPayloadToMap)
import Lib.Time (Seconds (..))
import qualified Web.JWT as JWT
class Monad m => MonadJwt m where
mkJwtToken :: Seconds -> JwtPayload -> m JwtToken
decodeAndVerifyJwtToken :: JwtToken -> m (Maybe JwtPayload)
instance MonadJwt App where
mkJwtToken = mkJwtTokenImpl
decodeAndVerifyJwtToken = decodeAndVerifyJwtTokenImpl
mkJwtTokenImpl
:: (MonadIO m, MonadReader r m, Has JwtSecret r)
=> Seconds -> JwtPayload -> m JwtToken
mkJwtTokenImpl (Seconds expiry) payload = do
secret <- JWT.hmacSecret . unJwtSecret <$> grab
timeNow <- liftIO getPOSIXTime
let expiryTime = timeNow + fromIntegral expiry
let claimsSet = mempty
{ JWT.exp = JWT.numericDate expiryTime
, JWT.unregisteredClaims = jwtPayloadToMap payload
}
pure $ JwtToken $ JWT.encodeSigned secret claimsSet
decodeAndVerifyJwtTokenImpl
:: (MonadIO m, MonadReader r m, Has JwtSecret r)
=> JwtToken -> m (Maybe JwtPayload)
decodeAndVerifyJwtTokenImpl (JwtToken token) = do
secret <- JWT.hmacSecret . unJwtSecret <$> grab
timeNow <- JWT.numericDate <$> liftIO getPOSIXTime
pure $ do
claimsSet <- JWT.claims <$> JWT.decodeAndVerifySignature secret token
expiryTimeStatedInToken <- JWT.exp claimsSet
now <- timeNow
guard (expiryTimeStatedInToken >= now)
jwtPayloadFromMap $ JWT.unregisteredClaims claimsSet