Skip to content

Commit 42fa6cf

Browse files
committed
Remove error calls from OIDC Auth
1 parent 547b5af commit 42fa6cf

File tree

1 file changed

+29
-19
lines changed
  • kubernetes-client/src/Kubernetes/Client/Auth

1 file changed

+29
-19
lines changed

kubernetes-client/src/Kubernetes/Client/Auth/OIDC.hs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ where
77

88
import Control.Applicative
99
import Control.Concurrent.STM
10+
import Control.Exception.Safe (Exception, throwM)
1011
import Data.Either.Combinators
1112
import Data.Function ((&))
1213
import Data.Map (Map)
@@ -19,18 +20,19 @@ import Kubernetes.Client.KubeConfig
1920
import Kubernetes.OpenAPI.Core
2021
import Network.HTTP.Client
2122
import Network.HTTP.Client.TLS
22-
import Network.OAuth.OAuth2 as OAuth hiding (error)
23+
import Network.OAuth.OAuth2 as OAuth
2324
import Network.TLS as TLS
2425
import URI.ByteString
2526
import Web.JWT as JWT
2627
import Web.OIDC.Client.Discovery as OIDC
2728

28-
import qualified Data.ByteString as BS
29-
import qualified Data.ByteString.Base64 as B64
30-
import qualified Data.Map as Map
31-
import qualified Data.Text as Text
32-
import qualified Data.Text.Encoding as Text
33-
import qualified Lens.Micro as L
29+
import qualified Data.ByteString as BS
30+
import qualified Data.ByteString.Base64 as B64
31+
import qualified Data.Map as Map
32+
import qualified Data.Text as Text
33+
import qualified Data.Text.Encoding as Text
34+
import qualified Lens.Micro as L
35+
import qualified Network.OAuth.OAuth2.TokenRequest as OAuth2TokenRequest
3436

3537
data OIDCAuth = OIDCAuth { issuerURL :: Text
3638
, clientID :: Text
@@ -50,6 +52,16 @@ instance AuthMethod OIDCAuth where
5052
$ setHeader req [("Authorization", "Bearer " <> (Text.encodeUtf8 token))]
5153
& L.set rAuthTypesL []
5254

55+
data OIDCGetTokenException = OIDCOAuthException (OAuth2Error OAuth2TokenRequest.Errors)
56+
| OIDCURIException URIParseError
57+
| OIDCGetTokenException String
58+
deriving Show
59+
instance Exception OIDCGetTokenException
60+
61+
data OIDCAuthParsingException = OIDCAuthParsingException String
62+
deriving Show
63+
instance Exception OIDCAuthParsingException
64+
5365
-- TODO: Consider a token expired few seconds before actual expiry to account for time skew
5466
getToken :: OIDCAuth -> IO Text
5567
getToken o@(OIDCAuth{..}) = do
@@ -64,26 +76,27 @@ getToken o@(OIDCAuth{..}) = do
6476
isValidToken = fromMaybe False (fmap (now <) maybeExp)
6577
if not isValidToken
6678
then fetchToken mgr o
67-
else return $ fromMaybe (error "impossible") idToken
79+
else maybe (throwM $ OIDCGetTokenException "impossible") pure idToken
6880

6981
fetchToken :: Manager -> OIDCAuth -> IO Text
7082
fetchToken mgr o@(OIDCAuth{..}) = do
7183
maybeToken <- readTVarIO refreshTokenTVar
7284
case maybeToken of
73-
Nothing -> error "cannot refresh id-token without a refresh token"
85+
Nothing -> throwM $ OIDCGetTokenException "cannot refresh id-token without a refresh token"
7486
Just token -> do
7587
tokenEndpoint <- fetchTokenEndpoint mgr o
76-
tokenURI <- exceptEither $ parseURI strictURIParserOptions (Text.encodeUtf8 tokenEndpoint)
88+
tokenURI <- parseURI strictURIParserOptions (Text.encodeUtf8 tokenEndpoint)
89+
& either (throwM . OIDCURIException) pure
7790
let oauth = OAuth2{ oauthClientId = clientID
7891
, oauthClientSecret = clientSecret
7992
, oauthAccessTokenEndpoint = tokenURI
8093
, oauthOAuthorizeEndpoint = tokenURI
8194
, oauthCallback = Nothing
8295
}
8396
oauthToken <- refreshAccessToken mgr oauth (RefreshToken token)
84-
>>= exceptEither
97+
>>= either (throwM . OIDCOAuthException) pure
8598
case OAuth.idToken oauthToken of
86-
Nothing -> error "token response did not contain an id_token, either the scope \"openid\" wasn't requested upon login, or the provider doesn't support id_tokens as part of the refresh response."
99+
Nothing -> throwM $ OIDCGetTokenException "token response did not contain an id_token, either the scope \"openid\" wasn't requested upon login, or the provider doesn't support id_tokens as part of the refresh response."
87100
Just (IdToken t) -> do
88101
_ <- atomically $ writeTVar idTokenTVar (Just t)
89102
return t
@@ -94,10 +107,6 @@ fetchTokenEndpoint mgr OIDCAuth{..} = do
94107
& (fmap configuration)
95108
& (fmap tokenEndpoint)
96109

97-
exceptEither :: Show b => Either b a -> IO a
98-
exceptEither (Right a) = pure a
99-
exceptEither (Left t) = error (show t)
100-
101110
{-
102111
Detects if auth-provier name is oidc, if it is configures the 'KubernetesClientConfig' with OIDCAuth 'AuthMethod'.
103112
Does not use cache, consider using 'cachedOIDCAuth'.
@@ -106,7 +115,7 @@ oidcAuth :: DetectAuth
106115
oidcAuth AuthInfo{authProvider = Just(AuthProviderConfig "oidc" (Just cfg))} (tls, kubecfg)
107116
= Just
108117
$ parseOIDCAuthInfo cfg
109-
>>= either error (\oidc -> pure (tls, addAuthMethod kubecfg oidc))
118+
>>= either (throwM . OIDCAuthParsingException) (\oidc -> pure (tls, addAuthMethod kubecfg oidc))
110119
oidcAuth _ _ = Nothing
111120

112121
-- TODO: Consider doing this whole function atomically, as two threads may miss the cache simultaneously
@@ -118,10 +127,11 @@ cachedOIDCAuth :: OIDCCache -> DetectAuth
118127
cachedOIDCAuth cache AuthInfo{authProvider = Just(AuthProviderConfig "oidc" (Just cfg))} (tls, kubecfg) = Just $ do
119128
m <- readTVarIO cache
120129
o <- case findInCache m cfg of
121-
Left e -> error e
130+
Left e -> throwM $ OIDCAuthParsingException e
122131
Right (Just o) -> return o
123132
Right Nothing -> do
124-
o@(OIDCAuth{..}) <- either error pure =<< parseOIDCAuthInfo cfg
133+
o@(OIDCAuth{..}) <- parseOIDCAuthInfo cfg
134+
>>= either (throwM . OIDCAuthParsingException) pure
125135
let newCache = Map.insert (issuerURL, clientID) o m
126136
_ <- atomically $ swapTVar cache newCache
127137
return o

0 commit comments

Comments
 (0)