hoauth2-2.6.0: Haskell OAuth2 authentication client
Safe HaskellSafe-Inferred
LanguageHaskell2010

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

  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) and more or less obsolete 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.

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.

Documentation