freckle / yesod-auth-oauth2

OAuth2 authentication for yesod
MIT License
71 stars 53 forks source link

redirect_uri_mismatch - Server error 400 - Google Oauth2 #76

Closed mohamedhayibor closed 6 years ago

mohamedhayibor commented 7 years ago

I feel like like, I am missing a little something to get this to work. Tweaked the example for google:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}

module Main where

import Data.Monoid ((<>))
import Data.Text (Text)
import LoadEnv
import Network.HTTP.Conduit
import Network.Wai.Handler.Warp (runEnv)
import System.Environment
import Yesod
import Yesod.Auth
import Yesod.Auth.OAuth2.Google

import qualified Data.Text as T

data OAuthKeys = OAuthKeys
    { oauthKeysClientId :: Text
    , oauthKeysClientSecret :: Text
    }

loadOAuthKeysEnv :: String -> IO OAuthKeys
loadOAuthKeysEnv prefix = OAuthKeys
    <$> (getEnvT $ prefix <> "_CLIENT_ID")
    <*> (getEnvT $ prefix <> "_CLIENT_SECRET")

    where
      getEnvT = fmap T.pack .getEnv

data App = App
    { appHttpManager :: Manager
    , appGoogleKeys  :: OAuthKeys
    }

mkYesod "App" [parseRoutes|
/ HomeR GET
/auth AuthR Auth getAuth
|]

instance Yesod App where
    -- redirect_uri >> mismatch error
    approot = ApprootStatic "http://localhost:3000"

instance YesodAuth App where
    type AuthId App = Text
    loginDest _ = HomeR
    logoutDest _ = HomeR

    -- Disable any attempt to read persisted authenticated state
    maybeAuthId = return Nothing

    -- Copy the creds response into the session for viewing after
    authenticate c = do
        mapM_ (uncurry setSession) $
            [ ("credsIdent", credsIdent c)
            , ("credsPlugin", credsPlugin c)
            ] ++ credsExtra c

        return $ Authenticated "1"

    authHttpManager = appHttpManager

    authPlugins m =
        [ oauth2Google
            (oauthKeysClientId $ appGoogleKeys m)
            (oauthKeysClientId $ appGoogleKeys m)
        ]

instance RenderMessage App FormMessage where
    renderMessage _ _ = defaultFormMessage

getHomeR :: Handler Html
getHomeR = do
    sess <- getSession

    defaultLayout [whamlet|
        <h1>Yesod Auth OAuth2 Example
        <h2>
            <a href=@{AuthR LoginR}>Log in
        <h2> Session information
        <pre style="word-wrap: break-word;">
            #{show sess}
    |]

mkFoundation :: IO App
mkFoundation = do
    loadEnv

    appHttpManager <- newManager tlsManagerSettings
    appGoogleKeys <- loadOAuthKeysEnv "GOOGLE"

    return App {..}

main :: IO()
main = runEnv 3000 =<< toWaiApp =<< mkFoundation
pbrisbin commented 6 years ago

I've just tested this via #101 and it's working fine. I did have to fix a bug around the scope parameter, but that doesn't seem to be what you're running into.

Can you try pulling that branch, adding your keys to .env and testing again?

pbrisbin commented 6 years ago

After thinking a bit more, I remembered what causes this. It's easy to get the redirect URI wrong in the OAuth2 application setup. Please make sure it's correct:

https://console.developers.google.com/apis/credentials

I'm going to go ahead and close this optimistically. Feel free to re-open if things match and it's still not working. (And if #101 hasn't merged yet, please use that branch for testing.)