diff --git a/atlassian-connect-core.cabal b/atlassian-connect-core.cabal
--- a/atlassian-connect-core.cabal
+++ b/atlassian-connect-core.cabal
@@ -10,7 +10,7 @@
 -- PVP summary:      +-+------- breaking API changes
 --                   | | +----- non-breaking API additions
 --                   | | | +--- code changes with no API change
-version:             0.8.0.1
+version:             0.8.1.0
 
 -- A short (one-line) description of the package.
 synopsis:            Atlassian Connect snaplet for the Snap Framework and helper code.
@@ -95,7 +95,7 @@
   -- Other library packages from which modules are imported.
   build-depends:       base >=4.7 && < 5
                        , atlassian-connect-descriptor >= 0.4.5
-                       , jwt                >= 0.6
+                       , jwt                >= 0.6 && < 0.8
                        , aeson              >=  0.7.0.3
                        , bytestring         >= 0.9
                        , base64-bytestring  == 1.0.*
diff --git a/src/Snap/AtlassianConnect.hs b/src/Snap/AtlassianConnect.hs
--- a/src/Snap/AtlassianConnect.hs
+++ b/src/Snap/AtlassianConnect.hs
@@ -50,6 +50,8 @@
     , Tenant(..)
     , TenantKey
     , TenantWithUser
+    -- * QSH
+    , generateQSH
     -- * Page Tokens
     , PageToken(..) -- TODO make it so that you can query the token but nothing else
     , generateToken
@@ -75,4 +77,5 @@
 import           Snap.AtlassianConnect.Routes
 import           Snap.AtlassianConnect.Tenant
 import           Snap.AtlassianConnect.TimeUnits
+import           Snap.AtlassianConnect.QueryStringHash (generateQSH)
 
diff --git a/src/Snap/AtlassianConnect/QueryStringHash.hs b/src/Snap/AtlassianConnect/QueryStringHash.hs
--- a/src/Snap/AtlassianConnect/QueryStringHash.hs
+++ b/src/Snap/AtlassianConnect/QueryStringHash.hs
@@ -2,6 +2,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 module Snap.AtlassianConnect.QueryStringHash
     ( createQueryStringHash
+    , generateQSH
     , module Network.HTTP.Types
     ) where
 
@@ -15,12 +16,53 @@
 import           Data.Maybe
 import           Data.Monoid
 import           Data.Ord
-import qualified Data.Text             as T
-import qualified Data.Text.Encoding    as TE
+import qualified Data.Text                  as T
+import qualified Data.Text.Encoding         as TE
 import           Network.HTTP.Types
 import           Network.URI
+import qualified Snap.Helpers               as SH
+import qualified Snap.Core                  as SC
+import qualified Snap.AtlassianConnect.Data as AC
+import           Control.Monad.Trans.Class         (lift)
+import           Control.Monad.Trans.Except
 
+generateQSH :: (SC.MonadSnap m, AC.HasConnect m) => m (Either String T.Text)
+generateQSH = runExceptT $ do
+   connect <- lift $ AC.getConnect
+   request <- lift $ SC.getRequest
+   let connectBaseUrl = AC.connectBaseUrl connect
+   incomingRequestUrl <- ExceptT $ getRequestUri connectBaseUrl
+   let fullUrl = T.pack $ uriToString id incomingRequestUrl ""
+   let rawMethod = SC.rqMethod $ request
+   method <- except . SH.m2e (couldNotConvertMethod ++ (show rawMethod)) . convertMethod $ rawMethod
+   except . SH.m2e qshGenerationFailed $ createQueryStringHash method connectBaseUrl fullUrl
+   where
+      couldNotConvertMethod = "Could not convert the incoming request method: "
+      qshGenerationFailed = "Failed to generate a QSH for the current url"
 
+getRequestUri :: SC.MonadSnap m => URI -> m (Either String URI)
+getRequestUri connectBaseUrl = runExceptT $ do
+   request <- lift $ SC.getRequest
+   let rawRequestUri = B.unpack . SC.rqURI $ request
+   temporaryUri <- except . SH.m2e (couldNotParseUrl ++ rawRequestUri) . parseURI $ "https://example.com" ++ rawRequestUri
+   return $ temporaryUri
+      { uriScheme = uriScheme connectBaseUrl
+      , uriAuthority = uriAuthority connectBaseUrl
+      }
+   where
+      couldNotParseUrl = "Could not parse the current URL that the App is processing: "
+
+convertMethod :: SC.Method -> Maybe StdMethod
+convertMethod SC.GET       = Just GET
+convertMethod SC.HEAD      = Just HEAD
+convertMethod SC.POST      = Just POST
+convertMethod SC.PUT       = Just PUT
+convertMethod SC.DELETE    = Just DELETE
+convertMethod SC.TRACE     = Just TRACE
+convertMethod SC.OPTIONS   = Just OPTIONS
+convertMethod SC.CONNECT   = Just CONNECT
+convertMethod SC.PATCH     = Just PATCH
+convertMethod _            = Nothing
 -- $setup
 -- >>> import Data.Maybe
 -- >>> import Data.Text
diff --git a/src/Snap/Helpers.hs b/src/Snap/Helpers.hs
--- a/src/Snap/Helpers.hs
+++ b/src/Snap/Helpers.hs
@@ -21,6 +21,7 @@
     , respondWithErrors
     -- Write Aeson into a response
     , writeJson
+    , m2e
     ) where
 
 import           Data.Aeson
@@ -68,3 +69,6 @@
   } deriving (Show, Generic)
 
 instance ToJSON ErrorResponse
+
+m2e :: e -> Maybe a -> Either e a
+m2e e = maybe (Left e) Right
