Twitter OAuth Authentication with Elixir and Phoenix
There are a few good examples showing how to use OAuth authentication in Phoenix and Elixir, but I wanted a solution which used a small amount of dependencies, and had the ability to make authenticated requests on behalf of a user.
parroty/extwitter provides the functionality to authenticate as a user, as well as to make requests on behalf of that user. I wanted to just use this library, and avoid adding the additional dependencies of ueberauth and guardian.
Full code is available at: https://github.com/steveklebanoff/twitter_oauth_example
Here’s a breakdown of some of the interesting parts:
We start off authenticating via twitter in the request
function. This generates and redirects the user to a URL which will prompt them to authorize our application via twitter.
If the user authorizes, they will be redirected to our callback
function with oauth information in the request parameters. We use ExTwitter
to generate an access token based on oauth_verifier
and oauth_token
which was provided by twitter as URL parameters. We then configure ExTwitter to use the access_token and access_token_secret we received. This allows us to make verified requests on behalf of this twitter user.
Now that we can make verified requests, we call verify_credentials
to ensure everything is kosher, and also to receive information about the user’s twitter account. We take a subset of that information (name
and screen_name
) and set it on the session as current_user
.
We also store the access_token
and access_token_secret
on the session, so we can make further authenticated requests later. At the time of writing, twitter does not expire these tokens. Because Phoenix uses Plug.Session.COOKIE, which is “based on Plug.Crypto.MessageVerifier and Plug.Crypto.Message.Encryptor which encrypts and signs each cookie to ensure they can’t be read nor tampered with”, we can feel confident that this information will be safe.
We define three plugs which help our controllers work. These plugs are similar to rails controller before_filter
in that they are executed before controller code.
The first, AssignCurrentUser
, just allows us to access current_user
through conn.assigns.current_user
instead of having to do get_session(conn, :current_user)
every time.
The second, RequireUser
allows us to limit certain controller actions to only be available to signed in users.
The third, ConfigureTwitterClient
sets up our ExTwitter client to have the user’s access_token and access_secret configured for any twitter API call made by a signed-in user.
With authentication already handled, and ConfigureTwitterClient
already setting up ExTwitter for authenticated users, the TweetController is very small and simple. It uses ExTwitter to grab a user’s timeline, and to post a new tweet.
Putting It All Together
You can run the app see how the whole thing comes together in the code published at steveklebanoff/twitter_oauth_example.
If you see anywhere in which the code could be improved, please holler at me in the comments here, or in a Github issue or PR.
Other Resources and Acknowledgements
ueberauth/ueberauth_twitter is an awesome example of how to do authentication via Twitter using ueberauth. That being said, it doesn’t provide functionality to make authenticated requests on behalf of a user, and if you use parroty/extwitter you don’t necessarily need the ueberauth dependency.
scrogson/oauth2_example has great examples on how to do OAuth 2 Authentication via a variety of providers, but it does not support Twitter which uses OAuth 1.
Thanks to cjlarose for taking some time to discuss the security aspects of storing OAuth tokens in cookies.
Thanks you got me up and running in ~3 minutes?
Looking forward to your next post :)
Thanks for putting dev.secrets.exs in .gitignore
#details
:)