packages feed

hoauth2 2.6.0 → 2.7.0

raw patch · 11 files changed

+450/−323 lines, 11 filesdep +hoauth2dep +hspecPVP ok

version bump matches the API change (PVP)

Dependencies added: hoauth2, hspec

API changes (from Hackage documentation)

- Network.OAuth.OAuth2: accessTokenUrl :: OAuth2 -> ExchangeToken -> (URI, PostBody)
- Network.OAuth.OAuth2: addDefaultRequestHeaders :: Request -> Request
- Network.OAuth.OAuth2: clientSecretPost :: OAuth2 -> PostBody
- Network.OAuth.OAuth2: doJSONPostRequest :: (MonadIO m, FromJSON err, FromJSON a) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m a
- Network.OAuth.OAuth2: doSimplePostRequest :: (MonadIO m, FromJSON err) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m ByteString
- Network.OAuth.OAuth2: fetchAccessToken :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: fetchAccessToken2 :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: fetchAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: fetchAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: handleOAuth2TokenResponse :: FromJSON err => Response ByteString -> Either (OAuth2Error err) ByteString
- Network.OAuth.OAuth2: parseResponseFlexible :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a
- Network.OAuth.OAuth2: parseResponseString :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a
- Network.OAuth.OAuth2: refreshAccessToken :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: refreshAccessToken2 :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: refreshAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2: refreshAccessTokenUrl :: OAuth2 -> RefreshToken -> (URI, PostBody)
- Network.OAuth.OAuth2: refreshAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth.OAuth2.AuthorizationRequest: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.AuthorizationRequest.Errors
- Network.OAuth.OAuth2.Internal: AccessToken :: Text -> AccessToken
- Network.OAuth.OAuth2.Internal: ClientSecretBasic :: ClientAuthenticationMethod
- Network.OAuth.OAuth2.Internal: ClientSecretPost :: ClientAuthenticationMethod
- Network.OAuth.OAuth2.Internal: ExchangeToken :: Text -> ExchangeToken
- Network.OAuth.OAuth2.Internal: IdToken :: Text -> IdToken
- Network.OAuth.OAuth2.Internal: OAuth2 :: Text -> Text -> URIRef Absolute -> URIRef Absolute -> URIRef Absolute -> OAuth2
- Network.OAuth.OAuth2.Internal: OAuth2Error :: Either Text a -> Maybe Text -> Maybe (URIRef Absolute) -> OAuth2Error a
- Network.OAuth.OAuth2.Internal: OAuth2Token :: AccessToken -> Maybe RefreshToken -> Maybe Int -> Maybe Text -> Maybe IdToken -> OAuth2Token
- Network.OAuth.OAuth2.Internal: RefreshToken :: Text -> RefreshToken
- Network.OAuth.OAuth2.Internal: [accessToken] :: OAuth2Token -> AccessToken
- Network.OAuth.OAuth2.Internal: [atoken] :: AccessToken -> Text
- Network.OAuth.OAuth2.Internal: [errorDescription] :: OAuth2Error a -> Maybe Text
- Network.OAuth.OAuth2.Internal: [errorUri] :: OAuth2Error a -> Maybe (URIRef Absolute)
- Network.OAuth.OAuth2.Internal: [error] :: OAuth2Error a -> Either Text a
- Network.OAuth.OAuth2.Internal: [expiresIn] :: OAuth2Token -> Maybe Int
- Network.OAuth.OAuth2.Internal: [extoken] :: ExchangeToken -> Text
- Network.OAuth.OAuth2.Internal: [idToken] :: OAuth2Token -> Maybe IdToken
- Network.OAuth.OAuth2.Internal: [idtoken] :: IdToken -> Text
- Network.OAuth.OAuth2.Internal: [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute
- Network.OAuth.OAuth2.Internal: [oauth2ClientId] :: OAuth2 -> Text
- Network.OAuth.OAuth2.Internal: [oauth2ClientSecret] :: OAuth2 -> Text
- Network.OAuth.OAuth2.Internal: [oauth2RedirectUri] :: OAuth2 -> URIRef Absolute
- Network.OAuth.OAuth2.Internal: [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute
- Network.OAuth.OAuth2.Internal: [refreshToken] :: OAuth2Token -> Maybe RefreshToken
- Network.OAuth.OAuth2.Internal: [rtoken] :: RefreshToken -> Text
- Network.OAuth.OAuth2.Internal: [tokenType] :: OAuth2Token -> Maybe Text
- Network.OAuth.OAuth2.Internal: appendQueryParams :: [(ByteString, ByteString)] -> URIRef a -> URIRef a
- Network.OAuth.OAuth2.Internal: data ClientAuthenticationMethod
- Network.OAuth.OAuth2.Internal: data OAuth2
- Network.OAuth.OAuth2.Internal: data OAuth2Error a
- Network.OAuth.OAuth2.Internal: data OAuth2Token
- Network.OAuth.OAuth2.Internal: defaultRequestHeaders :: [(HeaderName, ByteString)]
- Network.OAuth.OAuth2.Internal: hostLens :: Lens' Request ByteString
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.AccessToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.ExchangeToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.IdToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.FromJSON.FromJSON err => Data.Aeson.Types.FromJSON.FromJSON (Network.OAuth.OAuth2.Internal.OAuth2Error err)
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.AccessToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.ExchangeToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.IdToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth.OAuth2.Internal: instance Data.Aeson.Types.ToJSON.ToJSON err => Data.Aeson.Types.ToJSON.ToJSON (Network.OAuth.OAuth2.Internal.OAuth2Error err)
- Network.OAuth.OAuth2.Internal: instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.AccessToken
- Network.OAuth.OAuth2.Internal: instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.IdToken
- Network.OAuth.OAuth2.Internal: instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth.OAuth2.Internal: instance Data.Default.Class.Default Network.OAuth.OAuth2.Internal.OAuth2
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.AccessToken
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.ClientAuthenticationMethod
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.IdToken
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.OAuth2
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Eq a => GHC.Classes.Eq (Network.OAuth.OAuth2.Internal.OAuth2Error a)
- Network.OAuth.OAuth2.Internal: instance GHC.Classes.Ord Network.OAuth.OAuth2.Internal.ClientAuthenticationMethod
- Network.OAuth.OAuth2.Internal: instance GHC.Generics.Generic (Network.OAuth.OAuth2.Internal.OAuth2Error a)
- Network.OAuth.OAuth2.Internal: instance GHC.Generics.Generic Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.AccessToken
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.ExchangeToken
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.IdToken
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.OAuth2
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.OAuth2Token
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth.OAuth2.Internal: instance GHC.Show.Show a => GHC.Show.Show (Network.OAuth.OAuth2.Internal.OAuth2Error a)
- Network.OAuth.OAuth2.Internal: mkDecodeOAuth2Error :: ByteString -> String -> OAuth2Error err
- Network.OAuth.OAuth2.Internal: newtype AccessToken
- Network.OAuth.OAuth2.Internal: newtype ExchangeToken
- Network.OAuth.OAuth2.Internal: newtype IdToken
- Network.OAuth.OAuth2.Internal: newtype RefreshToken
- Network.OAuth.OAuth2.Internal: parseOAuth2Error :: FromJSON err => ByteString -> OAuth2Error err
- Network.OAuth.OAuth2.Internal: portLens :: Lens' Request Int
- Network.OAuth.OAuth2.Internal: requestToUri :: Request -> URI
- Network.OAuth.OAuth2.Internal: type PostBody = [(ByteString, ByteString)]
- Network.OAuth.OAuth2.Internal: type QueryParams = [(ByteString, ByteString)]
- Network.OAuth.OAuth2.Internal: uriToRequest :: MonadThrow m => URI -> m Request
- Network.OAuth.OAuth2.TokenRequest: data Errors
- Network.OAuth.OAuth2.TokenRequest: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.TokenRequest.Errors
- Network.OAuth.OAuth2.TokenRequest: instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.TokenRequest.Errors
- Network.OAuth.OAuth2.TokenRequest: instance GHC.Classes.Eq Network.OAuth.OAuth2.TokenRequest.Errors
- Network.OAuth.OAuth2.TokenRequest: instance GHC.Generics.Generic Network.OAuth.OAuth2.TokenRequest.Errors
- Network.OAuth.OAuth2.TokenRequest: instance GHC.Show.Show Network.OAuth.OAuth2.TokenRequest.Errors
- Network.OAuth2.Experiment.Pkce: CodeChallenge :: Text -> CodeChallenge
- Network.OAuth2.Experiment.Pkce: CodeVerifier :: Text -> CodeVerifier
- Network.OAuth2.Experiment.Pkce: PkceRequestParam :: CodeVerifier -> CodeChallenge -> CodeChallengeMethod -> PkceRequestParam
- Network.OAuth2.Experiment.Pkce: S256 :: CodeChallengeMethod
- Network.OAuth2.Experiment.Pkce: [codeChallengeMethod] :: PkceRequestParam -> CodeChallengeMethod
- Network.OAuth2.Experiment.Pkce: [codeChallenge] :: PkceRequestParam -> CodeChallenge
- Network.OAuth2.Experiment.Pkce: [codeVerifier] :: PkceRequestParam -> CodeVerifier
- Network.OAuth2.Experiment.Pkce: [unCodeChallenge] :: CodeChallenge -> Text
- Network.OAuth2.Experiment.Pkce: [unCodeVerifier] :: CodeVerifier -> Text
- Network.OAuth2.Experiment.Pkce: data CodeChallengeMethod
- Network.OAuth2.Experiment.Pkce: data PkceRequestParam
- Network.OAuth2.Experiment.Pkce: instance GHC.Show.Show Network.OAuth2.Experiment.Pkce.CodeChallengeMethod
- Network.OAuth2.Experiment.Pkce: instance GHC.Show.Show Network.OAuth2.Experiment.Pkce.CodeVerifier
- Network.OAuth2.Experiment.Pkce: mkPkceParam :: MonadIO m => m PkceRequestParam
- Network.OAuth2.Experiment.Pkce: newtype CodeChallenge
- Network.OAuth2.Experiment.Pkce: newtype CodeVerifier
- Network.OAuth2.Experiment.Types: -- WithExchangeToken a b = b' implies no exchange token v.s. 'type
- Network.OAuth2.Experiment.Types: -- client credentials) will use <a>ExchangeToken</a> in the token request
- Network.OAuth2.Experiment.Types: -- create type family to be explicit on it. with 'type instance
- Network.OAuth2.Experiment.Types: -- endpoint.
- Network.OAuth2.Experiment.Types: -- instance WithExchangeToken a b = ExchangeToken -&gt; b' implies
- Network.OAuth2.Experiment.Types: -- needing an exchange token
- Network.OAuth2.Experiment.Types: -- | <a>https://www.rfc-editor.org/rfc/rfc6749#page-47</a>
- Network.OAuth2.Experiment.Types: AuthorizationCode :: GrantTypeFlow
- Network.OAuth2.Experiment.Types: AuthorizeState :: Text -> AuthorizeState
- Network.OAuth2.Experiment.Types: ClientCredentials :: GrantTypeFlow
- Network.OAuth2.Experiment.Types: ClientId :: Text -> ClientId
- Network.OAuth2.Experiment.Types: ClientSecret :: Text -> ClientSecret
- Network.OAuth2.Experiment.Types: GTAuthorizationCode :: GrantTypeValue
- Network.OAuth2.Experiment.Types: GTClientCredentials :: GrantTypeValue
- Network.OAuth2.Experiment.Types: GTPassword :: GrantTypeValue
- Network.OAuth2.Experiment.Types: GTRefreshToken :: GrantTypeValue
- Network.OAuth2.Experiment.Types: Idp :: URI -> URI -> URI -> (forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a)) -> Idp a
- Network.OAuth2.Experiment.Types: Password :: Text -> Password
- Network.OAuth2.Experiment.Types: RedirectUri :: URI -> RedirectUri
- Network.OAuth2.Experiment.Types: ResourceOwnerPassword :: GrantTypeFlow
- Network.OAuth2.Experiment.Types: Scope :: Text -> Scope
- Network.OAuth2.Experiment.Types: Username :: Text -> Username
- Network.OAuth2.Experiment.Types: [$sel:idpAuthorizeEndpoint:Idp] :: Idp a -> URI
- Network.OAuth2.Experiment.Types: [$sel:idpFetchUserInfo:Idp] :: Idp a -> forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a)
- Network.OAuth2.Experiment.Types: [$sel:idpTokenEndpoint:Idp] :: Idp a -> URI
- Network.OAuth2.Experiment.Types: [$sel:idpUserInfoEndpoint:Idp] :: Idp a -> URI
- Network.OAuth2.Experiment.Types: [$sel:unAuthorizeState:AuthorizeState] :: AuthorizeState -> Text
- Network.OAuth2.Experiment.Types: [$sel:unClientId:ClientId] :: ClientId -> Text
- Network.OAuth2.Experiment.Types: [$sel:unClientSecret:ClientSecret] :: ClientSecret -> Text
- Network.OAuth2.Experiment.Types: [$sel:unPassword:Password] :: Password -> Text
- Network.OAuth2.Experiment.Types: [$sel:unRedirectUri:RedirectUri] :: RedirectUri -> URI
- Network.OAuth2.Experiment.Types: [$sel:unScope:Scope] :: Scope -> Text
- Network.OAuth2.Experiment.Types: [$sel:unUsername:Username] :: Username -> Text
- Network.OAuth2.Experiment.Types: class HasAuthorizeRequest (a :: GrantTypeFlow) where {
- Network.OAuth2.Experiment.Types: class HasIdpAppName (a :: GrantTypeFlow)
- Network.OAuth2.Experiment.Types: class HasPkceAuthorizeRequest (a :: GrantTypeFlow)
- Network.OAuth2.Experiment.Types: class HasPkceTokenRequest (b :: GrantTypeFlow)
- Network.OAuth2.Experiment.Types: class HasRefreshTokenRequest (a :: GrantTypeFlow) where {
- Network.OAuth2.Experiment.Types: class HasTokenRequest (a :: GrantTypeFlow) where {
- Network.OAuth2.Experiment.Types: class HasUserInfoRequest (a :: GrantTypeFlow)
- Network.OAuth2.Experiment.Types: class ToQueryParam a
- Network.OAuth2.Experiment.Types: class ToResponseTypeValue (a :: GrantTypeFlow)
- Network.OAuth2.Experiment.Types: conduitPkceTokenRequest :: (HasPkceTokenRequest b, MonadIO m) => IdpApplication b i -> Manager -> (ExchangeToken, CodeVerifier) -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth2.Experiment.Types: conduitRefreshTokenRequest :: (HasRefreshTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
- Network.OAuth2.Experiment.Types: conduitTokenRequest :: (HasTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> WithExchangeToken a (ExceptT (OAuth2Error Errors) m OAuth2Token)
- Network.OAuth2.Experiment.Types: conduitUserInfoRequest :: (HasUserInfoRequest a, FromJSON (IdpUserInfo i)) => IdpApplication a i -> Manager -> AccessToken -> ExceptT ByteString IO (IdpUserInfo i)
- Network.OAuth2.Experiment.Types: data AuthorizationRequest a;
- Network.OAuth2.Experiment.Types: data GrantTypeFlow
- Network.OAuth2.Experiment.Types: data GrantTypeValue
- Network.OAuth2.Experiment.Types: data Idp a
- Network.OAuth2.Experiment.Types: data RefreshTokenRequest a;
- Network.OAuth2.Experiment.Types: data TokenRequest a;
- Network.OAuth2.Experiment.Types: data family IdpApplication (a :: GrantTypeFlow) (i :: Type)
- Network.OAuth2.Experiment.Types: getIdpAppName :: HasIdpAppName a => IdpApplication a i -> Text
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.AuthorizeState
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.ClientId
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.ClientSecret
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.Password
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.Scope
- Network.OAuth2.Experiment.Types: instance Data.String.IsString Network.OAuth2.Experiment.Types.Username
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.AuthorizeState
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.ClientId
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.ClientSecret
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.GrantTypeValue
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Password
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.RedirectUri
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Scope
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Username
- Network.OAuth2.Experiment.Types: instance GHC.Classes.Ord Network.OAuth2.Experiment.Types.Scope
- Network.OAuth2.Experiment.Types: instance GHC.Show.Show Network.OAuth2.Experiment.Types.ClientId
- Network.OAuth2.Experiment.Types: instance GHC.Show.Show Network.OAuth2.Experiment.Types.GrantTypeValue
- Network.OAuth2.Experiment.Types: instance GHC.Show.Show Network.OAuth2.Experiment.Types.Scope
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasAuthorizeRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.ClientCredentials
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasPkceAuthorizeRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasPkceTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasRefreshTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasRefreshTokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.ClientCredentials
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasUserInfoRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.HasUserInfoRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Data.Set.Internal.Set Network.OAuth2.Experiment.Types.Scope)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.AuthorizationRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.RefreshTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.ClientCredentials)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth.OAuth2.Internal.ExchangeToken
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth.OAuth2.Internal.RefreshToken
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeChallenge
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeChallengeMethod
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeVerifier
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.AuthorizeState
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.ClientId
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.ClientSecret
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.GrantTypeValue
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.Password
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.RedirectUri
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.Username
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToQueryParam a => Network.OAuth2.Experiment.Types.ToQueryParam (GHC.Maybe.Maybe a)
- Network.OAuth2.Experiment.Types: instance Network.OAuth2.Experiment.Types.ToResponseTypeValue 'Network.OAuth2.Experiment.Types.AuthorizationCode
- Network.OAuth2.Experiment.Types: mkAuthorizeRequest :: HasAuthorizeRequest a => IdpApplication a i -> MkAuthorizationRequestResponse a
- Network.OAuth2.Experiment.Types: mkAuthorizeRequestParameter :: HasAuthorizeRequest a => IdpApplication a i -> AuthorizationRequest a
- Network.OAuth2.Experiment.Types: mkPkceAuthorizeRequest :: (HasPkceAuthorizeRequest a, MonadIO m) => IdpApplication a i -> m (Text, CodeVerifier)
- Network.OAuth2.Experiment.Types: mkRefreshTokenRequest :: HasRefreshTokenRequest a => IdpApplication a i -> RefreshToken -> RefreshTokenRequest a
- Network.OAuth2.Experiment.Types: mkTokenRequest :: HasTokenRequest a => IdpApplication a i -> WithExchangeToken a (TokenRequest a)
- Network.OAuth2.Experiment.Types: newtype AuthorizeState
- Network.OAuth2.Experiment.Types: newtype ClientId
- Network.OAuth2.Experiment.Types: newtype ClientSecret
- Network.OAuth2.Experiment.Types: newtype Password
- Network.OAuth2.Experiment.Types: newtype RedirectUri
- Network.OAuth2.Experiment.Types: newtype Scope
- Network.OAuth2.Experiment.Types: newtype Username
- Network.OAuth2.Experiment.Types: toOAuth2Key :: ClientId -> ClientSecret -> OAuth2
- Network.OAuth2.Experiment.Types: toQueryParam :: ToQueryParam a => a -> Map Text Text
- Network.OAuth2.Experiment.Types: toResponseTypeParam :: forall a b req. (ToResponseTypeValue a, IsString b) => req a -> Map b b
- Network.OAuth2.Experiment.Types: toResponseTypeValue :: (ToResponseTypeValue a, IsString b) => b
- Network.OAuth2.Experiment.Types: type MkAuthorizationRequestResponse a;
- Network.OAuth2.Experiment.Types: type WithExchangeToken a b;
- Network.OAuth2.Experiment.Types: type family IdpUserInfo a
- Network.OAuth2.Experiment.Types: }
- Network.OAuth2.Experiment.Utils: bs8ToLazyText :: ByteString -> Text
- Network.OAuth2.Experiment.Utils: mapsToParams :: [Map Text Text] -> [(ByteString, ByteString)]
- Network.OAuth2.Experiment.Utils: tlToBS :: Text -> ByteString
+ Network.OAuth.OAuth2: AccessToken :: Text -> AccessToken
+ Network.OAuth.OAuth2: ClientAssertionJwt :: ClientAuthenticationMethod
+ Network.OAuth.OAuth2: ClientSecretBasic :: ClientAuthenticationMethod
+ Network.OAuth.OAuth2: ClientSecretPost :: ClientAuthenticationMethod
+ Network.OAuth.OAuth2: ExchangeToken :: Text -> ExchangeToken
+ Network.OAuth.OAuth2: IdToken :: Text -> IdToken
+ Network.OAuth.OAuth2: OAuth2 :: Text -> Text -> URIRef Absolute -> URIRef Absolute -> URIRef Absolute -> OAuth2
+ Network.OAuth.OAuth2: OAuth2Token :: AccessToken -> Maybe RefreshToken -> Maybe Int -> Maybe Text -> Maybe IdToken -> OAuth2Token
+ Network.OAuth.OAuth2: RefreshToken :: Text -> RefreshToken
+ Network.OAuth.OAuth2: [accessToken] :: OAuth2Token -> AccessToken
+ Network.OAuth.OAuth2: [atoken] :: AccessToken -> Text
+ Network.OAuth.OAuth2: [expiresIn] :: OAuth2Token -> Maybe Int
+ Network.OAuth.OAuth2: [extoken] :: ExchangeToken -> Text
+ Network.OAuth.OAuth2: [idToken] :: OAuth2Token -> Maybe IdToken
+ Network.OAuth.OAuth2: [idtoken] :: IdToken -> Text
+ Network.OAuth.OAuth2: [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute
+ Network.OAuth.OAuth2: [oauth2ClientId] :: OAuth2 -> Text
+ Network.OAuth.OAuth2: [oauth2ClientSecret] :: OAuth2 -> Text
+ Network.OAuth.OAuth2: [oauth2RedirectUri] :: OAuth2 -> URIRef Absolute
+ Network.OAuth.OAuth2: [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute
+ Network.OAuth.OAuth2: [refreshToken] :: OAuth2Token -> Maybe RefreshToken
+ Network.OAuth.OAuth2: [rtoken] :: RefreshToken -> Text
+ Network.OAuth.OAuth2: [tokenType] :: OAuth2Token -> Maybe Text
+ Network.OAuth.OAuth2: appendQueryParams :: [(ByteString, ByteString)] -> URIRef a -> URIRef a
+ Network.OAuth.OAuth2: data ClientAuthenticationMethod
+ Network.OAuth.OAuth2: data OAuth2
+ Network.OAuth.OAuth2: data OAuth2Token
+ Network.OAuth.OAuth2: defaultRequestHeaders :: [(HeaderName, ByteString)]
+ Network.OAuth.OAuth2: hostLens :: Lens' Request ByteString
+ Network.OAuth.OAuth2: newtype AccessToken
+ Network.OAuth.OAuth2: newtype ExchangeToken
+ Network.OAuth.OAuth2: newtype IdToken
+ Network.OAuth.OAuth2: newtype RefreshToken
+ Network.OAuth.OAuth2: portLens :: Lens' Request Int
+ Network.OAuth.OAuth2: requestToUri :: Request -> URI
+ Network.OAuth.OAuth2: type PostBody = [(ByteString, ByteString)]
+ Network.OAuth.OAuth2: type QueryParams = [(ByteString, ByteString)]
+ Network.OAuth.OAuth2: uriToRequest :: MonadThrow m => URI -> m Request
+ Network.OAuth.OAuth2.TokenRequest: TokenRequestError :: TokenRequestErrorCode -> Maybe Text -> Maybe (URIRef Absolute) -> TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: UnknownErrorCode :: Text -> TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: [errorDescription] :: TokenRequestError -> Maybe Text
+ Network.OAuth.OAuth2.TokenRequest: [errorUri] :: TokenRequestError -> Maybe (URIRef Absolute)
+ Network.OAuth.OAuth2.TokenRequest: [error] :: TokenRequestError -> TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: data TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: data TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.TokenRequest.TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.TokenRequest.TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: instance GHC.Classes.Eq Network.OAuth.OAuth2.TokenRequest.TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: instance GHC.Classes.Eq Network.OAuth.OAuth2.TokenRequest.TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: instance GHC.Generics.Generic Network.OAuth.OAuth2.TokenRequest.TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: instance GHC.Show.Show Network.OAuth.OAuth2.TokenRequest.TokenRequestError
+ Network.OAuth.OAuth2.TokenRequest: instance GHC.Show.Show Network.OAuth.OAuth2.TokenRequest.TokenRequestErrorCode
+ Network.OAuth.OAuth2.TokenRequest: parseTokeRequestError :: ByteString -> TokenRequestError
+ Network.OAuth2.Experiment: -- WithExchangeToken a b = b' implies no exchange token v.s. 'type
+ Network.OAuth2.Experiment: -- client credentials) will use <a>ExchangeToken</a> in the token request
+ Network.OAuth2.Experiment: -- create type family to be explicit on it. with 'type instance
+ Network.OAuth2.Experiment: -- endpoint.
+ Network.OAuth2.Experiment: -- instance WithExchangeToken a b = ExchangeToken -&gt; b' implies
+ Network.OAuth2.Experiment: -- needing an exchange token
+ Network.OAuth2.Experiment: -- | <a>https://www.rfc-editor.org/rfc/rfc6749#page-47</a>
+ Network.OAuth2.Experiment: AuthorizationCode :: GrantTypeFlow
+ Network.OAuth2.Experiment: AuthorizeState :: Text -> AuthorizeState
+ Network.OAuth2.Experiment: ClientCredentials :: GrantTypeFlow
+ Network.OAuth2.Experiment: ClientId :: Text -> ClientId
+ Network.OAuth2.Experiment: ClientSecret :: Text -> ClientSecret
+ Network.OAuth2.Experiment: CodeChallenge :: Text -> CodeChallenge
+ Network.OAuth2.Experiment: CodeVerifier :: Text -> CodeVerifier
+ Network.OAuth2.Experiment: GTAuthorizationCode :: GrantTypeValue
+ Network.OAuth2.Experiment: GTClientCredentials :: GrantTypeValue
+ Network.OAuth2.Experiment: GTJwtBearer :: GrantTypeValue
+ Network.OAuth2.Experiment: GTPassword :: GrantTypeValue
+ Network.OAuth2.Experiment: GTRefreshToken :: GrantTypeValue
+ Network.OAuth2.Experiment: Idp :: URI -> URI -> URI -> (forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a)) -> Idp a
+ Network.OAuth2.Experiment: JwtBearer :: GrantTypeFlow
+ Network.OAuth2.Experiment: Password :: Text -> Password
+ Network.OAuth2.Experiment: PkceRequestParam :: CodeVerifier -> CodeChallenge -> CodeChallengeMethod -> PkceRequestParam
+ Network.OAuth2.Experiment: RedirectUri :: URI -> RedirectUri
+ Network.OAuth2.Experiment: ResourceOwnerPassword :: GrantTypeFlow
+ Network.OAuth2.Experiment: S256 :: CodeChallengeMethod
+ Network.OAuth2.Experiment: Scope :: Text -> Scope
+ Network.OAuth2.Experiment: UrnOAuthParam :: a -> UrnOAuthParam a
+ Network.OAuth2.Experiment: Username :: Text -> Username
+ Network.OAuth2.Experiment: [$sel:idpAuthorizeEndpoint:Idp] :: Idp a -> URI
+ Network.OAuth2.Experiment: [$sel:idpFetchUserInfo:Idp] :: Idp a -> forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a)
+ Network.OAuth2.Experiment: [$sel:idpTokenEndpoint:Idp] :: Idp a -> URI
+ Network.OAuth2.Experiment: [$sel:idpUserInfoEndpoint:Idp] :: Idp a -> URI
+ Network.OAuth2.Experiment: [$sel:unAuthorizeState:AuthorizeState] :: AuthorizeState -> Text
+ Network.OAuth2.Experiment: [$sel:unClientId:ClientId] :: ClientId -> Text
+ Network.OAuth2.Experiment: [$sel:unClientSecret:ClientSecret] :: ClientSecret -> Text
+ Network.OAuth2.Experiment: [$sel:unPassword:Password] :: Password -> Text
+ Network.OAuth2.Experiment: [$sel:unRedirectUri:RedirectUri] :: RedirectUri -> URI
+ Network.OAuth2.Experiment: [$sel:unScope:Scope] :: Scope -> Text
+ Network.OAuth2.Experiment: [$sel:unUsername:Username] :: Username -> Text
+ Network.OAuth2.Experiment: [codeChallengeMethod] :: PkceRequestParam -> CodeChallengeMethod
+ Network.OAuth2.Experiment: [codeChallenge] :: PkceRequestParam -> CodeChallenge
+ Network.OAuth2.Experiment: [codeVerifier] :: PkceRequestParam -> CodeVerifier
+ Network.OAuth2.Experiment: [unCodeChallenge] :: CodeChallenge -> Text
+ Network.OAuth2.Experiment: [unCodeVerifier] :: CodeVerifier -> Text
+ Network.OAuth2.Experiment: class HasAuthorizeRequest (a :: GrantTypeFlow) where {
+ Network.OAuth2.Experiment: class HasPkceAuthorizeRequest (a :: GrantTypeFlow)
+ Network.OAuth2.Experiment: class HasPkceTokenRequest (b :: GrantTypeFlow)
+ Network.OAuth2.Experiment: class HasRefreshTokenRequest (a :: GrantTypeFlow) where {
+ Network.OAuth2.Experiment: class HasTokenRequest (a :: GrantTypeFlow) where {
+ Network.OAuth2.Experiment: class HasUserInfoRequest (a :: GrantTypeFlow)
+ Network.OAuth2.Experiment: class ToQueryParam a
+ Network.OAuth2.Experiment: class ToResponseTypeValue (a :: GrantTypeFlow)
+ Network.OAuth2.Experiment: conduitPkceTokenRequest :: (HasPkceTokenRequest b, MonadIO m) => IdpApplication b i -> Manager -> (ExchangeToken, CodeVerifier) -> ExceptT TokenRequestError m OAuth2Token
+ Network.OAuth2.Experiment: conduitRefreshTokenRequest :: (HasRefreshTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> RefreshToken -> ExceptT TokenRequestError m OAuth2Token
+ Network.OAuth2.Experiment: conduitTokenRequest :: (HasTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> WithExchangeToken a (ExceptT TokenRequestError m OAuth2Token)
+ Network.OAuth2.Experiment: conduitUserInfoRequest :: (HasUserInfoRequest a, FromJSON (IdpUserInfo i)) => IdpApplication a i -> Manager -> AccessToken -> ExceptT ByteString IO (IdpUserInfo i)
+ Network.OAuth2.Experiment: data AuthorizationRequest a;
+ Network.OAuth2.Experiment: data CodeChallengeMethod
+ Network.OAuth2.Experiment: data GrantTypeFlow
+ Network.OAuth2.Experiment: data GrantTypeValue
+ Network.OAuth2.Experiment: data Idp a
+ Network.OAuth2.Experiment: data PkceRequestParam
+ Network.OAuth2.Experiment: data RefreshTokenRequest a;
+ Network.OAuth2.Experiment: data TokenRequest a;
+ Network.OAuth2.Experiment: data family IdpApplication (a :: GrantTypeFlow) (i :: Type)
+ Network.OAuth2.Experiment: mkAuthorizeRequest :: HasAuthorizeRequest a => IdpApplication a i -> MkAuthorizationRequestResponse a
+ Network.OAuth2.Experiment: mkAuthorizeRequestParameter :: HasAuthorizeRequest a => IdpApplication a i -> AuthorizationRequest a
+ Network.OAuth2.Experiment: mkPkceAuthorizeRequest :: (HasPkceAuthorizeRequest a, MonadIO m) => IdpApplication a i -> m (Text, CodeVerifier)
+ Network.OAuth2.Experiment: mkPkceParam :: MonadIO m => m PkceRequestParam
+ Network.OAuth2.Experiment: mkRefreshTokenRequest :: HasRefreshTokenRequest a => IdpApplication a i -> RefreshToken -> RefreshTokenRequest a
+ Network.OAuth2.Experiment: mkTokenRequest :: HasTokenRequest a => IdpApplication a i -> WithExchangeToken a (TokenRequest a)
+ Network.OAuth2.Experiment: newtype AuthorizeState
+ Network.OAuth2.Experiment: newtype ClientId
+ Network.OAuth2.Experiment: newtype ClientSecret
+ Network.OAuth2.Experiment: newtype CodeChallenge
+ Network.OAuth2.Experiment: newtype CodeVerifier
+ Network.OAuth2.Experiment: newtype Password
+ Network.OAuth2.Experiment: newtype RedirectUri
+ Network.OAuth2.Experiment: newtype Scope
+ Network.OAuth2.Experiment: newtype UrnOAuthParam a
+ Network.OAuth2.Experiment: newtype Username
+ Network.OAuth2.Experiment: toOAuth2Key :: ClientId -> ClientSecret -> OAuth2
+ Network.OAuth2.Experiment: toQueryParam :: ToQueryParam a => a -> Map Text Text
+ Network.OAuth2.Experiment: toResponseTypeParam :: forall a b req. (ToResponseTypeValue a, IsString b) => req a -> Map b b
+ Network.OAuth2.Experiment: toResponseTypeValue :: (ToResponseTypeValue a, IsString b) => b
+ Network.OAuth2.Experiment: type MkAuthorizationRequestResponse a;
+ Network.OAuth2.Experiment: type WithExchangeToken a b;
+ Network.OAuth2.Experiment: type family IdpUserInfo a
+ Network.OAuth2.Experiment: }
- Network.OAuth.OAuth2.TokenRequest: InvalidClient :: Errors
+ Network.OAuth.OAuth2.TokenRequest: InvalidClient :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: InvalidGrant :: Errors
+ Network.OAuth.OAuth2.TokenRequest: InvalidGrant :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: InvalidRequest :: Errors
+ Network.OAuth.OAuth2.TokenRequest: InvalidRequest :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: InvalidScope :: Errors
+ Network.OAuth.OAuth2.TokenRequest: InvalidScope :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: UnauthorizedClient :: Errors
+ Network.OAuth.OAuth2.TokenRequest: UnauthorizedClient :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: UnsupportedGrantType :: Errors
+ Network.OAuth.OAuth2.TokenRequest: UnsupportedGrantType :: TokenRequestErrorCode
- Network.OAuth.OAuth2.TokenRequest: doJSONPostRequest :: (MonadIO m, FromJSON err, FromJSON a) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m a
+ Network.OAuth.OAuth2.TokenRequest: doJSONPostRequest :: (MonadIO m, FromJSON a) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT TokenRequestError m a
- Network.OAuth.OAuth2.TokenRequest: doSimplePostRequest :: (MonadIO m, FromJSON err) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m ByteString
+ Network.OAuth.OAuth2.TokenRequest: doSimplePostRequest :: MonadIO m => Manager -> OAuth2 -> URI -> PostBody -> ExceptT TokenRequestError m ByteString
- Network.OAuth.OAuth2.TokenRequest: fetchAccessToken :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: fetchAccessToken :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: fetchAccessToken2 :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: fetchAccessToken2 :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: fetchAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: fetchAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: fetchAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: fetchAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: handleOAuth2TokenResponse :: FromJSON err => Response ByteString -> Either (OAuth2Error err) ByteString
+ Network.OAuth.OAuth2.TokenRequest: handleOAuth2TokenResponse :: Response ByteString -> Either TokenRequestError ByteString
- Network.OAuth.OAuth2.TokenRequest: parseResponseFlexible :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a
+ Network.OAuth.OAuth2.TokenRequest: parseResponseFlexible :: FromJSON a => ByteString -> Either TokenRequestError a
- Network.OAuth.OAuth2.TokenRequest: parseResponseString :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a
+ Network.OAuth.OAuth2.TokenRequest: parseResponseString :: FromJSON a => ByteString -> Either TokenRequestError a
- Network.OAuth.OAuth2.TokenRequest: refreshAccessToken :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: refreshAccessToken :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: refreshAccessToken2 :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: refreshAccessToken2 :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: refreshAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: refreshAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT TokenRequestError m OAuth2Token
- Network.OAuth.OAuth2.TokenRequest: refreshAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token
+ Network.OAuth.OAuth2.TokenRequest: refreshAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT TokenRequestError m OAuth2Token

Files

hoauth2.cabal view
@@ -2,7 +2,7 @@ name:               hoauth2  -- http://wiki.haskell.org/Package_versioning_policy-version:            2.6.0+version:            2.7.0 synopsis:           Haskell OAuth2 authentication client description:   Haskell OAuth2 authentication client.@@ -30,16 +30,20 @@ library   hs-source-dirs:     src   default-language:   Haskell2010+  autogen-modules:    Paths_hoauth2+  other-modules:+    Network.OAuth.OAuth2.Internal+    Network.OAuth2.Experiment.Pkce+    Network.OAuth2.Experiment.Types+    Network.OAuth2.Experiment.Utils+    Paths_hoauth2+   exposed-modules:     Network.OAuth.OAuth2     Network.OAuth.OAuth2.AuthorizationRequest     Network.OAuth.OAuth2.HttpClient-    Network.OAuth.OAuth2.Internal     Network.OAuth.OAuth2.TokenRequest     Network.OAuth2.Experiment-    Network.OAuth2.Experiment.Pkce-    Network.OAuth2.Experiment.Types-    Network.OAuth2.Experiment.Utils    default-extensions:     DataKinds@@ -52,24 +56,43 @@     TypeFamilies    build-depends:-    , aeson                 >=2.0   && <2.2-    , base                  >=4     && <5+    , aeson                 >=2.0    && <2.2+    , base                  >=4      && <5     , base64                ^>=0.4     , binary                ^>=0.8-    , bytestring            >=0.9   && <0.12+    , bytestring            >=0.9    && <0.12     , containers            ^>=0.6     , cryptonite            ^>=0.30     , data-default          ^>=0.7-    , exceptions            >=0.8.3 && <0.11-    , http-conduit          >=2.1   && <2.4-    , http-types            >=0.11  && <0.13+    , exceptions            >=0.8.3  && <0.11+    , http-conduit          >=2.1    && <2.4+    , http-types            >=0.11   && <0.13     , memory                ^>=0.17     , microlens             ^>=0.4.0-    , text                  >=0.11  && <1.3+    , text                  >=0.11   && <1.3     , transformers          ^>=0.5-    , uri-bytestring        >=0.2.3 && <0.4+    , uri-bytestring        >=0.2.3  && <0.4     , uri-bytestring-aeson  ^>=0.1    ghc-options:     -Wall -Wtabs -Wno-unused-do-bind -Wunused-packages -Wpartial-fields     -Wwarnings-deprecations++test-suite hoauth-tests+  type:               exitcode-stdio-1.0+  main-is:            Spec.hs+  hs-source-dirs:     test+  ghc-options:        -Wall+  build-depends:+    , aeson    >=2.0 && <2.2+    , base     >=4   && <5+    , hoauth2+    , hspec    >=2   && <3++  other-modules:      Network.OAuth.OAuth2.TokenRequestSpec+  default-language:   Haskell2010+  default-extensions:+    ImportQualifiedPost+    OverloadedStrings++  build-tool-depends: hspec-discover:hspec-discover >=2 && <3
src/Network/OAuth/OAuth2.hs view
@@ -1,19 +1,17 @@ -- | A lightweight oauth2 Haskell binding. -- See Readme for more details----module Network.OAuth.OAuth2-  ( module Network.OAuth.OAuth2.HttpClient,-    module Network.OAuth.OAuth2.AuthorizationRequest,-    module Network.OAuth.OAuth2.TokenRequest,-    module Network.OAuth.OAuth2.Internal,-  )-where+module Network.OAuth.OAuth2 (+  module Network.OAuth.OAuth2.HttpClient,+  module Network.OAuth.OAuth2.AuthorizationRequest,+  module Network.OAuth.OAuth2.TokenRequest,+  module Network.OAuth.OAuth2.Internal,+) where  {-   Hiding Errors data type from default.   Shall qualified import given the naming collision. -}-import Network.OAuth.OAuth2.AuthorizationRequest hiding (Errors(..))+import Network.OAuth.OAuth2.AuthorizationRequest hiding (Errors (..)) import Network.OAuth.OAuth2.HttpClient import Network.OAuth.OAuth2.Internal-import Network.OAuth.OAuth2.TokenRequest hiding (Errors(..))+import Network.OAuth.OAuth2.TokenRequest
src/Network/OAuth/OAuth2/AuthorizationRequest.hs view
@@ -7,8 +7,8 @@  import Data.Aeson import Data.Function (on)-import qualified Data.List as List-import qualified Data.Text.Encoding as T+import Data.List qualified as List+import Data.Text.Encoding qualified as T import GHC.Generics (Generic) import Lens.Micro (over) import Network.OAuth.OAuth2.Internal@@ -21,15 +21,12 @@ --------------------------------------------------  instance FromJSON Errors where-  parseJSON = genericParseJSON defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}--instance ToJSON Errors where-  toEncoding = genericToEncoding defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}+  parseJSON = genericParseJSON defaultOptions {constructorTagModifier = camelTo2 '_'}  -- | Authorization Code Grant Error Responses https://tools.ietf.org/html/rfc6749#section-4.1.2.1 -- I found hard time to figure a way to test the authorization error flow--- When anything wrong in @/authorize@ request (redirect to OAuth2 provider),--- it will end-up at the Provider page hence no way for this library to parse error response.+-- When anything wrong in @/authorize@ request, it will stuck at the Provider page+-- hence no way for this library to parse error response. -- In other words, @/authorize@ ends up with 4xx or 5xx. -- Revisit this whenever find a case OAuth2 provider redirects back to Relying party with errors. data Errors@@ -62,7 +59,7 @@     queryParts =       List.nubBy ((==) `on` fst) $         qs-          ++ [ ("client_id", T.encodeUtf8 $ oauth2ClientId oa),-               ("response_type", "code"),-               ("redirect_uri", serializeURIRef' $ oauth2RedirectUri oa)+          ++ [ ("client_id", T.encodeUtf8 $ oauth2ClientId oa)+             , ("response_type", "code")+             , ("redirect_uri", serializeURIRef' $ oauth2RedirectUri oa)              ]
src/Network/OAuth/OAuth2/HttpClient.hs view
@@ -4,39 +4,38 @@  -- | Bindings for The OAuth 2.0 Authorization Framework: Bearer Token Usage -- RFC6750 <https://www.rfc-editor.org/rfc/rfc6750>-module Network.OAuth.OAuth2.HttpClient-  ( -- * AUTH requests-    authGetJSON,-    authGetBS,-    authGetBS2,-    authGetJSONWithAuthMethod,-    authGetJSONInternal,-    authGetBSWithAuthMethod,-    authGetBSInternal,-    authPostJSON,-    authPostBS,-    authPostBS2,-    authPostBS3,-    authPostJSONWithAuthMethod,-    authPostJSONInternal,-    authPostBSWithAuthMethod,-    authPostBSInternal,+module Network.OAuth.OAuth2.HttpClient (+  -- * AUTH requests+  authGetJSON,+  authGetBS,+  authGetBS2,+  authGetJSONWithAuthMethod,+  authGetJSONInternal,+  authGetBSWithAuthMethod,+  authGetBSInternal,+  authPostJSON,+  authPostBS,+  authPostBS2,+  authPostBS3,+  authPostJSONWithAuthMethod,+  authPostJSONInternal,+  authPostBSWithAuthMethod,+  authPostBSInternal, -    -- * Types-    APIAuthenticationMethod (..),-  )-where+  -- * Types+  APIAuthenticationMethod (..),+) where  import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.Except (ExceptT (..), throwE) import Data.Aeson (FromJSON, eitherDecode)-import qualified Data.ByteString.Char8 as BS-import qualified Data.ByteString.Lazy.Char8 as BSL+import Data.ByteString.Char8 qualified as BS+import Data.ByteString.Lazy.Char8 qualified as BSL import Data.Maybe (fromJust, isJust)-import qualified Data.Text.Encoding as T+import Data.Text.Encoding qualified as T import Lens.Micro (over) import Network.HTTP.Conduit-import qualified Network.HTTP.Types as HT+import Network.HTTP.Types qualified as HT import Network.OAuth.OAuth2.Internal import URI.ByteString (URI, URIRef, queryL, queryPairsL) @@ -302,15 +301,20 @@   -- | HTTP connection manager.   Manager ->   ExceptT BSL.ByteString m BSL.ByteString-authRequest req upReq manage = ExceptT $ handleResponse <$> httpLbs (upReq req) manage+authRequest req upReq manage = ExceptT $ do+  resp <- httpLbs (upReq req) manage+  pure (handleResponse resp)  -- | Get response body out of a @Response@ handleResponse :: Response BSL.ByteString -> Either BSL.ByteString BSL.ByteString-handleResponse rsp =-  if HT.statusIsSuccessful (responseStatus rsp)-    then Right $ responseBody rsp-    else -- TODO: better to surface up entire resp so that client can decide what to do when error happens.-      Left $ responseBody rsp+handleResponse rsp+  | HT.statusIsSuccessful (responseStatus rsp) = Right (responseBody rsp)+  -- FIXME: better to surface up entire resp so that client can decide what to do when error happens.+  -- e.g. when 404, the response body could be empty hence library user has no idea what's happening.+  -- Which will be breaking changes.+  -- The current work around is surface up entire response as string.+  | BSL.null (responseBody rsp) = Left (BSL.pack $ show rsp)+  | otherwise = Left (responseBody rsp)  -- | Set several header values: --   + userAgennt    : `hoauth2`
src/Network/OAuth/OAuth2/Internal.hs view
@@ -6,24 +6,24 @@  module Network.OAuth.OAuth2.Internal where -import Control.Applicative import Control.Arrow (second) import Control.Monad.Catch import Data.Aeson import Data.Aeson.Types (Parser, explicitParseFieldMaybe) import Data.Binary (Binary)-import qualified Data.ByteString as BS-import qualified Data.ByteString.Lazy as BSL+import Data.ByteString qualified as BS+import Data.ByteString.Char8 qualified as BS8 import Data.Default import Data.Maybe-import Data.Text (Text, pack, unpack)-import Data.Text.Encoding+import Data.Text (Text, unpack)+import Data.Version (showVersion) import GHC.Generics import Lens.Micro import Lens.Micro.Extras import Network.HTTP.Conduit as C-import qualified Network.HTTP.Types as H-import qualified Network.HTTP.Types as HT+import Network.HTTP.Types qualified as H+import Network.HTTP.Types qualified as HT+import Paths_hoauth2 (version) import URI.ByteString import URI.ByteString.Aeson () import URI.ByteString.QQ@@ -36,22 +36,22 @@  -- | Query Parameter Representation data OAuth2 = OAuth2-  { oauth2ClientId :: Text,-    oauth2ClientSecret :: Text,-    oauth2AuthorizeEndpoint :: URIRef Absolute,-    oauth2TokenEndpoint :: URIRef Absolute,-    oauth2RedirectUri :: URIRef Absolute+  { oauth2ClientId :: Text+  , oauth2ClientSecret :: Text+  , oauth2AuthorizeEndpoint :: URIRef Absolute+  , oauth2TokenEndpoint :: URIRef Absolute+  , oauth2RedirectUri :: URIRef Absolute   }   deriving (Show, Eq)  instance Default OAuth2 where   def =     OAuth2-      { oauth2ClientId = "",-        oauth2ClientSecret = "",-        oauth2AuthorizeEndpoint = [uri|https://www.example.com/|],-        oauth2TokenEndpoint = [uri|https://www.example.com/|],-        oauth2RedirectUri = [uri|https://www.example.com/|]+      { oauth2ClientId = ""+      , oauth2ClientSecret = ""+      , oauth2AuthorizeEndpoint = [uri|https://www.example.com/|]+      , oauth2TokenEndpoint = [uri|https://www.example.com/|]+      , oauth2RedirectUri = [uri|https://www.example.com/|]       }  newtype AccessToken = AccessToken {atoken :: Text} deriving (Binary, Eq, Show, FromJSON, ToJSON)@@ -65,14 +65,14 @@  -- | https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4 data OAuth2Token = OAuth2Token-  { accessToken :: AccessToken,-    -- | Exists when @offline_access@ scope is in the 'authorizeUrl' and the provider supports Refresh Access Token.-    refreshToken :: Maybe RefreshToken,-    expiresIn :: Maybe Int,-    -- | See https://www.rfc-editor.org/rfc/rfc6749#section-5.1. It's required per spec. But OAuth2 provider implementation are vary. Maybe will remove 'Maybe' in future release.-    tokenType :: Maybe Text,-    -- | Exists when @openid@ scope is in the 'authorizeUrl' and the provider supports OpenID.-    idToken :: Maybe IdToken+  { accessToken :: AccessToken+  , refreshToken :: Maybe RefreshToken+  -- ^ Exists when @offline_access@ scope is in the 'authorizeUrl' and the provider supports Refresh Access Token.+  , expiresIn :: Maybe Int+  , tokenType :: Maybe Text+  -- ^ See https://www.rfc-editor.org/rfc/rfc6749#section-5.1. It's required per spec. But OAuth2 provider implementation are vary. Maybe will remove 'Maybe' in future release.+  , idToken :: Maybe IdToken+  -- ^ Exists when @openid@ scope is in the 'authorizeUrl' and the provider supports OpenID.   }   deriving (Eq, Show, Generic) @@ -100,37 +100,6 @@   toJSON = genericToJSON defaultOptions {fieldLabelModifier = camelTo2 '_'}   toEncoding = genericToEncoding defaultOptions {fieldLabelModifier = camelTo2 '_'} -data OAuth2Error a = OAuth2Error-  { error :: Either Text a,-    errorDescription :: Maybe Text,-    errorUri :: Maybe (URIRef Absolute)-  }-  deriving (Show, Eq, Generic)--instance FromJSON err => FromJSON (OAuth2Error err) where-  parseJSON (Object a) =-    do-      err <- (a .: "error") >>= (\str -> Right <$> parseJSON str <|> Left <$> parseJSON str)-      desc <- a .:? "error_description"-      errorUri <- a .:? "error_uri"-      return $ OAuth2Error err desc errorUri-  parseJSON _ = fail "Expected an object"--instance ToJSON err => ToJSON (OAuth2Error err) where-  toJSON = genericToJSON defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}-  toEncoding = genericToEncoding defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}--parseOAuth2Error :: FromJSON err => BSL.ByteString -> OAuth2Error err-parseOAuth2Error string =-  either (mkDecodeOAuth2Error string) id (eitherDecode string)--mkDecodeOAuth2Error :: BSL.ByteString -> String -> OAuth2Error err-mkDecodeOAuth2Error response err =-  OAuth2Error-    (Left "Decode error")-    (Just $ pack $ "Error: " <> err <> "\n Original Response:\n" <> show (decodeUtf8 $ BSL.toStrict response))-    Nothing- -- | https://www.rfc-editor.org/rfc/rfc6749#section-2.3 -- According to spec: --@@ -146,6 +115,7 @@ data ClientAuthenticationMethod   = ClientSecretBasic   | ClientSecretPost+  | ClientAssertionJwt   deriving (Eq, Ord)  --------------------------------------------------@@ -167,8 +137,8 @@  defaultRequestHeaders :: [(HT.HeaderName, BS.ByteString)] defaultRequestHeaders =-  [ (HT.hUserAgent, "hoauth2"),-    (HT.hAccept, "application/json")+  [ (HT.hUserAgent, "hoauth2-" <> BS8.pack (showVersion version))+  , (HT.hAccept, "application/json")   ]  appendQueryParams :: [(BS.ByteString, BS.ByteString)] -> URIRef a -> URIRef a@@ -189,8 +159,8 @@       req =         setQueryString query $           defaultRequest-            { secure = ssl,-              path = view pathL auri+            { secure = ssl+            , path = view pathL auri             }       req2 = (over hostLens . maybe id const . preview hostL) auri req       req3 = (over portLens . (const . fromMaybe defaultPort) . preview portL) auri req2
src/Network/OAuth/OAuth2/TokenRequest.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-}  -- | Bindings Access Token and Refresh Token part of The OAuth 2.0 Authorization Framework@@ -8,16 +7,18 @@ import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.Trans.Except (ExceptT (..), throwE) import Data.Aeson-import qualified Data.Aeson.Key as Key-import qualified Data.Aeson.KeyMap as KeyMap-import qualified Data.ByteString.Lazy.Char8 as BSL-import qualified Data.Text.Encoding as T+import Data.Aeson.Key qualified as Key+import Data.Aeson.KeyMap qualified as KeyMap+import Data.ByteString.Lazy.Char8 qualified as BSL+import Data.Text (Text)+import Data.Text qualified as T+import Data.Text.Encoding qualified as T import GHC.Generics (Generic) import Network.HTTP.Conduit-import qualified Network.HTTP.Types as HT+import Network.HTTP.Types qualified as HT import Network.HTTP.Types.URI (parseQuery) import Network.OAuth.OAuth2.Internal-import URI.ByteString (URI, serializeURIRef')+import URI.ByteString  -------------------------------------------------- @@ -25,22 +26,49 @@  -------------------------------------------------- -instance FromJSON Errors where-  parseJSON = genericParseJSON defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}--instance ToJSON Errors where-  toEncoding = genericToEncoding defaultOptions {constructorTagModifier = camelTo2 '_', allNullaryToStringTag = True}+data TokenRequestError = TokenRequestError+  { error :: TokenRequestErrorCode+  , errorDescription :: Maybe Text+  , errorUri :: Maybe (URIRef Absolute)+  }+  deriving (Show, Eq, Generic)  -- | Token Error Responses https://tools.ietf.org/html/rfc6749#section-5.2-data Errors+data TokenRequestErrorCode   = InvalidRequest   | InvalidClient   | InvalidGrant   | UnauthorizedClient   | UnsupportedGrantType   | InvalidScope-  deriving (Show, Eq, Generic)+  | UnknownErrorCode Text+  deriving (Show, Eq) +instance FromJSON TokenRequestErrorCode where+  parseJSON = withText "parseJSON TokenRequestErrorCode" $ \t ->+    pure $ case t of+      "invalid_request" -> InvalidRequest+      "invalid_client" -> InvalidClient+      "invalid_grant" -> InvalidGrant+      "unauthorized_client" -> UnauthorizedClient+      "unsupported_grant_type" -> UnsupportedGrantType+      "invalid_scope" -> InvalidScope+      _ -> UnknownErrorCode t++instance FromJSON TokenRequestError where+  parseJSON = genericParseJSON defaultOptions {constructorTagModifier = camelTo2 '_'}++parseTokeRequestError :: BSL.ByteString -> TokenRequestError+parseTokeRequestError string =+  either (mkDecodeOAuth2Error string) id (eitherDecode string)+  where+    mkDecodeOAuth2Error :: BSL.ByteString -> String -> TokenRequestError+    mkDecodeOAuth2Error response err =+      TokenRequestError+        (UnknownErrorCode "")+        (Just $ T.pack $ "Decode TokenRequestError failed: " <> err <> "\n Original Response:\n" <> show (T.decodeUtf8 $ BSL.toStrict response))+        Nothing+ --------------------------------------------------  -- * URL@@ -57,9 +85,9 @@ accessTokenUrl oa code =   let uri = oauth2TokenEndpoint oa       body =-        [ ("code", T.encodeUtf8 $ extoken code),-          ("redirect_uri", serializeURIRef' $ oauth2RedirectUri oa),-          ("grant_type", "authorization_code")+        [ ("code", T.encodeUtf8 $ extoken code)+        , ("redirect_uri", serializeURIRef' $ oauth2RedirectUri oa)+        , ("grant_type", "authorization_code")         ]    in (uri, body) @@ -74,8 +102,8 @@   where     uri = oauth2TokenEndpoint oa     body =-      [ ("grant_type", "refresh_token"),-        ("refresh_token", T.encodeUtf8 $ rtoken token)+      [ ("grant_type", "refresh_token")+      , ("refresh_token", T.encodeUtf8 $ rtoken token)       ]  --------------------------------------------------@@ -94,7 +122,7 @@   -- | OAuth2 Code   ExchangeToken ->   -- | Access Token-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token fetchAccessToken = fetchAccessTokenWithAuthMethod ClientSecretBasic  fetchAccessToken2 ::@@ -106,7 +134,7 @@   -- | Authorization Code   ExchangeToken ->   -- | Access Token-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token fetchAccessToken2 = fetchAccessTokenWithAuthMethod ClientSecretPost {-# DEPRECATED fetchAccessToken2 "use 'fetchAccessTokenWithAuthMethod'" #-} @@ -120,7 +148,7 @@   -- | Authorization Code   ExchangeToken ->   -- | Access Token-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token fetchAccessTokenInternal = fetchAccessTokenWithAuthMethod {-# DEPRECATED fetchAccessTokenInternal "use 'fetchAccessTokenWithAuthMethod'" #-} @@ -146,7 +174,7 @@   -- | Authorization Code   ExchangeToken ->   -- | Access Token-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token fetchAccessTokenWithAuthMethod authMethod manager oa code = do   let (uri, body) = accessTokenUrl oa code   let extraBody = if authMethod == ClientSecretPost then clientSecretPost oa else []@@ -161,7 +189,7 @@   OAuth2 ->   -- | Refresh Token gained after authorization   RefreshToken ->-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token refreshAccessToken = refreshAccessTokenWithAuthMethod ClientSecretBasic  refreshAccessToken2 ::@@ -172,7 +200,7 @@   OAuth2 ->   -- | Refresh Token gained after authorization   RefreshToken ->-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token refreshAccessToken2 = refreshAccessTokenWithAuthMethod ClientSecretPost {-# DEPRECATED refreshAccessToken2 "use 'refreshAccessTokenWithAuthMethod'" #-} @@ -185,7 +213,7 @@   OAuth2 ->   -- | Refresh Token gained after authorization   RefreshToken ->-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token refreshAccessTokenInternal = refreshAccessTokenWithAuthMethod {-# DEPRECATED refreshAccessTokenInternal "use 'refreshAccessTokenWithAuthMethod'" #-} @@ -210,7 +238,7 @@   OAuth2 ->   -- | Refresh Token gained after authorization   RefreshToken ->-  ExceptT (OAuth2Error Errors) m OAuth2Token+  ExceptT TokenRequestError m OAuth2Token refreshAccessTokenWithAuthMethod authMethod manager oa token = do   let (uri, body) = refreshAccessTokenUrl oa token   let extraBody = if authMethod == ClientSecretPost then clientSecretPost oa else []@@ -224,7 +252,7 @@  -- | Conduct post request and return response as JSON. doJSONPostRequest ::-  (MonadIO m, FromJSON err, FromJSON a) =>+  (MonadIO m, FromJSON a) =>   -- | HTTP connection manager.   Manager ->   -- | OAuth options@@ -234,7 +262,7 @@   -- | request body   PostBody ->   -- | Response as JSON-  ExceptT (OAuth2Error err) m a+  ExceptT TokenRequestError m a doJSONPostRequest manager oa uri body = do   resp <- doSimplePostRequest manager oa uri body   case parseResponseFlexible resp of@@ -243,7 +271,7 @@  -- | Conduct post request. doSimplePostRequest ::-  (MonadIO m, FromJSON err) =>+  (MonadIO m) =>   -- | HTTP connection manager.   Manager ->   -- | OAuth options@@ -253,7 +281,7 @@   -- | Request body.   PostBody ->   -- | Response as ByteString-  ExceptT (OAuth2Error err) m BSL.ByteString+  ExceptT TokenRequestError m BSL.ByteString doSimplePostRequest manager oa url body =   ExceptT . liftIO $ fmap handleOAuth2TokenResponse go   where@@ -264,26 +292,26 @@       httpLbs (urlEncodedBody body req') manager  -- | Gets response body from a @Response@ if 200 otherwise assume 'OAuth2Error'-handleOAuth2TokenResponse :: FromJSON err => Response BSL.ByteString -> Either (OAuth2Error err) BSL.ByteString+handleOAuth2TokenResponse :: Response BSL.ByteString -> Either TokenRequestError BSL.ByteString handleOAuth2TokenResponse rsp =   if HT.statusIsSuccessful (responseStatus rsp)     then Right $ responseBody rsp-    else Left $ parseOAuth2Error (responseBody rsp)+    else Left $ parseTokeRequestError (responseBody rsp)  -- | Try to parses response as JSON, if failed, try to parse as like query string. parseResponseFlexible ::-  (FromJSON err, FromJSON a) =>+  (FromJSON a) =>   BSL.ByteString ->-  Either (OAuth2Error err) a+  Either TokenRequestError a parseResponseFlexible r = case eitherDecode r of   Left _ -> parseResponseString r   Right x -> Right x  -- | Parses the response that contains not JSON but a Query String parseResponseString ::-  (FromJSON err, FromJSON a) =>+  (FromJSON a) =>   BSL.ByteString ->-  Either (OAuth2Error err) a+  Either TokenRequestError a parseResponseString b = case parseQuery $ BSL.toStrict b of   [] -> Left errorMessage   a -> case fromJSON $ queryToValue a of@@ -292,7 +320,7 @@   where     queryToValue = Object . KeyMap.fromList . map paramToPair     paramToPair (k, mv) = (Key.fromText $ T.decodeUtf8 k, maybe Null (String . T.decodeUtf8) mv)-    errorMessage = parseOAuth2Error b+    errorMessage = parseTokeRequestError b  -- | Set several header values: --   + userAgennt    : `hoauth2`@@ -305,6 +333,6 @@ -- | Add Credential (client_id, client_secret) to the request post body. clientSecretPost :: OAuth2 -> PostBody clientSecretPost oa =-  [ ("client_id", T.encodeUtf8 $ oauth2ClientId oa),-    ("client_secret", T.encodeUtf8 $ oauth2ClientSecret oa)+  [ ("client_id", T.encodeUtf8 $ oauth2ClientId oa)+  , ("client_secret", T.encodeUtf8 $ oauth2ClientSecret oa)   ]
src/Network/OAuth2/Experiment.hs view
@@ -86,12 +86,10 @@ -- @ -- -- Also you could find example from @hoauth2-providers-tutorials@ module.----module Network.OAuth2.Experiment-  ( module Network.OAuth2.Experiment.Types,-    module Network.OAuth2.Experiment.Pkce-  )-where+module Network.OAuth2.Experiment (+  module Network.OAuth2.Experiment.Types,+  module Network.OAuth2.Experiment.Pkce,+) where  import Network.OAuth2.Experiment.Pkce import Network.OAuth2.Experiment.Types
src/Network/OAuth2/Experiment/Pkce.hs view
@@ -1,11 +1,10 @@-module Network.OAuth2.Experiment.Pkce-  ( mkPkceParam,-    CodeChallenge (..),-    CodeVerifier (..),-    CodeChallengeMethod (..),-    PkceRequestParam (..),-  )-where+module Network.OAuth2.Experiment.Pkce (+  mkPkceParam,+  CodeChallenge (..),+  CodeVerifier (..),+  CodeChallengeMethod (..),+  PkceRequestParam (..),+) where  import Control.Monad.IO.Class import Crypto.Hash qualified as H@@ -25,11 +24,11 @@   deriving (Show)  data PkceRequestParam = PkceRequestParam-  { codeVerifier :: CodeVerifier,-    codeChallenge :: CodeChallenge,-    -- | spec says optional but really it shall be s256 or can be omitted?-    -- https://datatracker.ietf.org/doc/html/rfc7636#section-4.3-    codeChallengeMethod :: CodeChallengeMethod+  { codeVerifier :: CodeVerifier+  , codeChallenge :: CodeChallenge+  , codeChallengeMethod :: CodeChallengeMethod+  -- ^ spec says optional but really it shall be s256 or can be omitted?+  -- https://datatracker.ietf.org/doc/html/rfc7636#section-4.3   }  mkPkceParam :: MonadIO m => m PkceRequestParam@@ -37,9 +36,9 @@   codeV <- genCodeVerifier   pure     PkceRequestParam-      { codeVerifier = CodeVerifier (T.decodeUtf8 codeV),-        codeChallenge = CodeChallenge (encodeCodeVerifier codeV),-        codeChallengeMethod = S256+      { codeVerifier = CodeVerifier (T.decodeUtf8 codeV)+      , codeChallenge = CodeChallenge (encodeCodeVerifier codeV)+      , codeChallengeMethod = S256       }  encodeCodeVerifier :: BS.ByteString -> Text
src/Network/OAuth2/Experiment/Types.hs view
@@ -15,9 +15,10 @@ module Network.OAuth2.Experiment.Types where  import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Trans.Except (ExceptT)+import Control.Monad.Trans.Except (ExceptT (..), throwE) import Data.Aeson (FromJSON) import Data.Bifunctor+import Data.ByteString qualified as BS import Data.ByteString.Lazy.Char8 qualified as BSL import Data.Default (Default (def)) import Data.Kind@@ -29,10 +30,9 @@ import Data.Text.Encoding qualified as T import Data.Text.Lazy (Text) import Data.Text.Lazy qualified as TL-import Network.HTTP.Conduit (Manager)+import Network.HTTP.Conduit import Network.OAuth.OAuth2 hiding (RefreshToken) import Network.OAuth.OAuth2 qualified as OAuth2-import Network.OAuth.OAuth2.TokenRequest qualified as TR import Network.OAuth2.Experiment.Pkce import Network.OAuth2.Experiment.Utils import URI.ByteString hiding (UserInfo)@@ -47,7 +47,15 @@  ------------------------------------------------------------------------------- -data GrantTypeFlow = AuthorizationCode | ResourceOwnerPassword | ClientCredentials+data GrantTypeFlow+  = -- | https://www.rfc-editor.org/rfc/rfc6749#section-4.1+    AuthorizationCode+  | -- | https://www.rfc-editor.org/rfc/rfc6749#section-4.3+    ResourceOwnerPassword+  | -- | https://www.rfc-editor.org/rfc/rfc6749#section-4.4+    ClientCredentials+  | -- | https://www.rfc-editor.org/rfc/rfc7523.html#section-2.1+    JwtBearer  ------------------------------------------------------------------------------- @@ -73,10 +81,17 @@  ------------------------------------------------------------------------------- +newtype UrnOAuthParam a = UrnOAuthParam a+ -- | Grant type query parameter has association with 'GrantTypeFlow' but not completely strict. -- -- e.g. Both 'AuthorizationCode' and 'ResourceOwnerPassword' flow could support refresh token flow.-data GrantTypeValue = GTAuthorizationCode | GTPassword | GTClientCredentials | GTRefreshToken+data GrantTypeValue+  = GTAuthorizationCode+  | GTPassword+  | GTClientCredentials+  | GTRefreshToken+  | GTJwtBearer   deriving (Eq, Show)  -------------------------------------------------------------------------------@@ -107,6 +122,7 @@ newtype ClientId = ClientId {unClientId :: Text}   deriving (Show, Eq, IsString) +-- | Can be either "Client Secret" or JWT base on client authentication method newtype ClientSecret = ClientSecret {unClientSecret :: Text}   deriving (Eq, IsString) @@ -115,8 +131,8 @@ toOAuth2Key :: ClientId -> ClientSecret -> OAuth2 toOAuth2Key cid csecret =   def-    { oauth2ClientId = TL.toStrict $ unClientId cid,-      oauth2ClientSecret = TL.toStrict $ unClientSecret csecret+    { oauth2ClientId = TL.toStrict $ unClientId cid+    , oauth2ClientSecret = TL.toStrict $ unClientSecret csecret     }  newtype RedirectUri = RedirectUri {unRedirectUri :: URI}@@ -165,6 +181,7 @@       val GTPassword = "password"       val GTClientCredentials = "client_credentials"       val GTRefreshToken = "refresh_token"+      val GTJwtBearer = "urn:ietf:params:oauth:grant-type:jwt-bearer"  instance ToQueryParam ClientId where   toQueryParam :: ClientId -> Map Text Text@@ -222,9 +239,6 @@  ------------------------------------------------------------------------------- -class HasIdpAppName (a :: GrantTypeFlow) where-  getIdpAppName :: IdpApplication a i -> Text- class HasAuthorizeRequest (a :: GrantTypeFlow) where   data AuthorizationRequest a   type MkAuthorizationRequestResponse a@@ -249,7 +263,7 @@     (MonadIO m) =>     IdpApplication a i ->     Manager ->-    WithExchangeToken a (ExceptT (OAuth2Error TR.Errors) m OAuth2Token)+    WithExchangeToken a (ExceptT TokenRequestError m OAuth2Token)  class HasPkceAuthorizeRequest (a :: GrantTypeFlow) where   mkPkceAuthorizeRequest :: MonadIO m => IdpApplication a i -> m (TL.Text, CodeVerifier)@@ -260,7 +274,7 @@     IdpApplication b i ->     Manager ->     (ExchangeToken, CodeVerifier) ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token  class HasRefreshTokenRequest (a :: GrantTypeFlow) where   -- | https://www.rfc-editor.org/rfc/rfc6749#page-47@@ -272,7 +286,7 @@     IdpApplication a i ->     Manager ->     OAuth2.RefreshToken ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token  ------------------------------------------------------------------------------- @@ -298,12 +312,12 @@  -- | Shall IdpApplication has a field of 'Idp a'?? data Idp a = Idp-  { idpUserInfoEndpoint :: URI,-    -- NOTE: maybe worth data type to distinguish authorize and token endpoint+  { idpUserInfoEndpoint :: URI+  , -- NOTE: maybe worth data type to distinguish authorize and token endpoint     -- as I made mistake at passing to Authorize and Token Request-    idpAuthorizeEndpoint :: URI,-    idpTokenEndpoint :: URI,-    idpFetchUserInfo ::+    idpAuthorizeEndpoint :: URI+  , idpTokenEndpoint :: URI+  , idpFetchUserInfo ::       forall m.       (FromJSON (IdpUserInfo a), MonadIO m) =>       Manager ->@@ -328,16 +342,16 @@  -- | An Application that supports "Authorization code" flow data instance IdpApplication 'AuthorizationCode i = AuthorizationCodeIdpApplication-  { idpAppName :: Text,-    idpAppClientId :: ClientId,-    idpAppClientSecret :: ClientSecret,-    idpAppScope :: Set Scope,-    idpAppRedirectUri :: URI,-    idpAppAuthorizeState :: AuthorizeState,-    -- | Though technically one key can have multiple value in query, but who actually does it?!-    idpAppAuthorizeExtraParams :: Map Text Text,-    idpAppTokenRequestAuthenticationMethod :: ClientAuthenticationMethod,-    idp :: Idp i+  { idpAppName :: Text+  , idpAppClientId :: ClientId+  , idpAppClientSecret :: ClientSecret+  , idpAppScope :: Set Scope+  , idpAppRedirectUri :: URI+  , idpAppAuthorizeState :: AuthorizeState+  , idpAppAuthorizeExtraParams :: Map Text Text+  -- ^ Though technically one key can have multiple value in query, but who actually does it?!+  , idpAppTokenRequestAuthenticationMethod :: ClientAuthenticationMethod+  , idp :: Idp i   }  -- NOTE: maybe add function for parase authorization response@@ -345,27 +359,23 @@ -- parseAuthorizationResponse :: String -> AuthorizationResponse -- parseAuthorizationResponse :: ( String, String ) -> AuthorizationResponse -instance HasIdpAppName 'AuthorizationCode where-  getIdpAppName :: IdpApplication 'AuthorizationCode i -> Text-  getIdpAppName AuthorizationCodeIdpApplication {..} = idpAppName- instance HasAuthorizeRequest 'AuthorizationCode where   -- \| https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1   data AuthorizationRequest 'AuthorizationCode = AuthorizationCodeAuthorizationRequest-    { scope :: Set Scope,-      state :: AuthorizeState,-      clientId :: ClientId,-      redirectUri :: Maybe RedirectUri+    { scope :: Set Scope+    , state :: AuthorizeState+    , clientId :: ClientId+    , redirectUri :: Maybe RedirectUri     }   type MkAuthorizationRequestResponse 'AuthorizationCode = Text    mkAuthorizeRequestParameter :: IdpApplication 'AuthorizationCode i -> AuthorizationRequest 'AuthorizationCode   mkAuthorizeRequestParameter AuthorizationCodeIdpApplication {..} =     AuthorizationCodeAuthorizationRequest-      { scope = if null idpAppScope then Set.empty else idpAppScope,-        state = idpAppAuthorizeState,-        clientId = idpAppClientId,-        redirectUri = Just (RedirectUri idpAppRedirectUri)+      { scope = if null idpAppScope then Set.empty else idpAppScope+      , state = idpAppAuthorizeState+      , clientId = idpAppClientId+      , redirectUri = Just (RedirectUri idpAppRedirectUri)       }    mkAuthorizeRequest :: IdpApplication 'AuthorizationCode i -> Text@@ -384,10 +394,10 @@ instance HasTokenRequest 'AuthorizationCode where   -- \| https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3   data TokenRequest 'AuthorizationCode = AuthorizationCodeTokenRequest-    { code :: ExchangeToken,-      clientId :: ClientId,-      grantType :: GrantTypeValue,-      redirectUri :: RedirectUri+    { code :: ExchangeToken+    , clientId :: ClientId+    , grantType :: GrantTypeValue+    , redirectUri :: RedirectUri     }   type WithExchangeToken 'AuthorizationCode a = ExchangeToken -> a @@ -397,10 +407,10 @@     TokenRequest 'AuthorizationCode   mkTokenRequest AuthorizationCodeIdpApplication {..} authCode =     AuthorizationCodeTokenRequest-      { code = authCode,-        clientId = idpAppClientId,-        grantType = GTAuthorizationCode,-        redirectUri = RedirectUri idpAppRedirectUri+      { code = authCode+      , clientId = idpAppClientId+      , grantType = GTAuthorizationCode+      , redirectUri = RedirectUri idpAppRedirectUri       }   conduitTokenRequest ::     forall m i.@@ -408,14 +418,14 @@     IdpApplication 'AuthorizationCode i ->     Manager ->     ExchangeToken ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token   conduitTokenRequest idpAppConfig@AuthorizationCodeIdpApplication {..} mgr exchangeToken =     let req = mkTokenRequest idpAppConfig exchangeToken         key = toOAuth2Key idpAppClientId idpAppClientSecret         body =           mapsToParams-            [ toQueryParam req,-              toQueryParam+            [ toQueryParam req+            , toQueryParam                 ( if idpAppTokenRequestAuthenticationMethod == ClientSecretPost                     then Just idpAppClientSecret                     else Nothing@@ -430,10 +440,10 @@     let req = mkAuthorizeRequestParameter idpAppConfig     let allParams =           mapsToParams-            [ idpAppAuthorizeExtraParams,-              toQueryParam req,-              toQueryParam codeChallenge,-              toQueryParam codeChallengeMethod+            [ idpAppAuthorizeExtraParams+            , toQueryParam req+            , toQueryParam codeChallenge+            , toQueryParam codeChallengeMethod             ]      let url =@@ -450,45 +460,45 @@     IdpApplication 'AuthorizationCode i ->     Manager ->     (ExchangeToken, CodeVerifier) ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token   conduitPkceTokenRequest idpAppConfig@AuthorizationCodeIdpApplication {..} mgr (exchangeToken, codeVerifier) =     let req = mkTokenRequest idpAppConfig exchangeToken         key = toOAuth2Key idpAppClientId idpAppClientSecret         body =           mapsToParams-            [ toQueryParam req,-              toQueryParam codeVerifier,-              toQueryParam (if idpAppTokenRequestAuthenticationMethod == ClientSecretPost then Just idpAppClientSecret else Nothing)+            [ toQueryParam req+            , toQueryParam codeVerifier+            , toQueryParam (if idpAppTokenRequestAuthenticationMethod == ClientSecretPost then Just idpAppClientSecret else Nothing)             ]      in doJSONPostRequest mgr key (idpTokenEndpoint idp) body  instance HasRefreshTokenRequest 'AuthorizationCode where   data RefreshTokenRequest 'AuthorizationCode = AuthorizationCodeTokenRefreshRequest-    { refreshToken :: OAuth2.RefreshToken,-      grantType :: GrantTypeValue,-      scope :: Set Scope+    { refreshToken :: OAuth2.RefreshToken+    , grantType :: GrantTypeValue+    , scope :: Set Scope     }    mkRefreshTokenRequest :: IdpApplication 'AuthorizationCode i -> OAuth2.RefreshToken -> RefreshTokenRequest 'AuthorizationCode   mkRefreshTokenRequest AuthorizationCodeIdpApplication {..} rt =     AuthorizationCodeTokenRefreshRequest-      { scope = idpAppScope,-        grantType = GTRefreshToken,-        refreshToken = rt+      { scope = idpAppScope+      , grantType = GTRefreshToken+      , refreshToken = rt       }   conduitRefreshTokenRequest ::     (MonadIO m) =>     IdpApplication 'AuthorizationCode i ->     Manager ->     OAuth2.RefreshToken ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token   conduitRefreshTokenRequest idpAppConfig@AuthorizationCodeIdpApplication {..} mgr rt =     let req = mkRefreshTokenRequest idpAppConfig rt         key = toOAuth2Key idpAppClientId idpAppClientSecret         body =           mapsToParams-            [ toQueryParam req,-              toQueryParam (if idpAppTokenRequestAuthenticationMethod == ClientSecretPost then Just idpAppClientSecret else Nothing)+            [ toQueryParam req+            , toQueryParam (if idpAppTokenRequestAuthenticationMethod == ClientSecretPost then Just idpAppClientSecret else Nothing)             ]      in doJSONPostRequest mgr key (idpTokenEndpoint idp) body @@ -506,33 +516,90 @@   toQueryParam :: AuthorizationRequest 'AuthorizationCode -> Map Text Text   toQueryParam req@AuthorizationCodeAuthorizationRequest {..} =     Map.unions-      [ toResponseTypeParam req,-        toQueryParam scope,-        toQueryParam clientId,-        toQueryParam state,-        toQueryParam redirectUri+      [ toResponseTypeParam req+      , toQueryParam scope+      , toQueryParam clientId+      , toQueryParam state+      , toQueryParam redirectUri       ]  instance ToQueryParam (TokenRequest 'AuthorizationCode) where   toQueryParam :: TokenRequest 'AuthorizationCode -> Map Text Text   toQueryParam AuthorizationCodeTokenRequest {..} =     Map.unions-      [ toQueryParam grantType,-        toQueryParam code,-        toQueryParam redirectUri+      [ toQueryParam grantType+      , toQueryParam code+      , toQueryParam redirectUri       ]  instance ToQueryParam (RefreshTokenRequest 'AuthorizationCode) where   toQueryParam :: RefreshTokenRequest 'AuthorizationCode -> Map Text Text   toQueryParam AuthorizationCodeTokenRefreshRequest {..} =     Map.unions-      [ toQueryParam grantType,-        toQueryParam scope,-        toQueryParam refreshToken+      [ toQueryParam grantType+      , toQueryParam scope+      , toQueryParam refreshToken       ]  ------------------------------------------------------------------------------- +-- * JWTBearer++-------------------------------------------------------------------------------++-- | An Application that supports "Authorization code" flow+data instance IdpApplication 'JwtBearer i = JwtBearerIdpApplication+  { idpAppName :: Text+  , idpAppJwt :: BS.ByteString+  , idp :: Idp i+  }++instance HasTokenRequest 'JwtBearer where+  data TokenRequest 'JwtBearer = JwtBearerTokenRequest+    { grantType :: GrantTypeValue -- \| 'GTJwtBearer'+    , assertion :: BS.ByteString -- \| The the signed JWT token+    }+  type WithExchangeToken 'JwtBearer a = a++  mkTokenRequest ::+    IdpApplication 'JwtBearer i ->+    TokenRequest 'JwtBearer+  mkTokenRequest JwtBearerIdpApplication {..} =+    JwtBearerTokenRequest+      { grantType = GTJwtBearer+      , assertion = idpAppJwt+      }++  conduitTokenRequest ::+    forall m i.+    (MonadIO m) =>+    IdpApplication 'JwtBearer i ->+    Manager ->+    ExceptT TokenRequestError m OAuth2Token+  conduitTokenRequest idpAppConfig@JwtBearerIdpApplication {..} mgr = do+    resp <- ExceptT . liftIO $ do+      let tokenReq = mkTokenRequest idpAppConfig+      let body = mapsToParams [toQueryParam tokenReq]+      req <- uriToRequest (idpTokenEndpoint idp)+      handleOAuth2TokenResponse <$> httpLbs (urlEncodedBody body (addDefaultRequestHeaders req)) mgr+    case parseResponseFlexible resp of+      Right obj -> return obj+      Left e -> throwE e++instance ToQueryParam (TokenRequest 'JwtBearer) where+  toQueryParam :: TokenRequest 'JwtBearer -> Map Text Text+  toQueryParam JwtBearerTokenRequest {..} =+    Map.unions+      [ toQueryParam grantType+      , Map.fromList [("assertion", bs8ToLazyText assertion)]+      ]++instance HasUserInfoRequest 'JwtBearer where+  conduitUserInfoRequest JwtBearerIdpApplication {..} mgr at = do+    idpFetchUserInfo idp mgr at (idpUserInfoEndpoint idp)++-------------------------------------------------------------------------------+ -- * Password flow  -------------------------------------------------------------------------------@@ -545,51 +612,47 @@ -- -- Hence no AuhorizationRequest instance -data instance IdpApplication 'ResourceOwnerPassword i = ResourceOwnerPasswordIDPAppConfig-  { idpAppClientId :: ClientId,-    idpAppClientSecret :: ClientSecret,-    idpAppName :: Text,-    idpAppScope :: Set Scope,-    idpAppUserName :: Username,-    idpAppPassword :: Password,-    -- | Any parameter that required by your Idp and not mentioned in the OAuth2 spec-    idpAppTokenRequestExtraParams :: Map Text Text,-    idp :: Idp i+data instance IdpApplication 'ResourceOwnerPassword i = ResourceOwnerPasswordIDPApplication+  { idpAppClientId :: ClientId+  , idpAppClientSecret :: ClientSecret+  , idpAppName :: Text+  , idpAppScope :: Set Scope+  , idpAppUserName :: Username+  , idpAppPassword :: Password+  , idpAppTokenRequestExtraParams :: Map Text Text+  -- ^ Any parameter that required by your Idp and not mentioned in the OAuth2 spec+  , idp :: Idp i   } -instance HasIdpAppName 'ResourceOwnerPassword where-  getIdpAppName :: IdpApplication 'ResourceOwnerPassword i -> Text-  getIdpAppName ResourceOwnerPasswordIDPAppConfig {..} = idpAppName- instance HasUserInfoRequest 'ResourceOwnerPassword where-  conduitUserInfoRequest ResourceOwnerPasswordIDPAppConfig {..} mgr at = do+  conduitUserInfoRequest ResourceOwnerPasswordIDPApplication {..} mgr at = do     idpFetchUserInfo idp mgr at (idpUserInfoEndpoint idp)  instance HasTokenRequest 'ResourceOwnerPassword where   -- \| https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2   data TokenRequest 'ResourceOwnerPassword = PasswordTokenRequest-    { scope :: Set Scope,-      username :: Username,-      password :: Password,-      grantType :: GrantTypeValue+    { scope :: Set Scope+    , username :: Username+    , password :: Password+    , grantType :: GrantTypeValue     }   type WithExchangeToken 'ResourceOwnerPassword a = a    mkTokenRequest :: IdpApplication 'ResourceOwnerPassword i -> TokenRequest 'ResourceOwnerPassword-  mkTokenRequest ResourceOwnerPasswordIDPAppConfig {..} =+  mkTokenRequest ResourceOwnerPasswordIDPApplication {..} =     PasswordTokenRequest-      { username = idpAppUserName,-        password = idpAppPassword,-        grantType = GTPassword,-        scope = idpAppScope+      { username = idpAppUserName+      , password = idpAppPassword+      , grantType = GTPassword+      , scope = idpAppScope       }    conduitTokenRequest ::     (MonadIO m) =>     IdpApplication 'ResourceOwnerPassword i ->     Manager ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token-  conduitTokenRequest idpAppConfig@ResourceOwnerPasswordIDPAppConfig {..} mgr =+    ExceptT TokenRequestError m OAuth2Token+  conduitTokenRequest idpAppConfig@ResourceOwnerPasswordIDPApplication {..} mgr =     let req = mkTokenRequest idpAppConfig         key = toOAuth2Key idpAppClientId idpAppClientSecret         body = mapsToParams [idpAppTokenRequestExtraParams, toQueryParam req]@@ -610,17 +673,17 @@     IdpApplication 'ResourceOwnerPassword i ->     Manager ->     OAuth2.RefreshToken ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token+    ExceptT TokenRequestError m OAuth2Token   conduitRefreshTokenRequest = undefined  instance ToQueryParam (TokenRequest 'ResourceOwnerPassword) where   toQueryParam :: TokenRequest 'ResourceOwnerPassword -> Map Text Text   toQueryParam PasswordTokenRequest {..} =     Map.unions-      [ toQueryParam grantType,-        toQueryParam scope,-        toQueryParam username,-        toQueryParam password+      [ toQueryParam grantType+      , toQueryParam scope+      , toQueryParam username+      , toQueryParam password       ]  -------------------------------------------------------------------------------@@ -636,58 +699,80 @@ -- -- Hence no AuhorizationRequest instance -data instance IdpApplication 'ClientCredentials i = ClientCredentialsIDPAppConfig-  { idpAppClientId :: ClientId,-    idpAppClientSecret :: ClientSecret,-    idpAppName :: Text,-    idpAppScope :: Set Scope,-    -- | Any parameter that required by your Idp and not mentioned in the OAuth2 spec-    idpAppTokenRequestExtraParams :: Map Text Text,-    idp :: Idp i+data instance IdpApplication 'ClientCredentials i = ClientCredentialsIDPApplication+  { idpAppClientId :: ClientId+  , idpAppClientSecret :: ClientSecret+  , idpAppTokenRequestAuthenticationMethod :: ClientAuthenticationMethod+  -- ^ FIXME: rename to ClientCredential+  , idpAppName :: Text+  , idpAppScope :: Set Scope+  , idpAppTokenRequestExtraParams :: Map Text Text+  -- ^ Any parameter that required by your Idp and not mentioned in the OAuth2 spec+  , idp :: Idp i   } -instance HasIdpAppName 'ClientCredentials where-  getIdpAppName :: IdpApplication 'ClientCredentials i -> Text-  getIdpAppName ClientCredentialsIDPAppConfig {..} = idpAppName- instance HasTokenRequest 'ClientCredentials where   -- \| https://www.rfc-editor.org/rfc/rfc6749#section-4.4.2   data TokenRequest 'ClientCredentials = ClientCredentialsTokenRequest-    { scope :: Set Scope,-      grantType :: GrantTypeValue+    { scope :: Set Scope+    , grantType :: GrantTypeValue+    , clientAssertionType :: Text+    , clientAssertion :: BS.ByteString+    , clientAuthenticationMethod :: ClientAuthenticationMethod     }    type WithExchangeToken 'ClientCredentials a = a    mkTokenRequest :: IdpApplication 'ClientCredentials i -> TokenRequest 'ClientCredentials-  mkTokenRequest ClientCredentialsIDPAppConfig {..} =+  mkTokenRequest ClientCredentialsIDPApplication {..} =     ClientCredentialsTokenRequest-      { scope = idpAppScope,-        grantType = GTClientCredentials+      { scope = idpAppScope+      , grantType = GTClientCredentials+      , clientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"+      , clientAssertion = tlToBS $ unClientSecret idpAppClientSecret+      , clientAuthenticationMethod = idpAppTokenRequestAuthenticationMethod       }    conduitTokenRequest ::     (MonadIO m) =>     IdpApplication 'ClientCredentials i ->     Manager ->-    ExceptT (OAuth2Error TR.Errors) m OAuth2Token-  conduitTokenRequest idpAppConfig@ClientCredentialsIDPAppConfig {..} mgr =-    let req = mkTokenRequest idpAppConfig+    ExceptT TokenRequestError m OAuth2Token+  conduitTokenRequest idpAppConfig@ClientCredentialsIDPApplication {..} mgr = do+    let tokenReq = mkTokenRequest idpAppConfig         key =           toOAuth2Key             idpAppClientId             idpAppClientSecret         body =           mapsToParams-            [ idpAppTokenRequestExtraParams,-              toQueryParam req+            [ idpAppTokenRequestExtraParams+            , toQueryParam tokenReq             ]-     in doJSONPostRequest mgr key (idpTokenEndpoint idp) body+    if clientAuthenticationMethod tokenReq == ClientAssertionJwt+      then do+        resp <- ExceptT . liftIO $ do+          req <- uriToRequest (idpTokenEndpoint idp)+          let req' = urlEncodedBody body (addDefaultRequestHeaders req)+          handleOAuth2TokenResponse <$> httpLbs req' mgr+        case parseResponseFlexible resp of+          Right obj -> return obj+          Left e -> throwE e+      else doJSONPostRequest mgr key (idpTokenEndpoint idp) body  instance ToQueryParam (TokenRequest 'ClientCredentials) where   toQueryParam :: TokenRequest 'ClientCredentials -> Map Text Text   toQueryParam ClientCredentialsTokenRequest {..} =-    Map.unions-      [ toQueryParam grantType,-        toQueryParam scope+    Map.unions $+      [ toQueryParam grantType+      , toQueryParam scope       ]+        ++ [ Map.fromList+              ( if clientAuthenticationMethod == ClientAssertionJwt+                  then+                    [ ("client_assertion_type", clientAssertionType)+                    , ("client_assertion", bs8ToLazyText clientAssertion)+                    ]+                  else []+              )+           ]
+ test/Network/OAuth/OAuth2/TokenRequestSpec.hs view
@@ -0,0 +1,23 @@+module Network.OAuth.OAuth2.TokenRequestSpec where++import Data.Aeson qualified as Aeson+import Network.OAuth.OAuth2.TokenRequest+import Test.Hspec++spec :: Spec+spec =+  describe "parseJSON TokenRequestErrorCode" $ do+    it "invalid_request" $ do+      Aeson.eitherDecode "\"invalid_request\"" `shouldBe` Right InvalidRequest+    it "invalid_client" $ do+      Aeson.eitherDecode "\"invalid_client\"" `shouldBe` Right InvalidClient+    it "invalid_grant" $ do+      Aeson.eitherDecode "\"invalid_grant\"" `shouldBe` Right InvalidGrant+    it "unauthorized_client" $ do+      Aeson.eitherDecode "\"unauthorized_client\"" `shouldBe` Right UnauthorizedClient+    it "unsupported_grant_type" $ do+      Aeson.eitherDecode "\"unsupported_grant_type\"" `shouldBe` Right UnsupportedGrantType+    it "invalid_scope" $ do+      Aeson.eitherDecode "\"invalid_scope\"" `shouldBe` Right InvalidScope+    it "foo_code" $ do+      Aeson.eitherDecode "\"foo_code\"" `shouldBe` Right (UnknownErrorCode "foo_code")
+ test/Spec.hs view
@@ -0,0 +1,2 @@+-- file test/Spec.hs+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}