atlassian-connect-core 0.9.0.0 → 0.9.0.1
raw patch · 3 files changed
+31/−17 lines, 3 filesdep ~jwt
Dependency ranges changed: jwt
Files
- atlassian-connect-core.cabal +3/−3
- src/Snap/AtlassianConnect/HostRequest.hs +10/−2
- src/Snap/AtlassianConnect/OAuth.hs +18/−12
atlassian-connect-core.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.34.2.+-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack name: atlassian-connect-core-version: 0.9.0.0+version: 0.9.0.1 synopsis: Atlassian Connect snaplet for the Snap Framework and helper code. description: This library allows you to quickly get an Atlassian Connect application running on top of the Snap Framework. It provides best practices and helper functions to get you moving@@ -76,7 +76,7 @@ , http-client-tls >=0.2 , http-media ==0.8.* , http-types >=0.8- , jwt >=0.6 && <0.8+ , jwt ==0.10.* , mtl ==2.* , network-api-support >=0.2 , snap >=0.14
src/Snap/AtlassianConnect/HostRequest.hs view
@@ -153,7 +153,15 @@ generateJWTToken :: CD.PluginKey -> P.POSIXTime -> T.Text -> StdMethod -> URI -> T.Text -> Maybe T.Text generateJWTToken pluginKey' fromTime sharedSecret' method' ourURL requestURL = do queryStringHash <- QSH.createQueryStringHash method' ourURL requestURL- return $ JWT.encodeSigned JWT.HS256 (JWT.secret sharedSecret') (createClaims pluginKey' fromTime queryStringHash)+ return $ JWT.encodeSigned signer header (createClaims pluginKey' fromTime queryStringHash)+ where+ signer = JWT.hmacSecret sharedSecret'+ header = JWT.JOSEHeader+ { JWT.alg = Just JWT.HS256+ , JWT.kid = Nothing+ , JWT.typ = Nothing+ , JWT.cty = Nothing+ } createClaims :: CD.PluginKey -> P.POSIXTime -> T.Text -> JWT.JWTClaimsSet createClaims (CD.PluginKey pluginKey) fromTime queryStringHash = JWT.JWTClaimsSet@@ -164,7 +172,7 @@ , JWT.aud = Nothing , JWT.nbf = Nothing , JWT.jti = Nothing- , JWT.unregisteredClaims = M.fromList [("qsh", String queryStringHash)] + , JWT.unregisteredClaims = JWT.ClaimsMap $ M.fromList [("qsh", String queryStringHash)] } where expiryTime :: P.POSIXTime
src/Snap/AtlassianConnect/OAuth.hs view
@@ -9,7 +9,7 @@ Stability : experimental By default, all HTTP requests that your add-on makes to an Atlassian application (like JIRA or Confluence) will-be performed as your add-on user. For example, if your add-on service makes a HTTP request to comment on a JIRA +be performed as your add-on user. For example, if your add-on service makes a HTTP request to comment on a JIRA issue then the comment will be made as your add-on. However, if your addon requests the "ACT_AS_USER" scope then is is capable of using the OAuth service to generate an "access token" for a particular user on a tenant. This access token can be used to make make HTTP requests from your add-on service to an Atlassian product as a user@@ -20,7 +20,7 @@ You can read more about access token on the <https://developer.atlassian.com/cloud/jira/platform/oauth-2-jwt-bearer-token-authorization-grant-type/ official documentation>. -}-module Snap.AtlassianConnect.OAuth +module Snap.AtlassianConnect.OAuth ( requestAccessToken , AC.AccessTokenResponse(..) , AC.AccessToken@@ -50,15 +50,15 @@ import qualified Snap.AtlassianConnect.Tenant as AC import qualified Web.JWT as JWT --- | Request an access token for a tenant and user with the requested scopes. --- +-- | Request an access token for a tenant and user with the requested scopes.+-- -- This token will allow you to post subsequent HTTP requests using the Snap.AtlassianConnect.HostRequest module -- as an impersonated user. ----- The access token that is returned should be reused as much as possible in order to avoid hitting rate limits +-- The access token that is returned should be reused as much as possible in order to avoid hitting rate limits -- from the token generation service. Each token is specific to the tenant, user and scopes that -- it was created for. This means that the token reuse must be tenant, user and scopes specific.-requestAccessToken +requestAccessToken :: AC.Tenant -- ^ The tenant to generate the Access Token for. -> UserKey -- ^ The user key of the user on the tenant that should be impersonated. -> Maybe [D.ProductScope] -- ^ The collection of scopes that will be used for impersonation. Providing none requests all scopes that the add-on provides.@@ -79,7 +79,7 @@ url = authBaseUrl `T.append` "/oauth2/token" formParams :: T.Text -> [(BSC.ByteString, BSC.ByteString)]- formParams assertion = + formParams assertion = [ ("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer") , ("assertion", T.encodeUtf8 assertion) ] ++ scopeParam@@ -88,7 +88,7 @@ Nothing -> [] Just scopes -> (: []) . (,) "scope" . BSC.intercalate " " . fmap printScope . filter ((/=) D.ActAsUser) $ scopes -printScope :: D.ProductScope -> BSC.ByteString +printScope :: D.ProductScope -> BSC.ByteString printScope D.Read = "READ" printScope D.Write = "WRITE" printScope D.Delete = "DELETE"@@ -102,9 +102,15 @@ currentTime <- P.getPOSIXTime case generateAssertionClaims currentTime tenant userKey of Nothing -> return Nothing- Just claims -> return . Just $ JWT.encodeSigned JWT.HS256 jwtSecret claims+ Just claims -> return . Just $ JWT.encodeSigned signer header claims where- jwtSecret = JWT.secret . AC.sharedSecret $ tenant+ signer = JWT.hmacSecret . AC.sharedSecret $ tenant+ header = JWT.JOSEHeader+ { JWT.alg = Just JWT.HS256+ , JWT.kid = Nothing+ , JWT.typ = Nothing+ , JWT.cty = Nothing+ } -- These claims are documented here: https://developer.atlassian.com/cloud/jira/platform/oauth-2-jwt-bearer-token-authorization-grant-type/ {-@@ -126,7 +132,7 @@ , JWT.exp = JWT.numericDate expiryTime , JWT.nbf = Nothing , JWT.jti = Nothing- , JWT.unregisteredClaims = M.fromList [("tnt", String . T.pack $ tenantBaseUrlString)]+ , JWT.unregisteredClaims = JWT.ClaimsMap $ M.fromList [("tnt", String . T.pack $ tenantBaseUrlString)] } where tenantBaseUrlString = show . AC.getURI . AC.baseUrl $ tenant@@ -138,5 +144,5 @@ expiryPeriod :: Minute expiryPeriod = 1 -authBaseUrl :: T.Text +authBaseUrl :: T.Text authBaseUrl = "https://auth.atlassian.io"