packages feed

hoauth2-providers-0.2: src/Network/OAuth2/Provider/Auth0.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}

-- | https://auth0.com/docs/api/authentication#authorize-application
module Network.OAuth2.Provider.Auth0 where

import Control.Monad.IO.Class
import Control.Monad.Trans.Except
import Data.Aeson
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Data.Text.Lazy (Text)
import GHC.Generics
import Network.OAuth.OAuth2
import Network.OAuth2.Experiment
import Network.OIDC.WellKnown
import URI.ByteString.QQ

data Auth0 = Auth0
  deriving (Show, Eq)

type instance IdpUserInfo Auth0 = Auth0User

defaultAuth0App :: Idp Auth0 -> IdpApplication 'AuthorizationCode Auth0
defaultAuth0App i =
  AuthorizationCodeIdpApplication
    { idpAppClientId = ""
    , idpAppClientSecret = ""
    , idpAppScope = Set.fromList ["openid", "profile", "email", "offline_access"]
    , idpAppAuthorizeState = "CHANGE_ME"
    , idpAppAuthorizeExtraParams = Map.empty
    , idpAppRedirectUri = [uri|http://localhost|]
    , idpAppName = "default-auth0-App"
    , idpAppTokenRequestAuthenticationMethod = ClientSecretBasic
    , idp = i
    }

defaultAuth0Idp :: Idp Auth0
defaultAuth0Idp =
  Idp
    { idpFetchUserInfo = authGetJSON @(IdpUserInfo Auth0)
    , --  https://auth0.com/docs/api/authentication#user-profile
      idpUserInfoEndpoint = [uri|https://foo.auth0.com/userinfo|]
    , -- https://auth0.com/docs/api/authentication#authorization-code-flow
      idpAuthorizeEndpoint = [uri|https://foo.auth0.com/authorize|]
    , -- https://auth0.com/docs/api/authentication#authorization-code-flow44
      idpTokenEndpoint = [uri|https://foo.auth0.com/oauth/token|]
    }

mkAuth0Idp ::
  MonadIO m =>
  -- | Full domain with no http protocol. e.g. @foo.auth0.com@
  Text ->
  ExceptT Text m (Idp Auth0)
mkAuth0Idp domain = do
  OpenIDConfigurationUris {..} <- fetchWellKnownUris domain
  pure
    ( defaultAuth0Idp
        { idpUserInfoEndpoint = userinfoUri
        , idpAuthorizeEndpoint = authorizationUri
        , idpTokenEndpoint = tokenUri
        }
    )

-- | https://auth0.com/docs/api/authentication#user-profile
data Auth0User = Auth0User
  { name :: Text
  , email :: Text
  , sub :: Text
  }
  deriving (Show, Generic)

instance FromJSON Auth0User