graphql-engine/server/src-lib/Hasura/Server/Auth.hs

310 lines
12 KiB
Haskell
Raw Normal View History

{-# LANGUAGE DerivingStrategies #-}
module Hasura.Server.Auth
( getUserInfoWithExpTime,
AuthMode (..),
compareAuthMode,
setupAuthMode,
AdminSecretHash,
unsafeMkAdminSecretHash,
hashAdminSecret,
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
updateJwkCtx,
-- * WebHook related
AuthHookType (..),
AuthHook (..),
-- * JWT related
RawJWT,
JWTConfig (..),
JWTCtx (..),
JWKSet (..),
processJwt,
UserAuthentication (..),
-- * Exposed for testing
getUserInfoWithExpTime_,
)
where
import Control.Monad.Trans.Control (MonadBaseControl)
import Crypto.Hash qualified as Crypto
import Data.ByteArray qualified as BA
import Data.ByteString (ByteString)
import Data.HashSet qualified as Set
import Data.Hashable qualified as Hash
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
import Data.IORef (newIORef, readIORef)
import Data.List qualified as L
import Data.Text.Encoding qualified as T
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
import Data.Time.Clock (UTCTime, getCurrentTime)
import Hasura.Base.Error
import Hasura.GraphQL.Transport.HTTP.Protocol (ReqsText)
import Hasura.Logging
import Hasura.Prelude
import Hasura.Server.Auth.JWT hiding (processJwt_)
import Hasura.Server.Auth.WebHook
import Hasura.Server.Utils
import Hasura.Session
import Network.HTTP.Client qualified as HTTP
import Network.HTTP.Types qualified as HTTP
-- | Typeclass representing the @UserInfo@ authorization and resolving effect
class (Monad m) => UserAuthentication m where
resolveUserInfo ::
Logger Hasura ->
HTTP.Manager ->
-- | request headers
[HTTP.Header] ->
AuthMode ->
Maybe ReqsText ->
m (Either QErr (UserInfo, Maybe UTCTime, [HTTP.Header], ExtraUserInfo))
-- | The hashed admin password. 'hashAdminSecret' is our public interface for
-- constructing the secret.
--
-- To prevent misuse and leaking we keep this opaque and don't provide
-- instances that could leak information. Likewise for 'AuthMode'.
--
-- Although this exists only in memory we store only a hash of the admin secret
-- primarily in order to:
--
-- - prevent theoretical timing attacks from a naive `==` check
-- - prevent misuse or inadvertent leaking of the secret
newtype AdminSecretHash = AdminSecretHash (Crypto.Digest Crypto.SHA512)
deriving (Ord, Eq)
unsafeMkAdminSecretHash :: (Crypto.Digest Crypto.SHA512) -> AdminSecretHash
unsafeMkAdminSecretHash = AdminSecretHash
instance Hash.Hashable AdminSecretHash where
hashWithSalt salt (AdminSecretHash h) = Hash.hashWithSalt @ByteString salt $ BA.convert h
-- We don't want to be able to leak the secret hash. This is a dummy instance
-- to support 'Show AuthMode' which we want for testing.
instance Show AdminSecretHash where
show _ = "(error \"AdminSecretHash hidden\")"
hashAdminSecret :: Text -> AdminSecretHash
hashAdminSecret = AdminSecretHash . Crypto.hash . T.encodeUtf8
-- | The methods we'll use to derive roles for authenticating requests.
--
-- @Maybe RoleName@ below is the optionally-defined role for the
-- unauthenticated (anonymous) user.
--
-- See: https://hasura.io/docs/latest/graphql/core/auth/authentication/unauthenticated-access.html
data AuthMode
= AMNoAuth
| AMAdminSecret !(Set.HashSet AdminSecretHash) !(Maybe RoleName)
| AMAdminSecretAndHook !(Set.HashSet AdminSecretHash) !AuthHook
| AMAdminSecretAndJWT !(Set.HashSet AdminSecretHash) ![JWTCtx] !(Maybe RoleName)
deriving (Eq, Show)
-- | In case JWT is used as an authentication mode, the JWKs are stored inside JWTCtx
-- as an `IORef`. `IORef` has pointer equality, so we need to compare the values
-- inside the `IORef` to check if the `JWTCtx` is same.
compareAuthMode :: AuthMode -> AuthMode -> IO Bool
compareAuthMode authMode authMode' = do
case (authMode, authMode') of
((AMAdminSecretAndJWT adminSecretHash jwtCtx roleName), (AMAdminSecretAndJWT adminSecretHash' jwtCtx' roleName')) -> do
-- Since keyConfig of JWTCtx is an IORef it is necessary to extract the value before checking the equality
isJwtCtxSame <- zipWithM compareJWTConfig jwtCtx jwtCtx'
return $ (adminSecretHash == adminSecretHash') && (and isJwtCtxSame) && (roleName == roleName')
_ -> return $ authMode == authMode'
where
compareJWTConfig :: JWTCtx -> JWTCtx -> IO Bool
compareJWTConfig (JWTCtx url keyConfigRef audM iss claims allowedSkew headers) (JWTCtx url' keyConfigRef' audM' iss' claims' allowedSkew' headers') = do
keyConfig <- readIORef keyConfigRef
keyConfig' <- readIORef keyConfigRef'
return $ (url, keyConfig, audM, iss, claims, allowedSkew, headers) == (url', keyConfig', audM', iss', claims', allowedSkew', headers')
-- | Validate the user's requested authentication configuration, launching any
-- required maintenance threads for JWT etc.
--
-- This must only be run once, on launch.
setupAuthMode ::
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
( MonadError Text m,
MonadIO m,
MonadBaseControl IO m
) =>
Set.HashSet AdminSecretHash ->
Maybe AuthHook ->
[JWTConfig] ->
Maybe RoleName ->
Logger Hasura ->
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
HTTP.Manager ->
m AuthMode
setupAuthMode adminSecretHashSet mWebHook mJwtSecrets mUnAuthRole logger httpManager =
case (not (Set.null adminSecretHashSet), mWebHook, not (null mJwtSecrets)) of
(True, Nothing, False) -> return $ AMAdminSecret adminSecretHashSet mUnAuthRole
(True, Nothing, True) -> do
jwtCtxs <- traverse mkJwtCtx (L.nub mJwtSecrets)
pure $ AMAdminSecretAndJWT adminSecretHashSet jwtCtxs mUnAuthRole
-- Nothing below this case uses unauth role. Throw a fatal error if we would otherwise ignore
-- that parameter, lest users misunderstand their auth configuration:
_
| isJust mUnAuthRole ->
throwError $
"Fatal Error: --unauthorized-role (HASURA_GRAPHQL_UNAUTHORIZED_ROLE)"
<> requiresAdminScrtMsg
<> " and is not allowed when --auth-hook (HASURA_GRAPHQL_AUTH_HOOK) is set"
(False, Nothing, False) -> return AMNoAuth
(True, Just hook, False) -> return $ AMAdminSecretAndHook adminSecretHashSet hook
(False, Just _, False) ->
throwError $
"Fatal Error : --auth-hook (HASURA_GRAPHQL_AUTH_HOOK)" <> requiresAdminScrtMsg
(False, Nothing, True) ->
throwError $
"Fatal Error : --jwt-secret (HASURA_GRAPHQL_JWT_SECRET)" <> requiresAdminScrtMsg
(_, Just _, True) ->
throwError
"Fatal Error: Both webhook and JWT mode cannot be enabled at the same time"
where
requiresAdminScrtMsg =
" requires --admin-secret (HASURA_GRAPHQL_ADMIN_SECRET) or "
<> " --access-key (HASURA_GRAPHQL_ACCESS_KEY) to be set"
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
mkJwtCtx :: (MonadIO m, MonadBaseControl IO m, MonadError Text m) => JWTConfig -> m JWTCtx
mkJwtCtx JWTConfig {..} = do
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
(jwkUri, jwkKeyConfig) <- case jcKeyOrUrl of
Left jwk -> do
jwkRef <- liftIO $ newIORef (JWKSet [jwk], Nothing)
return (Nothing, jwkRef)
-- in case JWT url is provided, an empty JWKSet is initialised,
-- which will be populated by the 'updateJWKCtx' poller thread
Right uri -> do
-- fetch JWK initially and throw error if it fails
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
void $ withJwkError $ fetchJwk logger httpManager uri
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
jwkRef <- liftIO $ newIORef (JWKSet [], Nothing)
return (Just uri, jwkRef)
let jwtHeader = fromMaybe JHAuthorization jcHeader
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
return $ JWTCtx jwkUri jwkKeyConfig jcAudience jcIssuer jcClaims jcAllowedSkew jwtHeader
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
withJwkError a = do
res <- runExceptT a
onLeft res \case
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
-- when fetching JWK initially, except expiry parsing error, all errors are critical
JFEHttpException _ msg -> throwError msg
JFEHttpError _ _ _ e -> throwError e
JFEJwkParseError _ e -> throwError e
JFEExpiryParseError _ _ -> pure (JWKSet [], [])
-- | Update the JWK based on the expiry time specified in @Expires@ header or
-- @Cache-Control@ header
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
updateJwkCtx ::
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
forall m.
(MonadIO m, MonadBaseControl IO m) =>
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
AuthMode ->
HTTP.Manager ->
Logger Hasura ->
m ()
updateJwkCtx authMode httpManager logger = do
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
case authMode of
AMAdminSecretAndJWT _ jwtCtxs _ -> traverse_ updateJwkFromUrl jwtCtxs
_ -> pure ()
where
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
updateJwkFromUrl :: JWTCtx -> m ()
server: update the jwt refresh thread to poll ## Description This PR updates the JWK refresh thread to poll every second instead of the previous behaviour where the thread used to sleep based on the expiry time in `Cache-Control`/`Expires` response headers. ## Motivation As a part of dynamically updating environment variables on cloud without restart the user projects, we want to implement a mechanism which makes HGE aware of any changes in the user configuration by updating a shared variable data type which can be accessed by relevant threads/core functionality before their execution. The above updates requires us to make the threads polling in nature such that before executing their code, any change in the user config is captured and the appropriate behaviour is channelised. In the case of JWK updating thread, the thread used to sleep for the time as mentioned in the `Cache-Control` or `Expires` headers which make the thread unware of any new changes in the user config in that period of time, hence requiring a restart to propogate the new changes. To solve this problem we have now updated the JWK update thread to poll every second for change in `AuthMode`(from a shared variable in subsequent changes to implement the dynamic env var update feature) and update the JWK accordingly such that it does not use any stale configurations and works without HGE restart. ### Related Issues https://hasurahq.atlassian.net/browse/GS-300 ### Solution and Design - We store the expiry time in the `JWTCtx` - On every poll check whether the current time exceeds the expiry time, in which case we call the JWK url to fetch the new JWK and expiry. PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7177 Co-authored-by: Krushan Bauva <31391329+krushanbauva@users.noreply.github.com> Co-authored-by: Anon Ray <616387+ecthiender@users.noreply.github.com> GitOrigin-RevId: bc1e44a8c3823d7554167a7f01c3ce085646cedb
2023-01-06 09:39:10 +03:00
updateJwkFromUrl (JWTCtx url ref _ _ _ _ _) =
for_ url \uri -> do
(jwkSet, jwkExpiry) <- liftIO $ readIORef ref
case jwkSet of
-- get the JWKs initially if the JWKSet is empty
JWKSet [] -> fetchAndUpdateJWKs logger httpManager uri ref
-- if the JWKSet is not empty, get the new JWK based on the
-- expiry time
_ -> do
currentTime <- liftIO getCurrentTime
for_ jwkExpiry \expiryTime ->
when (currentTime >= expiryTime) $
fetchAndUpdateJWKs logger httpManager uri ref
-- | Authenticate the request using the headers and the configured 'AuthMode'.
getUserInfoWithExpTime ::
forall m.
Rewrite `Tracing` to allow for only one `TraceT` in the entire stack. This PR is on top of #7789. ### Description This PR entirely rewrites the API of the Tracing library, to make `interpTraceT` a thing of the past. Before this change, we ran traces by sticking a `TraceT` on top of whatever we were doing. This had several major drawbacks: - we were carrying a bunch of `TraceT` across the codebase, and the entire codebase had to know about it - we needed to carry a second class constraint around (`HasReporterM`) to be able to run all of those traces - we kept having to do stack rewriting with `interpTraceT`, which went from inconvenient to horrible - we had to declare several behavioral instances on `TraceT m` This PR rewrite all of `Tracing` using a more conventional model: there is ONE `TraceT` at the bottom of the stack, and there is an associated class constraint `MonadTrace`: any part of the code that happens to satisfy `MonadTrace` is able to create new traces. We NEVER have to do stack rewriting, `interpTraceT` is gone, and `TraceT` and `Reporter` become implementation details that 99% of the code is blissfully unaware of: code that needs to do tracing only needs to declare that the monad in which it operates implements `MonadTrace`. In doing so, this PR revealed **several bugs in the codebase**: places where we were expecting to trace something, but due to the default instance of `HasReporterM IO` we would actually not do anything. This PR also splits the code of `Tracing` in more byte-sized modules, with the goal of potentially moving to `server/lib` down the line. ### Remaining work This PR is a draft; what's left to do is: - [x] make Pro compile; i haven't updated `HasuraPro/Main` yet - [x] document Tracing by writing a note that explains how to use the library, and the meaning of "reporter", "trace" and "span", as well as the pitfalls - [x] discuss some of the trade-offs in the implementation, which is why i'm opening this PR already despite it not fully building yet - [x] it depends on #7789 being merged first PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7791 GitOrigin-RevId: cadd32d039134c93ddbf364599a2f4dd988adea8
2023-03-13 20:37:16 +03:00
(MonadIO m, MonadBaseControl IO m, MonadError QErr m) =>
Logger Hasura ->
HTTP.Manager ->
[HTTP.Header] ->
AuthMode ->
Maybe ReqsText ->
m (UserInfo, Maybe UTCTime, [HTTP.Header])
getUserInfoWithExpTime = getUserInfoWithExpTime_ userInfoFromAuthHook processJwt
-- Broken out for testing with mocks:
getUserInfoWithExpTime_ ::
forall m mgr logger.
(MonadIO m, MonadError QErr m) =>
-- | mock 'userInfoFromAuthHook'
( logger ->
mgr ->
AuthHook ->
[HTTP.Header] ->
Maybe ReqsText ->
m (UserInfo, Maybe UTCTime, [HTTP.Header])
) ->
-- | mock 'processJwt'
( [JWTCtx] ->
[HTTP.Header] ->
Maybe RoleName ->
m (UserInfo, Maybe UTCTime, [HTTP.Header])
) ->
logger ->
mgr ->
[HTTP.Header] ->
AuthMode ->
Maybe ReqsText ->
m (UserInfo, Maybe UTCTime, [HTTP.Header])
getUserInfoWithExpTime_ userInfoFromAuthHook_ processJwt_ logger manager rawHeaders authMode reqs = case authMode of
2020-05-05 22:57:17 +03:00
AMNoAuth -> withNoExpTime $ mkUserInfoFallbackAdminRole UAuthNotSet
-- If hasura was started with an admin secret we:
-- - check if a secret was sent in the request
-- - if so, check it and authorize as admin else fail
-- - if not proceed with either webhook or JWT auth if configured
AMAdminSecret adminSecretHashSet maybeUnauthRole ->
checkingSecretIfSent adminSecretHashSet $
server: forward auth webhook set-cookies header on response > High-Level TODO: * [x] Code Changes * [x] Tests * [x] Check that pro/multitenant build ok * [x] Documentation Changes * [x] Updating this PR with full details * [ ] Reviews * [ ] Ensure code has all FIXMEs and TODOs addressed * [x] Ensure no files are checked in mistakenly * [x] Consider impact on console, cli, etc. ### Description > This PR adds support for adding set-cookie header on the response from the auth webhook. If the set-cookie header is sent by the webhook, it will be forwarded in the graphQL engine response. Fixes a bug in test-server.sh: testing of get-webhook tests was done by POST method and vice versa. To fix, the parameters were swapped. ### Changelog - [x] `CHANGELOG.md` is updated with user-facing content relevant to this PR. ### Affected components - [x] Server - [ ] Console - [ ] CLI - [x] Docs - [ ] Community Content - [ ] Build System - [x] Tests - [ ] Other (list it) ### Related Issues -> Closes [#2269](https://github.com/hasura/graphql-engine/issues/2269) ### Solution and Design > ### Steps to test and verify > Please refer to the docs to see how to send the set-cookie header from webhook. ### Limitations, known bugs & workarounds > - Support for only set-cookie header forwarding is added - the value forwarded in the set-cookie header cannot be validated completely, the [Cookie](https://hackage.haskell.org/package/cookie) package has been used to parse the header value and any unnecessary information is stripped off before forwarding the header. The standard given in [RFC6265](https://datatracker.ietf.org/doc/html/rfc6265) has been followed for the Set-Cookie format. ### Server checklist #### Catalog upgrade Does this PR change Hasura Catalog version? - [x] No - [ ] Yes - [ ] Updated docs with SQL for downgrading the catalog #### Metadata Does this PR add a new Metadata feature? - [x] No #### GraphQL - [x] No new GraphQL schema is generated - [ ] New GraphQL schema is being generated: - [ ] New types and typenames are correlated #### Breaking changes - [x] No Breaking changes PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2538 Co-authored-by: Robert <132113+robx@users.noreply.github.com> GitOrigin-RevId: d9047e997dd221b7ce4fef51911c3694037e7c3f
2021-11-09 15:00:21 +03:00
withNoExpTime
-- Consider unauthorized role, if not found raise admin secret header required exception
case maybeUnauthRole of
Nothing ->
throw401 $
adminSecretHeader
<> "/"
<> deprecatedAccessKeyHeader
<> " required, but not found"
Just unAuthRole ->
mkUserInfo (URBPreDetermined unAuthRole) UAdminSecretNotSent sessionVariables
-- this is the case that actually ends up consuming the request AST
AMAdminSecretAndHook adminSecretHashSet hook ->
checkingSecretIfSent adminSecretHashSet $ userInfoFromAuthHook_ logger manager hook rawHeaders reqs
AMAdminSecretAndJWT adminSecretHashSet jwtSecrets unAuthRole ->
checkingSecretIfSent adminSecretHashSet $ processJwt_ jwtSecrets rawHeaders unAuthRole
where
-- CAREFUL!:
2020-05-05 22:57:17 +03:00
mkUserInfoFallbackAdminRole adminSecretState =
mkUserInfo
(URBFromSessionVariablesFallback adminRoleName)
adminSecretState
sessionVariables
sessionVariables = mkSessionVariablesHeaders rawHeaders
checkingSecretIfSent ::
Set.HashSet AdminSecretHash -> m (UserInfo, Maybe UTCTime, [HTTP.Header]) -> m (UserInfo, Maybe UTCTime, [HTTP.Header])
checkingSecretIfSent adminSecretHashSet actionIfNoAdminSecret = do
2020-05-05 22:57:17 +03:00
let maybeRequestAdminSecret =
foldl1 (<|>) $
map
(`getSessionVariableValue` sessionVariables)
[adminSecretHeader, deprecatedAccessKeyHeader]
2020-05-05 22:57:17 +03:00
-- when admin secret is absent, run the action to retrieve UserInfo
case maybeRequestAdminSecret of
Nothing -> actionIfNoAdminSecret
2020-05-05 22:57:17 +03:00
Just requestAdminSecret -> do
unless (Set.member (hashAdminSecret requestAdminSecret) adminSecretHashSet) $
throw401 $
"invalid " <> adminSecretHeader <> "/" <> deprecatedAccessKeyHeader
2020-05-05 22:57:17 +03:00
withNoExpTime $ mkUserInfoFallbackAdminRole UAdminSecretSent
server: forward auth webhook set-cookies header on response > High-Level TODO: * [x] Code Changes * [x] Tests * [x] Check that pro/multitenant build ok * [x] Documentation Changes * [x] Updating this PR with full details * [ ] Reviews * [ ] Ensure code has all FIXMEs and TODOs addressed * [x] Ensure no files are checked in mistakenly * [x] Consider impact on console, cli, etc. ### Description > This PR adds support for adding set-cookie header on the response from the auth webhook. If the set-cookie header is sent by the webhook, it will be forwarded in the graphQL engine response. Fixes a bug in test-server.sh: testing of get-webhook tests was done by POST method and vice versa. To fix, the parameters were swapped. ### Changelog - [x] `CHANGELOG.md` is updated with user-facing content relevant to this PR. ### Affected components - [x] Server - [ ] Console - [ ] CLI - [x] Docs - [ ] Community Content - [ ] Build System - [x] Tests - [ ] Other (list it) ### Related Issues -> Closes [#2269](https://github.com/hasura/graphql-engine/issues/2269) ### Solution and Design > ### Steps to test and verify > Please refer to the docs to see how to send the set-cookie header from webhook. ### Limitations, known bugs & workarounds > - Support for only set-cookie header forwarding is added - the value forwarded in the set-cookie header cannot be validated completely, the [Cookie](https://hackage.haskell.org/package/cookie) package has been used to parse the header value and any unnecessary information is stripped off before forwarding the header. The standard given in [RFC6265](https://datatracker.ietf.org/doc/html/rfc6265) has been followed for the Set-Cookie format. ### Server checklist #### Catalog upgrade Does this PR change Hasura Catalog version? - [x] No - [ ] Yes - [ ] Updated docs with SQL for downgrading the catalog #### Metadata Does this PR add a new Metadata feature? - [x] No #### GraphQL - [x] No new GraphQL schema is generated - [ ] New GraphQL schema is being generated: - [ ] New types and typenames are correlated #### Breaking changes - [x] No Breaking changes PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2538 Co-authored-by: Robert <132113+robx@users.noreply.github.com> GitOrigin-RevId: d9047e997dd221b7ce4fef51911c3694037e7c3f
2021-11-09 15:00:21 +03:00
withNoExpTime a = (,Nothing,[]) <$> a