-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Haskell OAuth2 authentication client -- -- Haskell OAuth2 authentication client. -- -- Tutorial -- https://github.com/freizl/hoauth2/tree/main/hoauth2-tutorial/ -- -- Demo application -- https://github.com/freizl/hoauth2-demo/tree/main/hoauth2-demo/ @package hoauth2 @version 2.6.0 module Network.OAuth.OAuth2.Internal -- | Query Parameter Representation data OAuth2 OAuth2 :: Text -> Text -> URIRef Absolute -> URIRef Absolute -> URIRef Absolute -> OAuth2 [oauth2ClientId] :: OAuth2 -> Text [oauth2ClientSecret] :: OAuth2 -> Text [oauth2AuthorizeEndpoint] :: OAuth2 -> URIRef Absolute [oauth2TokenEndpoint] :: OAuth2 -> URIRef Absolute [oauth2RedirectUri] :: OAuth2 -> URIRef Absolute newtype AccessToken AccessToken :: Text -> AccessToken [atoken] :: AccessToken -> Text newtype RefreshToken RefreshToken :: Text -> RefreshToken [rtoken] :: RefreshToken -> Text newtype IdToken IdToken :: Text -> IdToken [idtoken] :: IdToken -> Text -- | Authorization Code newtype ExchangeToken ExchangeToken :: Text -> ExchangeToken [extoken] :: ExchangeToken -> Text -- | https://www.rfc-editor.org/rfc/rfc6749#section-4.1.4 data OAuth2Token OAuth2Token :: AccessToken -> Maybe RefreshToken -> Maybe Int -> Maybe Text -> Maybe IdToken -> OAuth2Token [accessToken] :: OAuth2Token -> AccessToken -- | Exists when offline_access scope is in the -- authorizeUrl and the provider supports Refresh Access Token. [refreshToken] :: OAuth2Token -> Maybe RefreshToken [expiresIn] :: OAuth2Token -> 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] :: OAuth2Token -> Maybe Text -- | Exists when openid scope is in the authorizeUrl and -- the provider supports OpenID. [idToken] :: OAuth2Token -> Maybe IdToken data OAuth2Error a OAuth2Error :: Either Text a -> Maybe Text -> Maybe (URIRef Absolute) -> OAuth2Error a [error] :: OAuth2Error a -> Either Text a [errorDescription] :: OAuth2Error a -> Maybe Text [errorUri] :: OAuth2Error a -> Maybe (URIRef Absolute) parseOAuth2Error :: FromJSON err => ByteString -> OAuth2Error err mkDecodeOAuth2Error :: ByteString -> String -> OAuth2Error err -- | https://www.rfc-editor.org/rfc/rfc6749#section-2.3 According to -- spec: -- -- The client MUST NOT use more than one authentication method in each -- request. -- -- Which means use Authorization header or Post body. -- -- However, in reality, I always have to include authentication in the -- header. -- -- In other words, ClientSecrectBasic is always assured. -- ClientSecretPost is optional. -- -- Maybe consider an alternative implementation that boolean kind of data -- type is good enough. data ClientAuthenticationMethod ClientSecretBasic :: ClientAuthenticationMethod ClientSecretPost :: ClientAuthenticationMethod -- | type synonym of post body content type PostBody = [(ByteString, ByteString)] type QueryParams = [(ByteString, ByteString)] defaultRequestHeaders :: [(HeaderName, ByteString)] appendQueryParams :: [(ByteString, ByteString)] -> URIRef a -> URIRef a uriToRequest :: MonadThrow m => URI -> m Request requestToUri :: Request -> URI hostLens :: Lens' Request ByteString portLens :: Lens' Request Int instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.OAuth2 instance GHC.Show.Show Network.OAuth.OAuth2.Internal.OAuth2 instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.AccessToken instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.AccessToken instance GHC.Show.Show Network.OAuth.OAuth2.Internal.AccessToken instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.AccessToken instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.AccessToken instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.RefreshToken instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.RefreshToken instance GHC.Show.Show Network.OAuth.OAuth2.Internal.RefreshToken instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.RefreshToken instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.RefreshToken instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.IdToken instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.IdToken instance GHC.Show.Show Network.OAuth.OAuth2.Internal.IdToken instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.IdToken instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.IdToken instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.ExchangeToken instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.ExchangeToken instance GHC.Show.Show Network.OAuth.OAuth2.Internal.ExchangeToken instance GHC.Generics.Generic Network.OAuth.OAuth2.Internal.OAuth2Token instance GHC.Show.Show Network.OAuth.OAuth2.Internal.OAuth2Token instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.OAuth2Token instance GHC.Generics.Generic (Network.OAuth.OAuth2.Internal.OAuth2Error a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Network.OAuth.OAuth2.Internal.OAuth2Error a) instance GHC.Show.Show a => GHC.Show.Show (Network.OAuth.OAuth2.Internal.OAuth2Error a) instance GHC.Classes.Ord Network.OAuth.OAuth2.Internal.ClientAuthenticationMethod instance GHC.Classes.Eq Network.OAuth.OAuth2.Internal.ClientAuthenticationMethod instance Data.Aeson.Types.FromJSON.FromJSON err => Data.Aeson.Types.FromJSON.FromJSON (Network.OAuth.OAuth2.Internal.OAuth2Error err) instance Data.Aeson.Types.ToJSON.ToJSON err => Data.Aeson.Types.ToJSON.ToJSON (Network.OAuth.OAuth2.Internal.OAuth2Error err) instance Data.Binary.Class.Binary Network.OAuth.OAuth2.Internal.OAuth2Token instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.Internal.OAuth2Token instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.Internal.OAuth2Token instance Data.Default.Class.Default Network.OAuth.OAuth2.Internal.OAuth2 -- | Bindings for The OAuth 2.0 Authorization Framework: Bearer Token Usage -- RFC6750 https://www.rfc-editor.org/rfc/rfc6750 module Network.OAuth.OAuth2.HttpClient -- | Conduct an authorized GET request and return response as JSON. Inject -- Access Token to Authorization Header. authGetJSON :: (FromJSON a, MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m a -- | Conduct an authorized GET request. Inject Access Token to -- Authorization Header. authGetBS :: MonadIO m => Manager -> AccessToken -> URI -> ExceptT ByteString m ByteString -- | Same to authGetBS but set access token to query parameter -- rather than header -- | Deprecated: use authGetBSWithAuthMethod authGetBS2 :: MonadIO m => Manager -> AccessToken -> URI -> ExceptT ByteString m ByteString -- | Conduct an authorized GET request and return response as JSON. Allow -- to specify how to append AccessToken. authGetJSONWithAuthMethod :: (MonadIO m, FromJSON a) => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> ExceptT ByteString m a -- | Deprecated: use authGetJSONWithAuthMethod authGetJSONInternal :: (FromJSON a, MonadIO m) => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> ExceptT ByteString m a -- | Conduct an authorized GET request and return response as ByteString. -- Allow to specify how to append AccessToken. authGetBSWithAuthMethod :: MonadIO m => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> ExceptT ByteString m ByteString -- | Deprecated: use authGetBSWithAuthMethod authGetBSInternal :: MonadIO m => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> ExceptT ByteString m ByteString -- | Conduct POST request and return response as JSON. Inject Access Token -- to Authorization Header. authPostJSON :: (FromJSON a, MonadIO m) => Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m a -- | Conduct POST request. Inject Access Token to http header -- (Authorization) authPostBS :: MonadIO m => Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m ByteString -- | Conduct POST request with access token only in the request body but -- header. -- | Deprecated: use authPostBSWithAuthMethod authPostBS2 :: MonadIO m => Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m ByteString -- | Conduct POST request with access token only in the header and not in -- body -- | Deprecated: use authPostBSWithAuthMethod authPostBS3 :: MonadIO m => Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m ByteString -- | Conduct POST request and return response as JSON. Allow to specify how -- to append AccessToken. authPostJSONWithAuthMethod :: (FromJSON a, MonadIO m) => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m a -- | Deprecated: use authPostJSONWithAuthMethod authPostJSONInternal :: (FromJSON a, MonadIO m) => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m a -- | Conduct POST request and return response as ByteString. Allow to -- specify how to append AccessToken. authPostBSWithAuthMethod :: MonadIO m => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m ByteString -- | Deprecated: use authPostBSWithAuthMethod authPostBSInternal :: MonadIO m => APIAuthenticationMethod -> Manager -> AccessToken -> URI -> PostBody -> ExceptT ByteString m ByteString -- | https://www.rfc-editor.org/rfc/rfc6750#section-2 data APIAuthenticationMethod -- | Provides in Authorization header AuthInRequestHeader :: APIAuthenticationMethod -- | Provides in request body AuthInRequestBody :: APIAuthenticationMethod -- | Provides in request query parameter AuthInRequestQuery :: APIAuthenticationMethod instance GHC.Classes.Ord Network.OAuth.OAuth2.HttpClient.APIAuthenticationMethod instance GHC.Classes.Eq Network.OAuth.OAuth2.HttpClient.APIAuthenticationMethod -- | Bindings Authorization part of The OAuth 2.0 Authorization Framework -- RFC6749 https://www.rfc-editor.org/rfc/rfc6749 module Network.OAuth.OAuth2.AuthorizationRequest -- | 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. 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 InvalidRequest :: Errors UnauthorizedClient :: Errors AccessDenied :: Errors UnsupportedResponseType :: Errors InvalidScope :: Errors ServerError :: Errors TemporarilyUnavailable :: Errors -- | See authorizationUrlWithParams authorizationUrl :: OAuth2 -> URI -- | Prepare the authorization URL. Redirect to this URL asking for user -- interactive authentication. authorizationUrlWithParams :: QueryParams -> OAuth2 -> URI instance GHC.Generics.Generic Network.OAuth.OAuth2.AuthorizationRequest.Errors instance GHC.Classes.Eq Network.OAuth.OAuth2.AuthorizationRequest.Errors instance GHC.Show.Show Network.OAuth.OAuth2.AuthorizationRequest.Errors instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.AuthorizationRequest.Errors instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.AuthorizationRequest.Errors -- | Bindings Access Token and Refresh Token part of The OAuth 2.0 -- Authorization Framework RFC6749 -- https://www.rfc-editor.org/rfc/rfc6749 module Network.OAuth.OAuth2.TokenRequest -- | Token Error Responses -- https://tools.ietf.org/html/rfc6749#section-5.2 data Errors InvalidRequest :: Errors InvalidClient :: Errors InvalidGrant :: Errors UnauthorizedClient :: Errors UnsupportedGrantType :: Errors InvalidScope :: Errors -- | Prepare the URL and the request body query for fetching an access -- token. accessTokenUrl :: OAuth2 -> ExchangeToken -> (URI, PostBody) -- | Obtain a new access token by sending a Refresh Token to the -- Authorization server. refreshAccessTokenUrl :: OAuth2 -> RefreshToken -> (URI, PostBody) -- | Exchange code for an Access Token with authenticate in -- request header. fetchAccessToken :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use fetchAccessTokenWithAuthMethod fetchAccessToken2 :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use fetchAccessTokenWithAuthMethod fetchAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Exchange code for an Access Token -- -- OAuth2 spec allows credential (client_id, -- client_secret) to be sent either in the header (a.k.a -- ClientSecretBasic). or as form/url params (a.k.a -- ClientSecretPost). -- -- The OAuth provider can choose to implement only one, or both. Look for -- API document from the OAuth provider you're dealing with. If you're -- uncertain, try fetchAccessToken which sends credential in -- authorization http header, which is common case. fetchAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Fetch a new AccessToken using the Refresh Token with authentication in -- request header. refreshAccessToken :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use refreshAccessTokenWithAuthMethod refreshAccessToken2 :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use refreshAccessTokenWithAuthMethod refreshAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Fetch a new AccessToken using the Refresh Token. -- -- OAuth2 spec allows credential (client_id, -- client_secret) to be sent either in the header (a.k.a -- ClientSecretBasic). or as form/url params (a.k.a -- ClientSecretPost). -- -- The OAuth provider can choose to implement only one, or both. Look for -- API document from the OAuth provider you're dealing with. If you're -- uncertain, try refreshAccessToken which sends credential in -- authorization http header, which is common case. refreshAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Conduct post request and return response as JSON. doJSONPostRequest :: (MonadIO m, FromJSON err, FromJSON a) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m a -- | Conduct post request. doSimplePostRequest :: (MonadIO m, FromJSON err) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m ByteString -- | Gets response body from a Response if 200 otherwise assume -- OAuth2Error handleOAuth2TokenResponse :: FromJSON err => Response ByteString -> Either (OAuth2Error err) ByteString -- | Try to parses response as JSON, if failed, try to parse as like query -- string. parseResponseFlexible :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a -- | Parses the response that contains not JSON but a Query String parseResponseString :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a -- | Set several header values: + userAgennt : hoauth2 + accept : -- `application/json` addDefaultRequestHeaders :: Request -> Request -- | Add Credential (client_id, client_secret) to the request post body. clientSecretPost :: OAuth2 -> PostBody instance GHC.Generics.Generic Network.OAuth.OAuth2.TokenRequest.Errors instance GHC.Classes.Eq Network.OAuth.OAuth2.TokenRequest.Errors instance GHC.Show.Show Network.OAuth.OAuth2.TokenRequest.Errors instance Data.Aeson.Types.FromJSON.FromJSON Network.OAuth.OAuth2.TokenRequest.Errors instance Data.Aeson.Types.ToJSON.ToJSON Network.OAuth.OAuth2.TokenRequest.Errors -- | A lightweight oauth2 Haskell binding. See Readme for more details module Network.OAuth.OAuth2 -- | See authorizationUrlWithParams authorizationUrl :: OAuth2 -> URI -- | Prepare the authorization URL. Redirect to this URL asking for user -- interactive authentication. authorizationUrlWithParams :: QueryParams -> OAuth2 -> URI -- | Prepare the URL and the request body query for fetching an access -- token. accessTokenUrl :: OAuth2 -> ExchangeToken -> (URI, PostBody) -- | Obtain a new access token by sending a Refresh Token to the -- Authorization server. refreshAccessTokenUrl :: OAuth2 -> RefreshToken -> (URI, PostBody) -- | Exchange code for an Access Token with authenticate in -- request header. fetchAccessToken :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use fetchAccessTokenWithAuthMethod fetchAccessToken2 :: MonadIO m => Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use fetchAccessTokenWithAuthMethod fetchAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Exchange code for an Access Token -- -- OAuth2 spec allows credential (client_id, -- client_secret) to be sent either in the header (a.k.a -- ClientSecretBasic). or as form/url params (a.k.a -- ClientSecretPost). -- -- The OAuth provider can choose to implement only one, or both. Look for -- API document from the OAuth provider you're dealing with. If you're -- uncertain, try fetchAccessToken which sends credential in -- authorization http header, which is common case. fetchAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> ExchangeToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Fetch a new AccessToken using the Refresh Token with authentication in -- request header. refreshAccessToken :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use refreshAccessTokenWithAuthMethod refreshAccessToken2 :: MonadIO m => Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Deprecated: use refreshAccessTokenWithAuthMethod refreshAccessTokenInternal :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Fetch a new AccessToken using the Refresh Token. -- -- OAuth2 spec allows credential (client_id, -- client_secret) to be sent either in the header (a.k.a -- ClientSecretBasic). or as form/url params (a.k.a -- ClientSecretPost). -- -- The OAuth provider can choose to implement only one, or both. Look for -- API document from the OAuth provider you're dealing with. If you're -- uncertain, try refreshAccessToken which sends credential in -- authorization http header, which is common case. refreshAccessTokenWithAuthMethod :: MonadIO m => ClientAuthenticationMethod -> Manager -> OAuth2 -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token -- | Conduct post request and return response as JSON. doJSONPostRequest :: (MonadIO m, FromJSON err, FromJSON a) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m a -- | Conduct post request. doSimplePostRequest :: (MonadIO m, FromJSON err) => Manager -> OAuth2 -> URI -> PostBody -> ExceptT (OAuth2Error err) m ByteString -- | Gets response body from a Response if 200 otherwise assume -- OAuth2Error handleOAuth2TokenResponse :: FromJSON err => Response ByteString -> Either (OAuth2Error err) ByteString -- | Try to parses response as JSON, if failed, try to parse as like query -- string. parseResponseFlexible :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a -- | Parses the response that contains not JSON but a Query String parseResponseString :: (FromJSON err, FromJSON a) => ByteString -> Either (OAuth2Error err) a -- | Set several header values: + userAgennt : hoauth2 + accept : -- `application/json` addDefaultRequestHeaders :: Request -> Request -- | Add Credential (client_id, client_secret) to the request post body. clientSecretPost :: OAuth2 -> PostBody module Network.OAuth2.Experiment.Pkce mkPkceParam :: MonadIO m => m PkceRequestParam newtype CodeChallenge CodeChallenge :: Text -> CodeChallenge [unCodeChallenge] :: CodeChallenge -> Text newtype CodeVerifier CodeVerifier :: Text -> CodeVerifier [unCodeVerifier] :: CodeVerifier -> Text data CodeChallengeMethod S256 :: CodeChallengeMethod data PkceRequestParam PkceRequestParam :: CodeVerifier -> CodeChallenge -> CodeChallengeMethod -> PkceRequestParam [codeVerifier] :: PkceRequestParam -> CodeVerifier [codeChallenge] :: PkceRequestParam -> 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] :: PkceRequestParam -> CodeChallengeMethod instance GHC.Show.Show Network.OAuth2.Experiment.Pkce.CodeVerifier instance GHC.Show.Show Network.OAuth2.Experiment.Pkce.CodeChallengeMethod module Network.OAuth2.Experiment.Utils tlToBS :: Text -> ByteString bs8ToLazyText :: ByteString -> Text mapsToParams :: [Map Text Text] -> [(ByteString, ByteString)] module Network.OAuth2.Experiment.Types data GrantTypeFlow AuthorizationCode :: GrantTypeFlow ResourceOwnerPassword :: GrantTypeFlow ClientCredentials :: GrantTypeFlow class ToResponseTypeValue (a :: GrantTypeFlow) toResponseTypeValue :: (ToResponseTypeValue a, IsString b) => b toResponseTypeParam :: forall a b req. (ToResponseTypeValue a, IsString b) => req a -> Map b b -- | 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 :: GrantTypeValue GTPassword :: GrantTypeValue GTClientCredentials :: GrantTypeValue GTRefreshToken :: GrantTypeValue newtype Scope Scope :: Text -> Scope [$sel:unScope:Scope] :: Scope -> Text newtype ClientId ClientId :: Text -> ClientId [$sel:unClientId:ClientId] :: ClientId -> Text newtype ClientSecret ClientSecret :: Text -> ClientSecret [$sel:unClientSecret:ClientSecret] :: ClientSecret -> Text -- | In order to reuse some methods from legacy -- Network.OAuth.OAuth2. Will be removed when Experiment module -- becomes default. toOAuth2Key :: ClientId -> ClientSecret -> OAuth2 newtype RedirectUri RedirectUri :: URI -> RedirectUri [$sel:unRedirectUri:RedirectUri] :: RedirectUri -> URI newtype AuthorizeState AuthorizeState :: Text -> AuthorizeState [$sel:unAuthorizeState:AuthorizeState] :: AuthorizeState -> Text newtype Username Username :: Text -> Username [$sel:unUsername:Username] :: Username -> Text newtype Password Password :: Text -> Password [$sel:unPassword:Password] :: Password -> Text class ToQueryParam a toQueryParam :: ToQueryParam a => a -> Map Text Text class HasIdpAppName (a :: GrantTypeFlow) getIdpAppName :: HasIdpAppName a => IdpApplication a i -> Text class HasAuthorizeRequest (a :: GrantTypeFlow) where { data AuthorizationRequest a; type MkAuthorizationRequestResponse a; } mkAuthorizeRequestParameter :: HasAuthorizeRequest a => IdpApplication a i -> AuthorizationRequest a mkAuthorizeRequest :: HasAuthorizeRequest a => IdpApplication a i -> MkAuthorizationRequestResponse a class HasTokenRequest (a :: GrantTypeFlow) where { -- | Each GrantTypeFlow has slightly different request parameter to /token -- endpoint. data TokenRequest a; -- | Only 'AuthorizationCode flow (but not resource owner password nor -- client credentials) will use ExchangeToken in the token request -- create type family to be explicit on it. with 'type instance -- WithExchangeToken a b = b' implies no exchange token v.s. 'type -- instance WithExchangeToken a b = ExchangeToken -> b' implies -- needing an exchange token type WithExchangeToken a b; } mkTokenRequest :: HasTokenRequest a => IdpApplication a i -> WithExchangeToken a (TokenRequest a) conduitTokenRequest :: (HasTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> WithExchangeToken a (ExceptT (OAuth2Error Errors) m OAuth2Token) class HasPkceAuthorizeRequest (a :: GrantTypeFlow) mkPkceAuthorizeRequest :: (HasPkceAuthorizeRequest a, MonadIO m) => IdpApplication a i -> m (Text, CodeVerifier) class HasPkceTokenRequest (b :: GrantTypeFlow) conduitPkceTokenRequest :: (HasPkceTokenRequest b, MonadIO m) => IdpApplication b i -> Manager -> (ExchangeToken, CodeVerifier) -> ExceptT (OAuth2Error Errors) m OAuth2Token class HasRefreshTokenRequest (a :: GrantTypeFlow) where { -- | https://www.rfc-editor.org/rfc/rfc6749#page-47 data RefreshTokenRequest a; } mkRefreshTokenRequest :: HasRefreshTokenRequest a => IdpApplication a i -> RefreshToken -> RefreshTokenRequest a conduitRefreshTokenRequest :: (HasRefreshTokenRequest a, MonadIO m) => IdpApplication a i -> Manager -> RefreshToken -> ExceptT (OAuth2Error Errors) m OAuth2Token type family IdpUserInfo a class HasUserInfoRequest (a :: GrantTypeFlow) conduitUserInfoRequest :: (HasUserInfoRequest a, FromJSON (IdpUserInfo i)) => IdpApplication a i -> Manager -> AccessToken -> ExceptT ByteString IO (IdpUserInfo i) -- | Shall IdpApplication has a field of 'Idp a'?? data Idp a Idp :: URI -> URI -> URI -> (forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a)) -> Idp a [$sel:idpUserInfoEndpoint:Idp] :: Idp a -> URI [$sel:idpAuthorizeEndpoint:Idp] :: Idp a -> URI [$sel:idpTokenEndpoint:Idp] :: Idp a -> URI [$sel:idpFetchUserInfo:Idp] :: Idp a -> forall m. (FromJSON (IdpUserInfo a), MonadIO m) => Manager -> AccessToken -> URI -> ExceptT ByteString m (IdpUserInfo a) data family IdpApplication (a :: GrantTypeFlow) (i :: Type) instance GHC.Show.Show Network.OAuth2.Experiment.Types.GrantTypeValue instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.GrantTypeValue instance GHC.Classes.Ord Network.OAuth2.Experiment.Types.Scope instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Scope instance GHC.Show.Show Network.OAuth2.Experiment.Types.Scope instance Data.String.IsString Network.OAuth2.Experiment.Types.ClientId instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.ClientId instance GHC.Show.Show Network.OAuth2.Experiment.Types.ClientId instance Data.String.IsString Network.OAuth2.Experiment.Types.ClientSecret instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.ClientSecret instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.RedirectUri instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.AuthorizeState instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Username instance GHC.Classes.Eq Network.OAuth2.Experiment.Types.Password instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword instance Network.OAuth2.Experiment.Types.HasIdpAppName 'Network.OAuth2.Experiment.Types.ClientCredentials instance Network.OAuth2.Experiment.Types.HasAuthorizeRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.HasPkceAuthorizeRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.AuthorizationRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode) instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.HasPkceTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode) instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword) instance Network.OAuth2.Experiment.Types.HasTokenRequest 'Network.OAuth2.Experiment.Types.ClientCredentials instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.TokenRequest 'Network.OAuth2.Experiment.Types.ClientCredentials) instance Network.OAuth2.Experiment.Types.HasRefreshTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.ToQueryParam (Network.OAuth2.Experiment.Types.RefreshTokenRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode) instance Network.OAuth2.Experiment.Types.HasRefreshTokenRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword instance Network.OAuth2.Experiment.Types.HasUserInfoRequest 'Network.OAuth2.Experiment.Types.AuthorizationCode instance Network.OAuth2.Experiment.Types.HasUserInfoRequest 'Network.OAuth2.Experiment.Types.ResourceOwnerPassword instance Network.OAuth2.Experiment.Types.ToQueryParam a => Network.OAuth2.Experiment.Types.ToQueryParam (GHC.Maybe.Maybe a) instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.GrantTypeValue instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.ClientId instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.ClientSecret instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.Username instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.Password instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.AuthorizeState instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Types.RedirectUri instance Network.OAuth2.Experiment.Types.ToQueryParam (Data.Set.Internal.Set Network.OAuth2.Experiment.Types.Scope) instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeVerifier instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeChallenge instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth2.Experiment.Pkce.CodeChallengeMethod instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth.OAuth2.Internal.ExchangeToken instance Network.OAuth2.Experiment.Types.ToQueryParam Network.OAuth.OAuth2.Internal.RefreshToken instance Data.String.IsString Network.OAuth2.Experiment.Types.Password instance Data.String.IsString Network.OAuth2.Experiment.Types.Username instance Data.String.IsString Network.OAuth2.Experiment.Types.AuthorizeState instance Data.String.IsString Network.OAuth2.Experiment.Types.Scope instance Network.OAuth2.Experiment.Types.ToResponseTypeValue 'Network.OAuth2.Experiment.Types.AuthorizationCode -- | This module contains a new way of doing OAuth2 authorization and -- authentication in order to obtain Access Token and maybe Refresh Token -- base on rfc6749. -- -- This module will become default in future release. (TBD but likely -- 3.0). -- -- The key concept/change is to introduce the GrantTypeFlow, which -- determines the entire work flow per spec. Each work flow will have -- slight different request parameters, which often time you'll see -- different configuration when creating OAuth2 application in the IdP -- developer application page. -- -- Here are supported flows -- --
-- data Google = Google deriving (Eq, Show)
-- googleIdp = Idp Google
-- Idp
-- { idpFetchUserInfo = authGetJSON @(IdpUserInfo Google),
-- idpAuthorizeEndpoint = [uri|https://accounts.google.com/o/oauth2/v2/auth|],
-- idpTokenEndpoint = [uri|https://oauth2.googleapis.com/token|],
-- idpUserInfoEndpoint = [uri|https://www.googleapis.com/oauth2/v2/userinfo|]
-- }
--
-- fooApp :: IdpApplication 'AuthorizationCode Google
-- fooApp =
-- AuthorizationCodeIdpApplication
-- { idpAppClientId = "xxxxx",
-- idpAppClientSecret = "xxxxx",
-- idpAppScope =
-- Set.fromList
-- [ "https://www.googleapis.com/auth/userinfo.email",
-- "https://www.googleapis.com/auth/userinfo.profile"
-- ],
-- idpAppAuthorizeState = "CHANGE_ME",
-- idpAppAuthorizeExtraParams = Map.empty,
-- idpAppRedirectUri = [uri|http://localhost/oauth2/callback|],
-- idpAppName = "default-google-App",
-- idpAppTokenRequestAuthenticationMethod = ClientSecretBasic,
-- idp = googleIdp
-- }
--
--
-- Secondly, construct the authorize URL.
--
-- -- authorizeUrl = mkAuthorizeRequest fooApp ---- -- Thirdly, after a successful redirect with authorize code, you could -- exchange for access token -- --
-- mgr <- liftIO $ newManager tlsManagerSettings -- tokenResp <- conduitTokenRequest fooApp mgr authorizeCode ---- -- Lastly, you probably like to fetch user info -- --
-- conduitUserInfoRequest fooApp mgr (accessToken tokenResp) ---- -- Also you could find example from hoauth2-providers-tutorials -- module. module Network.OAuth2.Experiment