HORIZON HASKELLDocslts/ghc-9.10.xc74966e2026-09-27Search names, modules, packages, or :: a typeCtrl K

GHC 9.10.3 · lts/ghc-9.10.x · c74966e · 2026-09-27

Modulehoauth2-2.14.3Haskell2010

Network.OAuth2.Experiment

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

  1. Authorization Code. This flow requires authorize call to obtain an authorize code, then exchange the code for tokens.

  2. Resource Owner Password. This flow only requires to hit token endpoint with, of course, username and password, to obtain tokens.

  3. 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.

  4. 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.

  • 18 types
  • 5 classes
  • 8 values
  • Packagehoauth2-2.14.3
  • Exports33
  • LanguageHaskell2010
  • LicenceMIT
  • SourceExperiment.hs

Application per Grant type

6 declarations

An Application that supports "Device Authorization Grant"

https://www.rfc-editor.org/rfc/rfc8628#section-3.1

Constructors

Instances8HasDeviceAuthorizationRequest, HasTokenRequest, HasOAuth2Key, HasTokenRequestClientAuthenticationMethod, HasUserInfoRequest, ToQueryParam, …
Instances10HasAuthorizeRequest, HasRefreshTokenRequest, HasTokenRequest, HasOAuth2Key, HasPkceAuthorizeRequest, HasTokenRequestClientAuthenticationMethod, …
Instances6HasTokenRequest, HasOAuth2Key, HasTokenRequestClientAuthenticationMethod, ToQueryParam, ExchangeTokenInfo, TokenRequest
datadata JwtBearerApplication
#

An Application that supports "JWT Bearer" flow

https://datatracker.ietf.org/doc/html/rfc7523

Instances7HasTokenRequest, HasOAuth2Key, HasTokenRequestClientAuthenticationMethod, HasUserInfoRequest, ToQueryParam, ExchangeTokenInfo, …
Instances8HasRefreshTokenRequest, HasTokenRequest, HasOAuth2Key, HasTokenRequestClientAuthenticationMethod, HasUserInfoRequest, ToQueryParam, …

Authorization Code

3 declarations

Device Authorization

3 declarations

Token Request

6 declarations

Associated types

Instances5HasTokenRequest
familydata family TokenRequest a
#
Instances10ToQueryParam, TokenRequest, …
familytype family ExchangeTokenInfo a
#
Instances5ExchangeTokenInfo
datadata NoNeedExchangeToken
#

Only Authorization Code Grant involves a Exchange Token (Authorization Code). ResourceOwnerPassword and Client Credentials make token request directly.

Refresh Token Request

2 declarations

UserInfo Request

0 declarations

Types

12 declarations
classclass HasOAuth2Key a where
#
Instances5HasOAuth2Key
datadata Idp (i :: k)
#

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

datadata IdpApplication (i :: k) a
#

An OAuth2 Application "a" of IdP "i". "a" can be one of following type:

  • Network.OAuth2.Experiment.AuthorizationCodeApplication

  • Network.OAuth2.Experiment.DeviceAuthorizationApplication

  • Network.OAuth2.Experiment.ClientCredentialsApplication

  • Network.OAuth2.Experiment.ResourceOwnerPasswordApplication

  • Network.OAuth2.Experiment.JwtBearerApplication

Constructors

newtypenewtype Scope
#

Constructors

Instances5Eq, Ord, Show, IsString, ToQueryParam
  • Eq ScopeDefined in hoauth2-2.14.3 · Network.OAuth2.Experiment.Types
  • Ord ScopeDefined in hoauth2-2.14.3 · Network.OAuth2.Experiment.Types
  • Show ScopeDefined in hoauth2-2.14.3 · Network.OAuth2.Experiment.Types
  • IsString ScopeDefined in hoauth2-2.14.3 · Network.OAuth2.Experiment.Types
  • ToQueryParam (Set Scope)Defined in hoauth2-2.14.3 · Network.OAuth2.Experiment.Types

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

Instances2Eq, Show

Utils

1 declaration