Safe Haskell | None |
---|---|
Language | Haskell2010 |
Network.OAuth2.Experiment
Description
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.
The key concept/change is to introduce the Grant flow, 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
- Authorization Code. This flow requires authorize call to obtain an authorize code, then exchange the code for tokens.
- Resource Owner Password. This flow only requires to hit token endpoint with, of course, username and password, to obtain tokens.
- Client Credentials. This flow also only requires to hit token endpoint but with different parameters. Client credentials flow does not involve an end user hence you won't be able to hit userinfo endpoint with access token obtained.
- PKCE (rfc7636). This is enhancement on top of authorization code flow.
Implicit flow is not supported because it is more for SPA (single page app) given it is deprecated by Authorization Code flow with PKCE.
Here is quick sample for how to use vocabularies from this new module.
Firstly, initialize your IdP (use google as example) and the application.
import Network.OAuth2.Experiment import URI.ByteString.QQ data Google = Google deriving (Eq, Show) googleIdp :: Idp Google googleIdp = Idp { 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|] , idpDeviceAuthorizationEndpoint = Just [uri|https://oauth2.googleapis.com/device/code|] } fooApp :: AuthorizationCodeApplication fooApp = AuthorizationCodeApplication { acClientId = "xxxxx", acClientSecret = "xxxxx", acScope = Set.fromList [ "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ], acAuthorizeState = "CHANGE_ME", acAuthorizeRequestExtraParams = Map.empty, acRedirectUri = [uri|http://localhost/oauth2/callback|], acName = "sample-google-authorization-code-app", acTokenRequestAuthenticationMethod = ClientSecretBasic, } fooIdpApplication :: IdpApplication AuthorizationCodeApplication Google fooIdpApplication = IdpApplication fooApp googleIdp
Secondly, construct the authorize URL.
authorizeUrl = mkAuthorizationRequest fooIdpApplication
Thirdly, after a successful redirect with authorize code, you could exchange for access token
mgr <- liftIO $ newManager tlsManagerSettings tokenResp <- conduitTokenRequest fooIdpApplication mgr authorizeCode
If you'd like to fetch user info, uses this method
conduitUserInfoRequest fooIdpApplication mgr (accessToken tokenResp)
You could also find example from hoauth2-providers-tutorials
module.
Synopsis
- data DeviceAuthorizationApplication = DeviceAuthorizationApplication {}
- pollDeviceTokenRequest :: forall {k} (m :: Type -> Type) (i :: k). MonadIO m => IdpApplication i DeviceAuthorizationApplication -> Manager -> DeviceAuthorizationResponse -> ExceptT TokenResponseError m OAuth2Token
- data AuthorizationCodeApplication = AuthorizationCodeApplication {}
- data ClientCredentialsApplication = ClientCredentialsApplication {}
- data JwtBearerApplication = JwtBearerApplication {}
- data ResourceOwnerPasswordApplication = ResourceOwnerPasswordApplication {}
- class HasAuthorizeRequest a
- mkAuthorizationRequest :: forall {k} a (i :: k). HasAuthorizeRequest a => IdpApplication i a -> URI
- mkPkceAuthorizeRequest :: forall {k} m a (i :: k). (MonadIO m, HasPkceAuthorizeRequest a) => IdpApplication i a -> m (URI, CodeVerifier)
- data DeviceAuthorizationResponse = DeviceAuthorizationResponse {}
- class HasOAuth2Key a => HasDeviceAuthorizationRequest a
- conduitDeviceAuthorizationRequest :: forall {k} (m :: Type -> Type) a (i :: k). (MonadIO m, HasDeviceAuthorizationRequest a) => IdpApplication i a -> Manager -> ExceptT ByteString m DeviceAuthorizationResponse
- class (HasOAuth2Key a, HasTokenRequestClientAuthenticationMethod a) => HasTokenRequest a where
- data TokenRequest a
- type ExchangeTokenInfo a
- data family TokenRequest a
- type family ExchangeTokenInfo a
- data NoNeedExchangeToken = NoNeedExchangeToken
- conduitPkceTokenRequest :: forall {k} a (m :: Type -> Type) (i :: k). (HasTokenRequest a, ToQueryParam (TokenRequest a), MonadIO m) => IdpApplication i a -> Manager -> (ExchangeTokenInfo a, CodeVerifier) -> ExceptT TokenResponseError m OAuth2Token
- conduitTokenRequest :: forall {k} a (m :: Type -> Type) (i :: k). (HasTokenRequest a, ToQueryParam (TokenRequest a), MonadIO m) => IdpApplication i a -> Manager -> ExchangeTokenInfo a -> ExceptT TokenResponseError m OAuth2Token
- class (HasOAuth2Key a, HasTokenRequestClientAuthenticationMethod a) => HasRefreshTokenRequest a
- conduitRefreshTokenRequest :: forall {k} (m :: Type -> Type) a (i :: k). (MonadIO m, HasRefreshTokenRequest a) => IdpApplication i a -> Manager -> RefreshToken -> ExceptT TokenResponseError m OAuth2Token
- module Network.OAuth2.Experiment.Flows.UserInfoRequest
- newtype AuthorizeState = AuthorizeState {}
- newtype ClientId = ClientId {
- unClientId :: Text
- newtype ClientSecret = ClientSecret {}
- class HasOAuth2Key a
- data Idp (i :: k) = Idp {}
- data IdpApplication (i :: k) a = IdpApplication {
- idp :: Idp i
- application :: a
- newtype Password = Password {
- unPassword :: Text
- newtype RedirectUri = RedirectUri {
- unRedirectUri :: URI
- newtype Scope = Scope {}
- newtype Username = Username {
- unUsername :: Text
- newtype CodeVerifier = CodeVerifier {}
- data ClientAuthenticationMethod
- uriToText :: URI -> Text
Application per Grant type
data DeviceAuthorizationApplication Source #
An Application that supports "Device Authorization Grant"
https://www.rfc-editor.org/rfc/rfc8628#section-3.1
Constructors
DeviceAuthorizationApplication | |
Fields
|
Instances
pollDeviceTokenRequest :: forall {k} (m :: Type -> Type) (i :: k). MonadIO m => IdpApplication i DeviceAuthorizationApplication -> Manager -> DeviceAuthorizationResponse -> ExceptT TokenResponseError m OAuth2Token Source #
data AuthorizationCodeApplication Source #
An Application that supports "Authorization code" flow
https://www.rfc-editor.org/rfc/rfc6749#section-4.1
Constructors
AuthorizationCodeApplication | |
Instances
HasAuthorizeRequest AuthorizationCodeApplication Source # | |||||||||
HasPkceAuthorizeRequest AuthorizationCodeApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Methods mkPkceAuthorizeRequestParam :: MonadIO m => AuthorizationCodeApplication -> m (AuthorizationRequestParam, CodeVerifier) Source # | |||||||||
HasRefreshTokenRequest AuthorizationCodeApplication Source # | |||||||||
HasTokenRequest AuthorizationCodeApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Associated Types
| |||||||||
HasTokenRequestClientAuthenticationMethod AuthorizationCodeApplication Source # | |||||||||
HasOAuth2Key AuthorizationCodeApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Methods mkOAuth2Key :: AuthorizationCodeApplication -> OAuth2 Source # | |||||||||
HasUserInfoRequest AuthorizationCodeApplication Source # | |||||||||
ToQueryParam (TokenRequest AuthorizationCodeApplication) Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Methods toQueryParam :: TokenRequest AuthorizationCodeApplication -> Map Text Text Source # | |||||||||
type ExchangeTokenInfo AuthorizationCodeApplication Source # | |||||||||
data TokenRequest AuthorizationCodeApplication Source # | |||||||||
data ClientCredentialsApplication Source #
An Application that supports "Client Credentials" flow
https://www.rfc-editor.org/rfc/rfc6749#section-4.4
Constructors
ClientCredentialsApplication | |
Instances
HasTokenRequest ClientCredentialsApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.4.2 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Associated Types
| |||||||||
HasTokenRequestClientAuthenticationMethod ClientCredentialsApplication Source # | |||||||||
HasOAuth2Key ClientCredentialsApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Methods mkOAuth2Key :: ClientCredentialsApplication -> OAuth2 Source # | |||||||||
ToQueryParam (TokenRequest ClientCredentialsApplication) Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Methods toQueryParam :: TokenRequest ClientCredentialsApplication -> Map Text Text Source # | |||||||||
type ExchangeTokenInfo ClientCredentialsApplication Source # | |||||||||
data TokenRequest ClientCredentialsApplication Source # | |||||||||
data JwtBearerApplication Source #
An Application that supports "JWT Bearer" flow
https://datatracker.ietf.org/doc/html/rfc7523
Constructors
JwtBearerApplication | |
Fields
|
Instances
HasTokenRequest JwtBearerApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Associated Types
| |||||||||
HasTokenRequestClientAuthenticationMethod JwtBearerApplication Source # | |||||||||
HasOAuth2Key JwtBearerApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Methods | |||||||||
HasUserInfoRequest JwtBearerApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.JwtBearer | |||||||||
ToQueryParam (TokenRequest JwtBearerApplication) Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Methods toQueryParam :: TokenRequest JwtBearerApplication -> Map Text Text Source # | |||||||||
type ExchangeTokenInfo JwtBearerApplication Source # | |||||||||
data TokenRequest JwtBearerApplication Source # | |||||||||
data ResourceOwnerPasswordApplication Source #
An Application that supports "Resource Owner Password" flow
https://www.rfc-editor.org/rfc/rfc6749#section-4.3
Constructors
ResourceOwnerPasswordApplication | |
Instances
HasRefreshTokenRequest ResourceOwnerPasswordApplication Source # | |||||||||
HasTokenRequest ResourceOwnerPasswordApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Associated Types
| |||||||||
HasTokenRequestClientAuthenticationMethod ResourceOwnerPasswordApplication Source # | |||||||||
HasOAuth2Key ResourceOwnerPasswordApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Methods mkOAuth2Key :: ResourceOwnerPasswordApplication -> OAuth2 Source # | |||||||||
HasUserInfoRequest ResourceOwnerPasswordApplication Source # | |||||||||
ToQueryParam (TokenRequest ResourceOwnerPasswordApplication) Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Methods toQueryParam :: TokenRequest ResourceOwnerPasswordApplication -> Map Text Text Source # | |||||||||
type ExchangeTokenInfo ResourceOwnerPasswordApplication Source # | |||||||||
data TokenRequest ResourceOwnerPasswordApplication Source # | |||||||||
Authorization Code
class HasAuthorizeRequest a Source #
Minimal complete definition
mkAuthorizationRequest :: forall {k} a (i :: k). HasAuthorizeRequest a => IdpApplication i a -> URI Source #
Constructs Authorization Code request URI https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1
mkPkceAuthorizeRequest :: forall {k} m a (i :: k). (MonadIO m, HasPkceAuthorizeRequest a) => IdpApplication i a -> m (URI, CodeVerifier) Source #
Constructs Authorization Code (PKCE) request URI and the Code Verifier. https://datatracker.ietf.org/doc/html/rfc7636
Device Authorization
data DeviceAuthorizationResponse Source #
Constructors
DeviceAuthorizationResponse | |
Fields
|
Instances
class HasOAuth2Key a => HasDeviceAuthorizationRequest a Source #
Minimal complete definition
conduitDeviceAuthorizationRequest :: forall {k} (m :: Type -> Type) a (i :: k). (MonadIO m, HasDeviceAuthorizationRequest a) => IdpApplication i a -> Manager -> ExceptT ByteString m DeviceAuthorizationResponse Source #
Makes Device Authorization Request https://www.rfc-editor.org/rfc/rfc8628#section-3.1
Token Request
class (HasOAuth2Key a, HasTokenRequestClientAuthenticationMethod a) => HasTokenRequest a Source #
Minimal complete definition
Instances
HasTokenRequest AuthorizationCodeApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Associated Types
| |||||||||
HasTokenRequest ClientCredentialsApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.4.2 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Associated Types
| |||||||||
HasTokenRequest DeviceAuthorizationApplication Source # | https://www.rfc-editor.org/rfc/rfc8628#section-3.4 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.DeviceAuthorization Associated Types
| |||||||||
HasTokenRequest JwtBearerApplication Source # | |||||||||
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Associated Types
| |||||||||
HasTokenRequest ResourceOwnerPasswordApplication Source # | https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2 | ||||||||
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Associated Types
|
data family TokenRequest a Source #
Instances
ToQueryParam (TokenRequest AuthorizationCodeApplication) Source # | |
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Methods toQueryParam :: TokenRequest AuthorizationCodeApplication -> Map Text Text Source # | |
ToQueryParam (TokenRequest ClientCredentialsApplication) Source # | |
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Methods toQueryParam :: TokenRequest ClientCredentialsApplication -> Map Text Text Source # | |
ToQueryParam (TokenRequest DeviceAuthorizationApplication) Source # | |
Defined in Network.OAuth2.Experiment.Grants.DeviceAuthorization Methods toQueryParam :: TokenRequest DeviceAuthorizationApplication -> Map Text Text Source # | |
ToQueryParam (TokenRequest JwtBearerApplication) Source # | |
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Methods toQueryParam :: TokenRequest JwtBearerApplication -> Map Text Text Source # | |
ToQueryParam (TokenRequest ResourceOwnerPasswordApplication) Source # | |
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Methods toQueryParam :: TokenRequest ResourceOwnerPasswordApplication -> Map Text Text Source # | |
data TokenRequest AuthorizationCodeApplication Source # | |
data TokenRequest ClientCredentialsApplication Source # | |
data TokenRequest DeviceAuthorizationApplication Source # | |
data TokenRequest JwtBearerApplication Source # | |
data TokenRequest ResourceOwnerPasswordApplication Source # | |
type family ExchangeTokenInfo a Source #
Instances
type ExchangeTokenInfo AuthorizationCodeApplication Source # | |
type ExchangeTokenInfo ClientCredentialsApplication Source # | |
type ExchangeTokenInfo DeviceAuthorizationApplication Source # | |
type ExchangeTokenInfo JwtBearerApplication Source # | |
type ExchangeTokenInfo ResourceOwnerPasswordApplication Source # | |
data NoNeedExchangeToken Source #
Only Authorization Code Grant involves a Exchange Token (Authorization Code). ResourceOwnerPassword and Client Credentials make token request directly.
Constructors
NoNeedExchangeToken |
conduitPkceTokenRequest :: forall {k} a (m :: Type -> Type) (i :: k). (HasTokenRequest a, ToQueryParam (TokenRequest a), MonadIO m) => IdpApplication i a -> Manager -> (ExchangeTokenInfo a, CodeVerifier) -> ExceptT TokenResponseError m OAuth2Token Source #
conduitTokenRequest :: forall {k} a (m :: Type -> Type) (i :: k). (HasTokenRequest a, ToQueryParam (TokenRequest a), MonadIO m) => IdpApplication i a -> Manager -> ExchangeTokenInfo a -> ExceptT TokenResponseError m OAuth2Token Source #
Refresh Token Request
class (HasOAuth2Key a, HasTokenRequestClientAuthenticationMethod a) => HasRefreshTokenRequest a Source #
Minimal complete definition
conduitRefreshTokenRequest :: forall {k} (m :: Type -> Type) a (i :: k). (MonadIO m, HasRefreshTokenRequest a) => IdpApplication i a -> Manager -> RefreshToken -> ExceptT TokenResponseError m OAuth2Token Source #
Make Refresh Token Request https://www.rfc-editor.org/rfc/rfc6749#section-6
UserInfo Request
Types
newtype AuthorizeState Source #
Constructors
AuthorizeState | |
Fields |
Instances
IsString AuthorizeState Source # | |
Defined in Network.OAuth2.Experiment.Types Methods fromString :: String -> AuthorizeState # | |
Eq AuthorizeState Source # | |
Defined in Network.OAuth2.Experiment.Types Methods (==) :: AuthorizeState -> AuthorizeState -> Bool # (/=) :: AuthorizeState -> AuthorizeState -> Bool # | |
ToQueryParam AuthorizeState Source # | |
Defined in Network.OAuth2.Experiment.Types Methods toQueryParam :: AuthorizeState -> Map Text Text Source # |
Constructors
ClientId | |
Fields
|
newtype ClientSecret Source #
Can be either "Client Secret" or JWT base on client authentication method
Constructors
ClientSecret | |
Fields |
Instances
IsString ClientSecret Source # | |
Defined in Network.OAuth2.Experiment.Types Methods fromString :: String -> ClientSecret # | |
Eq ClientSecret Source # | |
Defined in Network.OAuth2.Experiment.Types | |
ToQueryParam ClientSecret Source # | |
Defined in Network.OAuth2.Experiment.Types Methods toQueryParam :: ClientSecret -> Map Text Text Source # |
class HasOAuth2Key a Source #
Minimal complete definition
Instances
HasOAuth2Key AuthorizationCodeApplication Source # | |
Defined in Network.OAuth2.Experiment.Grants.AuthorizationCode Methods mkOAuth2Key :: AuthorizationCodeApplication -> OAuth2 Source # | |
HasOAuth2Key ClientCredentialsApplication Source # | |
Defined in Network.OAuth2.Experiment.Grants.ClientCredentials Methods mkOAuth2Key :: ClientCredentialsApplication -> OAuth2 Source # | |
HasOAuth2Key DeviceAuthorizationApplication Source # | |
Defined in Network.OAuth2.Experiment.Grants.DeviceAuthorization Methods mkOAuth2Key :: DeviceAuthorizationApplication -> OAuth2 Source # | |
HasOAuth2Key JwtBearerApplication Source # | |
Defined in Network.OAuth2.Experiment.Grants.JwtBearer Methods | |
HasOAuth2Key ResourceOwnerPasswordApplication Source # | |
Defined in Network.OAuth2.Experiment.Grants.ResourceOwnerPassword Methods mkOAuth2Key :: ResourceOwnerPasswordApplication -> OAuth2 Source # |
Idp i
consists various endpoints endpoints.
The i
is actually phantom type for information only (Idp name) at this moment.
And it is PolyKinds.
Hence whenever Idp i
or IdpApplication i a
is used as function parameter,
PolyKinds need to be enabled.
Constructors
Idp | |
Fields
|
data IdpApplication (i :: k) a Source #
An OAuth2 Application "a" of IdP "i". "a" can be one of following type:
Constructors
IdpApplication | |
Fields
|
Constructors
Password | |
Fields
|
Instances
IsString Password Source # | |
Defined in Network.OAuth2.Experiment.Types Methods fromString :: String -> Password # | |
Eq Password Source # | |
ToQueryParam Password Source # | |
Defined in Network.OAuth2.Experiment.Types |
newtype RedirectUri Source #
Constructors
RedirectUri | |
Fields
|
Instances
Eq RedirectUri Source # | |
Defined in Network.OAuth2.Experiment.Types | |
ToQueryParam RedirectUri Source # | |
Defined in Network.OAuth2.Experiment.Types Methods toQueryParam :: RedirectUri -> Map Text Text Source # |
Constructors
Username | |
Fields
|
Instances
IsString Username Source # | |
Defined in Network.OAuth2.Experiment.Types Methods fromString :: String -> Username # | |
Eq Username Source # | |
ToQueryParam Username Source # | |
Defined in Network.OAuth2.Experiment.Types |
newtype CodeVerifier Source #
Constructors
CodeVerifier | |
Fields |
Instances
ToQueryParam CodeVerifier Source # | |
Defined in Network.OAuth2.Experiment.Types Methods toQueryParam :: CodeVerifier -> Map Text Text Source # |
data ClientAuthenticationMethod Source #
How would the Client (RP) authenticate itself?
The client MUST NOT use more than one authentication method in each request. Means use Authorization header or Post body.
See more details
https://www.rfc-editor.org/rfc/rfc6749#section-2.3 https://oauth.net/private-key-jwt/ https://www.rfc-editor.org/rfc/rfc7523.html
Constructors
ClientSecretBasic | |
ClientSecretPost | |
ClientAssertionJwt |
Instances
Show ClientAuthenticationMethod Source # | |
Defined in Network.OAuth.OAuth2.Internal Methods showsPrec :: Int -> ClientAuthenticationMethod -> ShowS # show :: ClientAuthenticationMethod -> String # showList :: [ClientAuthenticationMethod] -> ShowS # | |
Eq ClientAuthenticationMethod Source # | |
Defined in Network.OAuth.OAuth2.Internal Methods (==) :: ClientAuthenticationMethod -> ClientAuthenticationMethod -> Bool # (/=) :: ClientAuthenticationMethod -> ClientAuthenticationMethod -> Bool # |