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_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 (
screen_name) and set it on the session as
We also store the
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.
AssignCurrentUser, just allows us to access
conn.assigns.current_user instead of having to do
get_session(conn, :current_user) every time.
RequireUser allows us to limit certain controller actions to only be available to signed in users.
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.