1
1
mirror of https://github.com/aelve/guide.git synced 2024-11-22 11:33:34 +03:00

Add Oauth2 types

This commit is contained in:
Aaron Friel 2017-07-03 09:42:22 -05:00
parent 68d7ea2072
commit c1c6c3af55
6 changed files with 231 additions and 0 deletions

View File

@ -50,6 +50,9 @@ library
Guide.Session
Guide.Config
Guide.State
-- Guide.Auth.Oauth2
-- Guide.Auth.Oauth2.Github
-- Guide.Auth.Oauth2.Google
Guide.Types
Guide.Types.Hue
Guide.Types.Core
@ -57,6 +60,10 @@ library
Guide.Types.Action
Guide.Types.User
Guide.Types.Session
Guide.Types.Oauth2
Guide.Types.Oauth2.Config
Guide.Types.Oauth2.Github
Guide.Types.Oauth2.Google
Guide.Handlers
Guide.Utils
Guide.Diff
@ -111,6 +118,7 @@ library
, haskell-src-meta
, http-api-data
, http-types
, hoauth2 == 0.5.*
, hvect
, ilist
, iproute == 1.7.*

View File

@ -27,6 +27,7 @@ import Data.Default
import Guide.Utils
import qualified Guide.Types.Oauth2 as Oauth2
-- | Site config. Stored in @config.json@.
data Config = Config {
@ -36,6 +37,7 @@ data Config = Config {
_googleToken :: Text, -- ^ Google site verification token. Will
-- be inserted into all pages
_adminPassword :: Text, -- ^ Password for the admin user
_githubOauthConfig :: [Oauth2.GithubEndpoint],
_prerender :: Bool, -- ^ Whether to prerender all pages when
-- the app is started
_discussLink :: Maybe Url -- ^ Link to a place to discuss the site.
@ -50,6 +52,7 @@ instance Default Config where
_baseUrl = "/",
_googleToken = "",
_adminPassword = "",
_githubOauthConfig = [Oauth2.oauth2def "/"],
_prerender = False,
_discussLink = Nothing }

19
src/Guide/Types/Oauth2.hs Normal file
View File

@ -0,0 +1,19 @@
{- |
Module  : Guide.Types.Oauth2
Description : Oauth2 data definitions
Copyright  : (c) Aaron Friel
License  : BSD-3
Maintainer  : Aaron Friel <mayreply@aaronfriel.com>
Stability  : unstable
Portability : portable
-}
module Guide.Types.Oauth2
(
module X
) where
import Guide.Types.Oauth2.Config as X
import Guide.Types.Oauth2.Github as X

View File

@ -0,0 +1,97 @@
{- |
Module  : Guide.Types.Oauth2.Config
Description : Oauth2 data definitions
Copyright  : (c) Aaron Friel
License  : BSD-3
Maintainer  : Aaron Friel <mayreply@aaronfriel.com>
Stability  : unstable
Portability : portable
-}
{-# LANGUAGE OverloadedStrings #-}
module Guide.Types.Oauth2.Config where
import Imports
-- acid-state
import Data.SafeCopy hiding (kind)
import Guide.SafeCopy
import Guide.Utils
import Guide.Types.User
-- Aeson
import Data.Aeson
import Data.Aeson.Encode.Pretty
-- ByteString
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
-- Default
import Data.Default
-- | Configuration details to access an endpoint.
--
-- Intended to be used in a config file.
--
-- See note [Oauth2 workflow]
data Oauth2Endpoint = Oauth2Endpoint {
_endpointName :: Text, -- ^ A unique name for the Oauth2 endpoint.
_endpointClientId :: Text, -- ^ The client ID for the Oauth2 endpoint.
_endpointClientSecret :: Text, -- ^ The client secret for the Oauth2 endpoint.
_endpointAuthorize :: Url, -- ^ The endpoint authorization URL, clients are redirected
-- to this URL to begin the Oauth2 workflow.
_endpointCallback :: Url, -- ^ The server callback URL, after logging in at the authorize URL
-- the client is redirected to this server-controlled URL to provide
-- the server with a
_endpointAccessToken :: Url -- ^ The endpoint access token URL, once the app receives a
-- authorization code, this endpoint may be used to obtain
-- a longer-lived access token for an API.
}
deriving (Eq, Show)
makeClassy ''Oauth2Endpoint
class Oauth2Default t where
oauth2def :: Url -> t
instance Oauth2Default Oauth2Endpoint where
oauth2def baseUrl = Oauth2Endpoint {
_endpointName = "",
_endpointClientId = "",
_endpointClientSecret = "",
_endpointAuthorize = "",
_endpointAccessToken = "",
_endpointCallback = baseUrl // "auth" // "oauth2" // "callback"
}
-- oauth2login :: t ->
{- Note [Oauth2 workflow]
Terms:
* Endpoint: the third party authentication/authorization service.
* Server: this application (the Aelve Guide)
* Client: the user agent accessing the application (e.g.: web browser, API
client)
One of the better sources on authentication workflow is Google's:
https://developers.google.com/identity/protocols/OAuth2
Every OAuth2 provider is free to add additional parameters, so a general OAuth2
flow isn't possible. We use type classes and the `microlens` function
'makeClassy' to create type classes as such:
class HasOauth2Endpoint t where endpointName :: ...
instance HasOauth2Endpoint Oauth2Endpoint where
...
Each instance of an Oauth2 endpoint then will contain a Oauth2Endpoint field,
and implement the above type classes.
-}

View File

@ -0,0 +1,52 @@
{- |
Module  : Guide.Types.Oauth2.Github
Description : Github Oauth2 authentication parameters & workflow.
Copyright  : (c) Aaron Friel
License  : BSD-3
Maintainer  : Aaron Friel <mayreply@aaronfriel.com>
Stability  : unstable | experimental | provisional | stable | frozen
Portability : portable | non-portable (<reason>)
-}
{-# LANGUAGE OverloadedStrings #-}
module Guide.Types.Oauth2.Github where
import Imports
-- acid-state
import Data.SafeCopy hiding (kind)
import Guide.SafeCopy
import Guide.Utils
import Guide.Types.User
-- Aeson
import Data.Aeson
import Data.Aeson.Encode.Pretty
-- ByteString
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
-- Default
import Guide.Types.Oauth2.Config
-- | Github authentication details
data GithubEndpoint = GithubEndpoint {
_githubEndpointConfig :: Oauth2Endpoint
}
deriving (Eq, Show)
makeClassy ''GithubEndpoint
instance Oauth2Default GithubEndpoint where
oauth2def baseUrl = GithubEndpoint {
_githubEndpointConfig = (oauth2def baseUrl) {
_endpointName = "Github",
_endpointAuthorize = "http://github.com/login/oauth/authorize",
_endpointAccessToken = "https://github.com/login/oauth/access_token"
}
}
instance HasOauth2Endpoint GithubEndpoint where
oauth2Endpoint = githubEndpointConfig

View File

@ -0,0 +1,52 @@
{- |
Module  : Guide.Types.Oauth2.Google
Description : Google Oauth2 authentication parameters & workflow.
Copyright  : (c) Aaron Friel
License  : BSD-3
Maintainer  : Aaron Friel <mayreply@aaronfriel.com>
Stability  : unstable | experimental | provisional | stable | frozen
Portability : portable | non-portable (<reason>)
-}
{-# LANGUAGE OverloadedStrings #-}
module Guide.Types.Oauth2.Google where
import Imports
-- acid-state
import Data.SafeCopy hiding (kind)
import Guide.SafeCopy
import Guide.Utils
import Guide.Types.User
-- Aeson
import Data.Aeson
import Data.Aeson.Encode.Pretty
-- ByteString
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
-- Default
import Guide.Types.Oauth2.Config
-- | Google authentication details
data GoogleEndpoint = GoogleEndpoint {
_googleEndpointConfig :: Oauth2Endpoint
}
deriving (Eq, Show)
makeClassy ''GoogleEndpoint
instance Oauth2Default GoogleEndpoint where
oauth2def baseUrl = GoogleEndpoint {
_googleEndpointConfig = (oauth2def baseUrl) {
_endpointName = "Google",
_endpointAuthorize = "https://accounts.google.com/o/oauth2/v2/auth",
_endpointAccessToken = "https://www.googleapis.com/oauth2/v4/token"
}
}
instance HasOauth2Endpoint GoogleEndpoint where
oauth2Endpoint = googleEndpointConfig