@@ -1,11 +1,20 @@
1+{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE UndecidableInstances #-}
3+{-# LANGUAGE DataKinds #-}
1{-# LANGUAGE DeriveDataTypeable #-}
4{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveGeneric #-}
5{-# LANGUAGE DeriveGeneric #-}
3{-# LANGUAGE FlexibleContexts #-}
6{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
7{-# LANGUAGE FlexibleInstances #-}
8+{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10+{-# LANGUAGE KindSignatures #-}
6{-# LANGUAGE LambdaCase #-}
11{-# LANGUAGE LambdaCase #-}
7{-# LANGUAGE OverloadedStrings #-}
12{-# LANGUAGE OverloadedStrings #-}
13+{-# LANGUAGE PolyKinds #-}
8{-# LANGUAGE RecordWildCards #-}
14{-# LANGUAGE RecordWildCards #-}
15+{-# LANGUAGE ScopedTypeVariables #-}
16+{-# LANGUAGE TypeFamilies #-}
17+{-# LANGUAGE TypeOperators #-}
11-- Module : Network.Google.Auth
20-- Module : Network.Google.Auth
@@ -17,86 +26,86 @@
18-- Explicitly specify your Google credentials, or retrieve them
27-- Explicitly specify your Google credentials, or retrieve them
19-- from the underlying OS.
28-- from the underlying OS.
20−module Network.Google.Auth
29+module Network.Google.Auth where
22− -- * Credentials
31+ -- -- * Credentials
23− Credentials (..)
32+ -- Credentials (..)
25− -- ** Application Default Credentials
34+ -- -- ** Application Default Credentials
26− , getApplicationDefault
35+ -- , getApplicationDefault
27− , fromWellKnownPath
36+ -- , fromWellKnownPath
28− , fromFilePath
37+ -- , fromFilePath
30− -- ** Installed Application Credentials
39+ -- -- ** Installed Application Credentials
31− , formURL
40+ -- , formURL
33− -- ** Authorizing Requests
42+ -- -- ** Authorizing Requests
34− , authorize
43+ -- , authorize
36− -- ** Thread-safe Storage
45+ -- -- ** Thread-safe Storage
37− , Store
46+ -- , Store
38− , initStore
47+ -- , initStore
40− , Auth (..)
49+ -- , Auth (..)
41− , exchange
50+ -- , exchange
42− , refresh
51+ -- , refresh
44− -- ** Default Constants
53+ -- -- ** Default Constants
45− , checkGCEVar
54+ -- , checkGCEVar
46− , cloudSDKConfigDir
55+ -- , cloudSDKConfigDir
47− , defaultCredentialsFile
56+ -- , defaultCredentialsFile
49− -- ** Handling Errors
58+ -- -- ** Handling Errors
50− , AsAuthError (..)
59+ -- , AsAuthError (..)
51− , AuthError (..)
60+ -- , AuthError (..)
53− -- * OAuth Types
62+ -- -- * OAuth Types
54− , OAuthClient (..)
63+ -- , OAuthClient (..)
55− , OAuthToken (..)
64+ -- , OAuthToken (..)
56− , OAuthCode (..)
65+ -- , OAuthCode (..)
57− , OAuthScope (..)
66+ -- , OAuthScope (..)
59− -- * Re-exported Types
68+ -- -- * Re-exported Types
60− , AccessToken (..)
69+ -- , AccessToken (..)
61− , RefreshToken (..)
70+ -- , RefreshToken (..)
62− , Secret (..)
71+ -- , Secret (..)
63− , ServiceId (..)
72+ -- , ServiceId (..)
64− , ClientId (..)
73+ -- , ClientId (..)
65− ) where
74+ -- ) where
67import Control.Applicative
76import Control.Applicative
68import Control.Concurrent
77import Control.Concurrent
69import Control.Exception.Lens
78import Control.Exception.Lens
70−import Control.Lens hiding
79+import Control.Lens hiding (coerce, (.=))
73import Control.Monad
80import Control.Monad
74import Control.Monad.Catch
81import Control.Monad.Catch
75import Control.Monad.IO.Class
82import Control.Monad.IO.Class
76−import Crypto.Hash.Algorithms (SHA256 (..))
83+import Crypto.Hash.Algorithms (SHA256 (..))
77−import Crypto.PubKey.RSA.PKCS15 (signSafer)
84+import Crypto.PubKey.RSA.PKCS15 (signSafer)
78−import Crypto.PubKey.RSA.Types (PrivateKey)
85+import Crypto.PubKey.RSA.Types (PrivateKey)
79import Data.Aeson
86import Data.Aeson
80import Data.Aeson.Types
87import Data.Aeson.Types
81import Data.ByteArray
88import Data.ByteArray
82import Data.ByteArray.Encoding
89import Data.ByteArray.Encoding
83−import Data.ByteString (ByteString)
90+import Data.ByteString (ByteString)
84−import Data.ByteString.Builder (Builder)
91+import Data.ByteString.Builder (Builder)
85−import qualified Data.ByteString.Builder as Build
92+import qualified Data.ByteString.Builder as Build
86−import qualified Data.ByteString.Char8 as BS8
93+import qualified Data.ByteString.Char8 as BS8
87−import qualified Data.ByteString.Lazy as LBS
94+import qualified Data.ByteString.Lazy as LBS
88import Data.Coerce
95import Data.Coerce
89−import Data.Default.Class (def)
96+import Data.Default.Class (def)
90−import Data.List (intersperse)
97+import Data.List
91import Data.String
98import Data.String
92−import qualified Data.Text as Text
99+import qualified Data.Text as Text
93−import qualified Data.Text.Encoding as Text
100+import qualified Data.Text.Encoding as Text
94import Data.Time
101import Data.Time
95import Data.Time.Clock.POSIX
102import Data.Time.Clock.POSIX
96import Data.Typeable
103import Data.Typeable
97import Data.X509
104import Data.X509
98import Data.X509.Memory
105import Data.X509.Memory
99−import Network.Google.Auth.ApplicationDefaultCredentials
106+import GHC.Exts (Constraint)
108+import Network.Google.Auth.ApplicationDefault
100import Network.Google.Auth.Device
109import Network.Google.Auth.Device
101import Network.Google.Auth.InstalledApplication
110import Network.Google.Auth.InstalledApplication
102import Network.Google.Auth.ServiceAccount
111import Network.Google.Auth.ServiceAccount
@@ -104,105 +113,110 @@ import Network.Google.Compute.Metadata
104import Network.Google.Internal.Auth
113import Network.Google.Internal.Auth
105import Network.Google.Internal.Logger
114import Network.Google.Internal.Logger
106import Network.Google.Prelude
115import Network.Google.Prelude
107−import Network.HTTP.Conduit hiding
116+import Network.HTTP.Conduit hiding (Proxy)
109−import qualified Network.HTTP.Conduit as Client
117+import qualified Network.HTTP.Conduit as Client
110import Network.HTTP.Types
118import Network.HTTP.Types
111−import System.Directory (doesFileExist, getHomeDirectory)
119+
112−import System.Environment (lookupEnv)
113−import System.FilePath ((</>))
114−import System.Info (os)
116-- | An 'OAuthToken' that can potentially be expired, with the original
121-- | An 'OAuthToken' that can potentially be expired, with the original
117-- credentials that can be used to perform a refresh.
122-- credentials that can be used to perform a refresh.
118−data Auth = Auth
123+data Auth (s :: [*]) = Auth
119− { _credentials :: !Credentials
124+ { _credentials :: !(Credentials s)
120 , _token :: !OAuthToken
125 , _token :: !OAuthToken
123−-- | Check if the given token is still valid, ie. younger than the projected
128+newtype Store (s :: [*]) = Store { store :: MVar (Auth s) }
125−--
130+-- type family HasScope s a :: Constraint where
126−-- This deliberately makes no external calls due to the absolute construction of
131+-- HasScope s a = IsSubList s (Ss a)
127−-- the '_tokenExpiry' field, unlike the
132+
128−-- <https://developers.google.com/accounts/docs/OAuth2Login#validatingtoken documented>
133+type family And (a :: Constraint) (b :: Constraint) :: Constraint where
129−-- validation method.
134+ And () () = ()
130−validate :: MonadIO m => Auth -> m Bool
131−validate a = (< _tokenExpiry (_token a)) <$> liftIO getCurrentTime
136+type family IsSubList a b :: Constraint where
137+ IsSubList '[] b = ()
138+ IsSubList '[x] (x ': xs) = ()
139+ IsSubList '[x] (y ': ys) = IsSubList '[x] ys
140+ IsSubList (x ': xs) y = IsSubList '[x] y `And` IsSubList xs y
142+-- authorize :: (MonadIO m, MonadCatch m)
133−type Store = MVar Auth
146+-- -> m (Store s)
147+-- authorize = undefined
135-- | Construct storage containing the credentials which have not yet been
149-- | Construct storage containing the credentials which have not yet been
136-- exchanged or refreshed.
150-- exchanged or refreshed.
137initStore :: (MonadIO m, MonadCatch m)
151initStore :: (MonadIO m, MonadCatch m)
138− => Credentials
152+ => Credentials s
142−initStore c l m = exchange c l m >>= liftIO . newMVar
144−-- | Concurrently read the current token, and if expired, then
145−-- safely perform a single serial refresh.
146−getToken :: (MonadIO m, MonadCatch m)
152− x <- liftIO (readMVar s)
155− then pure (_token x)
156− else liftIO . modifyMVar s $ \y -> do
159− then pure (y, _token y)
164−-- | Perform the initial credentials exchange to obtain a valid 'OAuthToken'
165−-- suitable for authorizing requests.
166−exchange :: (MonadIO m, MonadCatch m)
171−exchange c l = fmap (Auth c) . action l
174− FromMetadata s -> metadataToken s
175− FromAccount a ss -> serviceAccountToken a ss
176− FromClient c n -> exchangeCode c n
177− FromUser u -> authorizedUserToken u Nothing
179−-- | Refresh an existing 'OAuthToken' using
180−refresh :: (MonadIO m, MonadCatch m)
185−refresh (Auth c t) l = fmap (Auth c) . action l
188− FromMetadata s -> metadataToken s
189− FromAccount a ss -> serviceAccountToken a ss
190− FromClient x _ -> refreshToken x t
191− FromUser u -> authorizedUserToken u (_tokenRefresh t)
193−-- | Apply the (by way of possible token refresh) a bearer token to the
194−-- authentication header of a request.
195−authorize :: (MonadIO m, MonadCatch m)
198 -> Logger
153 -> Logger
199 -> Manager
154 -> Manager
156+initStore c l m = undefined -- exchange c l m >>= liftIO . newMVar
158+-- -- | Concurrently read the current token, and if expired, then
159+-- -- safely perform a single serial refresh.
160+-- getToken :: (MonadIO m, MonadCatch m)
165+-- getToken s l m = do
166+-- x <- liftIO (readMVar s)
169+-- then pure (_token x)
170+-- else liftIO . modifyMVar s $ \y -> do
173+-- then pure (y, _token y)
175+-- z <- refresh y l m
176+-- pure (z, _token z)
178+-- -- | Perform the initial credentials exchange to obtain a valid 'OAuthToken'
179+-- -- suitable for authorizing requests.
180+-- exchange :: (MonadIO m, MonadCatch m)
185+-- exchange c l = fmap (Auth c) . action l
187+-- action = case c of
188+-- FromMetadata s -> metadataToken s
189+-- FromAccount a ss -> serviceAccountToken a ss
190+-- FromClient c n -> exchangeCode c n
191+-- FromUser u -> authorizedUserToken u Nothing
193+-- -- | Refresh an existing 'OAuthToken' using
194+-- refresh :: (MonadIO m, MonadCatch m)
199+-- refresh (Auth c t) l = fmap (Auth c) . action l
201+-- action = case c of
202+-- FromMetadata s -> metadataToken s
203+-- FromAccount a ss -> serviceAccountToken a ss
204+-- FromClient x _ -> refreshToken x t
205+-- FromUser u -> authorizedUserToken u (_tokenRefresh t)
207+-- -- | Apply the (by way of possible token refresh) a bearer token to the
208+-- -- authentication header of a request.
209+-- authorize :: (MonadIO m, MonadCatch m)
200− -> m Client.Request
210+-- => Client.Request
214+-- -> m Client.Request
201−authorize rq s l m = bearer <$> getToken s l m
215+-- authorize rq s l m = bearer <$> getToken s l m
203− bearer t = rq
217+-- bearer t = rq
204− { Client.requestHeaders =
218+-- { Client.requestHeaders =
205− ( hAuthorization
219+-- ( hAuthorization
206− , "Bearer " <> Text.encodeUtf8 (toText (_tokenAccess t))
220+-- , "Bearer " <> Text.encodeUtf8 (toText (_tokenAccess t))
207− ) : Client.requestHeaders rq
221+-- ) : Client.requestHeaders rq