OAuth 2.0 authentication plugins.
Library to authenticate with OAuth 2.0 for Yesod web applications.
Yesod.Auth.OAuth2
OAuth2 AuthPlugin
s for Yesod.
Usage
import Yesod.Auth
import Yesod.Auth.OAuth2.GitHub
instance YesodAuth App where
-- ...
authPlugins _ = [oauth2GitHub clientId clientSecret]
clientId :: Text
clientId = "..."
clientSecret :: Text
clientSecret = "..."
Some plugins, such as GitHub and Slack, have scoped functions for requesting additional information:
oauth2SlackScoped [SlackBasicScope, SlackEmailScope] clientId clientSecret
Working with Extra Data
We put the minimal amount of user data possible in credsExtra
-- just enough to support you parsing or fetching additional data yourself.
For example, if you work with GitHub and GitHub user profiles, you likely already have a model and a way to parse the /user
response. Rather than duplicate all that in our library, we try to make it easy for you to re-use that code yourself:
authenticate creds = do
let
-- You can run your own FromJSON parser on the response we already have
eGitHubUser :: Either String GitHubUser
eGitHubUser = getUserResponseJSON creds
-- Avert your eyes, simplified example
Just accessToken = getAccessToken creds
Right githubUser = eGitHubUser
-- Or make followup requests using our access token
runGitHub accessToken $ userRepositories githubUser
-- Or store it for later
insert User
{ userIdent = credsIdent creds
, userAccessToken = accessToken
}
NOTE: Avoid looking up values in credsExtra
yourself; prefer the provided get
functions. The data representation itself is no longer considered public API.
Local Providers
If we don't supply a "Provider" (e.g. GitHub, Google, etc) you need, you can write your own using our provided Prelude
:
import Yesod.Auth.OAuth2.Prelude
pluginName :: Text
pluginName = "mysite"
oauth2MySite :: YesodAuth m => Text -> Text -> AuthPlugin m
oauth2MySite clientId clientSecret =
authOAuth2 pluginName oauth2 $ \manager token -> do
-- Fetch a profile using the manager and token, leave it a ByteString
userResponse <- -- ...
-- Parse it to your preferred identifier, e.g. with Data.Aeson
userId <- -- ...
-- See authGetProfile for the typical case
pure Creds
{ credsPlugin = pluginName
, credsIdent = userId
, credsExtra = setExtra token userResponse
}
where
oauth2 = OAuth2
{ oauth2ClientId = clientId
, oauth2ClientSecret = Just clientSecret
, oauth2AuthorizeEndpoint = "https://mysite.com/oauth/authorize"
, oauth2TokenEndpoint = "https://mysite.com/oauth/token"
, oauth2RedirectUri = Nothing
}
The Prelude
module is considered public API, though we may build something higher-level that is more convenient for this use-case in the future.
Development & Tests
stack setup
stack build --dependencies-only
stack build --pedantic --test
Please also run HLint and Weeder before submitting PRs.
Example
This project includes an executable that runs a server with (almost) all supported providers present.
To use:
cp .env.example .env
and edit in secrets for providers you wish to testBe sure to include
http://localhost:3000/auth/page/{plugin}/callback
as a valid Redirect URI when configuring the OAuth application.Build with the example:
stack build ... --flag yesod-auth-oauth2:example
Run the example
stack exec yesod-auth-oauth2-example
Visit the example:
$BROWSER http://localhost:3000
Click the log-in link for the provider you configured
If successful, you will be presented with a page that shows the credential and User response value.