I am using Obelisk OAuth to handle multiple OAuth options (Facebook, Google, & Apple, though only FB is shown below).
I have getOAuthDetails
which gets the correct details for each provider.
I use it in backend
(at the bottom), but it gives me this error:
backend/src/Backend.hs:144:47-54: error:
• Couldn't match expected type ‘OAuthProvider’
with actual type ‘OAuth a1’
• In the first argument of ‘getOAuthDetails’, namely ‘provider’
In the expression: getOAuthDetails provider code
In a pattern binding: (t, reqUrl) = getOAuthDetails provider code
• Relevant bindings include
oauthRoute :: a1 (bound at backend/src/Backend.hs:140:41)
provider :: OAuth a1 (bound at backend/src/Backend.hs:140:29)
|
144 | let (t, reqUrl) = getOAuthDetails provider code
| ^^^^^^^^
This error is confusing to me because I am explicitly feeding in OAuthProvider
as provider
in that function. Why would it then say actual type ‘OAuth a1’
?
data OAuthProvider = OAuthProvider_Facebook
| OAuthProvider_Google
| OAuthProvider_Apple
getOAuthDetails :: OAuthProvider -> T.Text -> (TokenRequest BackendRoute, String) -- NB. this last T.Text is a reqUrl
getOAuthDetails OAuthProvider_Facebook code = (fbTokenReq code, (T.unpack fbReqUrl))
getOAuthDetails OAuthProvider_Google code = (googTokenReq code, (T.unpack googReqUrl))
getOAuthDetails OAuthProvider_Apple code = (applTokenReq code, (T.unpack applReqUrl))
fbTokenReq :: T.Text -> TokenRequest BackendRoute
fbTokenReq code = TokenRequest
{ _tokenRequest_grant = TokenGrant_AuthorizationCode $ T.encodeUtf8 code
, _tokenRequest_clientId = "fake-client-id" -- Get this from the OAuth authorization server
, _tokenRequest_clientSecret = "fake-client-secret" -- Get this from the OAuth authorization server
, _tokenRequest_redirectUri = BackendRoute_OAuth
}
fbReqUrl :: T.Text
fbReqUrl = "https://graph.facebook.com/oauth/access_token"
...
-- provider2Auth :: OAuthProvider -> OAuth RedirectUriParams
-- provider2Auth
backend :: OAuthProvider -> Backend BackendRoute FrontendRoute
backend provider = Backend
{ _backend_run = \serve -> do
cfg <- getConfigs
let route = T.strip $ T.decodeUtf8 $ cfg ! "common/route"
tlsMgr <- Https.newTlsManager
serve $ \case
BackendRoute_Missing :/ () -> error "404"
BackendRoute_OAuth :/ provider :/ oauthRoute -> case oauthRoute of
OAuth_RedirectUri :/ redirectParams -> case redirectParams of
Nothing -> liftIO $ error "Expected to receive the authorization code here"
Just (RedirectUriParams code _mstate) -> do
let (t, reqUrl) = getOAuthDetails provider code
rsp <- liftIO $ flip Http.httpLbs tlsMgr =<< getOauthToken reqUrl route checkedEncoder t
-- ^ this response should include the access token and probably a refresh token
liftIO $ print rsp
, _backend_routeEncoder = fullRouteEncoder
}
EDIT:
ob run
displayed this:
backend/src/Backend.hs:140:9-43: error:
• Could not deduce: a1 ~ R OAuth
from the context: a ~ Data.Dependent.Sum.DSum OAuth Identity
bound by a pattern with constructor:
BackendRoute_OAuth :: BackendRoute (R OAuth),
in a case alternative
at backend/src/Backend.hs:139:7-24
‘a1’ is a rigid type variable bound by
a pattern with pattern synonym:
:/ :: forall (f :: * -> *). () => forall a. f a -> a -> R f,
in a case alternative
at backend/src/Backend.hs:139:7-36
• In the pattern: OAuth_RedirectUri :/ redirectParams
In a case alternative:
OAuth_RedirectUri :/ redirectParams
-> case redirectParams of
Nothing
-> liftIO $ error "Expected to receive the authorization code here"
Just (RedirectUriParams code _mstate)
-> do let ...
....
In the expression:
case oauthRoute of {
OAuth_RedirectUri :/ redirectParams
-> case redirectParams of
Nothing
-> liftIO $ error "Expected to receive the authorization code here"
Just (RedirectUriParams code _mstate) -> do ... }
• Relevant bindings include
oauthRoute :: a1 (bound at backend/src/Backend.hs:139:41)
provider :: OAuth a1 (bound at backend/src/Backend.hs:139:29)
|
140 | OAuth_RedirectUri :/ redirectParams -> case redirectParams of
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend/src/Backend.hs:143:47-54: error:
• Couldn't match expected type ‘OAuthProvider’
with actual type ‘OAuth a1’
• In the first argument of ‘getOAuthDetails’, namely ‘provider’
In the expression: getOAuthDetails provider code
In a pattern binding: (t, reqUrl) = getOAuthDetails provider code
• Relevant bindings include
oauthRoute :: a1 (bound at backend/src/Backend.hs:139:41)
provider :: OAuth a1 (bound at backend/src/Backend.hs:139:29)
|
143 | let (t, reqUrl) = getOAuthDetails provider code
| ^^^^^^^^
Thanks to Srid, I saw that I had two provider
s. I modified my backend
to:
backend :: OAuthProvider -> Backend BackendRoute FrontendRoute
backend provider = Backend
{ _backend_run = \serve -> do
cfg <- getConfigs
let route = T.strip $ T.decodeUtf8 $ cfg ! "common/route"
tlsMgr <- Https.newTlsManager
serve $ \case
BackendRoute_Missing :/ () -> error "404"
BackendRoute_OAuth :/ oauthRoute -> case oauthRoute of
OAuth_RedirectUri :/ redirectParams -> case redirectParams of
Nothing -> liftIO $ error "Expected to receive the authorization code here"
Just (RedirectUriParams code _mstate) -> do
let (t, reqUrl) = getOAuthDetails provider code
rsp <- liftIO $ flip Http.httpLbs tlsMgr =<< getOauthToken reqUrl route checkedEncoder t
-- ^ this response should include the access token and probably a refresh token
liftIO $ print rsp
, _backend_routeEncoder = fullRouteEncoder
}
And now I get:
Running test...
<interactive>:623:116-130: error:
• Couldn't match expected type ‘Backend
backendRoute0 FrontendRoute’
with actual type ‘OAuthProvider
-> Backend BackendRoute FrontendRoute’
• Probable cause: ‘backend’ is applied to too few arguments
In the third argument of ‘Obelisk.Run.run’, namely ‘backend’
In the expression:
Obelisk.Run.run
55245
(Obelisk.Run.runServeAsset
"/Users/levelchart/Documents/git/app-obelisk/static")
backend
Frontend.frontend
In an equation for ‘it’:
it
= Obelisk.Run.run
55245
(Obelisk.Run.runServeAsset
"/Users/levelchart/Documents/git/app-obelisk/static")
backend
Frontend.frontend