Skip to content
This repository has been archived by the owner on Oct 29, 2021. It is now read-only.

Have the validation keys as an IORef #193

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import Crypto.JWT as Jose
import qualified Data.ByteString as BS
import Data.Default.Class
import Data.Time
import Data.IORef (IORef)
import GHC.Generics (Generic)
import Servant.API (IsSecure(..))
import GHC.IORef (newIORef)

data IsMatch = Matches | DoesNotMatch
deriving (Eq, Show, Read, Generic, Ord)
Expand All @@ -33,18 +35,19 @@ data JWTSettings = JWTSettings
-- | Algorithm used to sign JWT.
, jwtAlg :: Maybe Jose.Alg
-- | Keys used to validate JWT.
, validationKeys :: Jose.JWKSet
, validationKeys :: IORef Jose.JWKSet
-- | An @aud@ predicate. The @aud@ is a string or URI that identifies the
-- intended recipient of the JWT.
, audienceMatches :: Jose.StringOrURI -> IsMatch
} deriving (Generic)

-- | A @JWTSettings@ where the audience always matches.
defaultJWTSettings :: Jose.JWK -> JWTSettings
defaultJWTSettings k = JWTSettings
defaultJWTSettings :: Jose.JWK -> IO JWTSettings
Copy link
Author

@dnikolovv dnikolovv Jun 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking we could even omit the IO via unsafePerformIO to avoid forcing existing users change their code. It should be relatively safe as the only thing we're doing is create a new IORef.

This will make the changes even less invasive (or in most cases invisible).

I guess @jkarni @domenkozar or other maintainers should give their opinion on that.

defaultJWTSettings k = newIORef (Jose.JWKSet [k]) >>= \keysRef ->
return $ JWTSettings
{ signingKey = k
, jwtAlg = Nothing
, validationKeys = Jose.JWKSet [k]
, validationKeys = keysRef
, audienceMatches = const Matches }

-- | The policies to use when generating cookies.
Expand Down
8 changes: 3 additions & 5 deletions servant-auth-server/src/Servant/Auth/Server/Internal/JWT.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ import Control.Monad.Except
import Control.Monad.Reader
import qualified Crypto.JOSE as Jose
import qualified Crypto.JWT as Jose
import Data.Aeson (FromJSON, Result (..), ToJSON, fromJSON,
toJSON)
import Data.ByteArray (constEq)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import qualified Data.HashMap.Strict as HM
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import Data.Time (UTCTime)
import Network.Wai (requestHeaders)

import Servant.Auth.JWT (FromJWT(..), ToJWT(..))
import Servant.Auth.Server.Internal.ConfigTypes
import Servant.Auth.Server.Internal.Types
import Data.IORef (readIORef)


-- | A JWT @AuthCheck@. You likely won't need to use this directly unless you
Expand Down Expand Up @@ -60,9 +57,10 @@ verifyJWT :: FromJWT a => JWTSettings -> BS.ByteString -> IO (Maybe a)
verifyJWT jwtCfg input = do
verifiedJWT <- liftIO $ runExceptT $ do
unverifiedJWT <- Jose.decodeCompact (BSL.fromStrict input)
keys <- liftIO . readIORef $ validationKeys jwtCfg
Jose.verifyClaims
(jwtSettingsToJwtValidationSettings jwtCfg)
(validationKeys jwtCfg)
keys
unverifiedJWT
return $ case verifiedJWT of
Left (_ :: Jose.JWTError) -> Nothing
Expand Down
12 changes: 12 additions & 0 deletions stack.yaml.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files

packages: []
snapshots:
- completed:
size: 587963
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2021/6/1.yaml
sha256: 6f13285c82266d1d06f7f68366a5190dcbc6758ae8806813005cf56daa6bb9be
original: nightly-2021-06-01