Support echo server to test POST /verify

TL;DR:
- Add common dependencies like Servant, Aeson, Warp, Cors
- Define a POST /verify endpoint for our client to hit
- POST to /verify client-side onSignIn
This commit is contained in:
William Carroll 2020-08-06 22:21:30 +01:00
parent 1fc1087014
commit a7ddb56b9b
5 changed files with 79 additions and 8 deletions

View file

@ -5,8 +5,12 @@ in pkgs.mkShell {
elmPackages.elm
elmPackages.elm-format
elmPackages.elm-live
(haskellPackages.ghcWithPackages (hpkgs: with hpkgs; [
hspec
(haskellPackages.ghcWithPackages (hpkgs: [
hpkgs.hspec
hpkgs.servant-server
hpkgs.aeson
hpkgs.wai-cors
hpkgs.warp
]))
];
}

View file

@ -0,0 +1,15 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
--------------------------------------------------------------------------------
module API where
--------------------------------------------------------------------------------
import Data.Text
import Servant.API
import Web.Cookie
import qualified Types as T
--------------------------------------------------------------------------------
type API = "verify"
:> ReqBody '[JSON] T.VerifyGoogleSignInRequest
:> Post '[JSON] NoContent

View file

@ -1,6 +1,35 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RecordWildCards #-}
--------------------------------------------------------------------------------
module Main where
--------------------------------------------------------------------------------
import Servant
import API
import Control.Monad.IO.Class (liftIO)
import qualified Network.Wai.Handler.Warp as Warp
import qualified Network.Wai.Middleware.Cors as Cors
import qualified Types as T
--------------------------------------------------------------------------------
server :: Server API
server = verifyGoogleSignIn
where
verifyGoogleSignIn :: T.VerifyGoogleSignInRequest -> Handler NoContent
verifyGoogleSignIn T.VerifyGoogleSignInRequest{..} = do
liftIO $ putStrLn $ "Received: " ++ idToken
pure NoContent
main :: IO ()
main = putStrLn "Working!"
main = do
Warp.run 3000 (enforceCors $ serve (Proxy @ API) $ server)
where
enforceCors = Cors.cors (const $ Just corsPolicy)
corsPolicy :: Cors.CorsResourcePolicy
corsPolicy =
Cors.simpleCorsResourcePolicy
{ Cors.corsOrigins = Just (["http://localhost:8000"], True)
, Cors.corsMethods = Cors.simpleMethods ++ ["PUT", "PATCH", "DELETE", "OPTIONS"]
, Cors.corsRequestHeaders = Cors.simpleHeaders ++ ["Content-Type", "Authorization"]
}

View file

@ -0,0 +1,16 @@
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedStrings #-}
--------------------------------------------------------------------------------
module Types where
--------------------------------------------------------------------------------
import Data.Aeson
--------------------------------------------------------------------------------
data VerifyGoogleSignInRequest = VerifyGoogleSignInRequest
{ idToken :: String
} deriving (Eq, Show)
instance FromJSON VerifyGoogleSignInRequest where
parseJSON = withObject "" $ \x -> do
idToken <- x .: "idToken"
pure VerifyGoogleSignInRequest{..}

View file

@ -11,11 +11,18 @@
<a href="#" onclick="signOut();">Sign out</a>
<script>
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
console.log('Name: ' + profile.getName());
console.log('Image URL: ' + profile.getImageUrl());
console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
var idToken = googleUser.getAuthResponse().id_token;
fetch('http://localhost:3000/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
idToken: idToken,
})
})
.then(x => console.log(x))
.catch(err => console.error(err));
}
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();