FullstackPhoenix

GitHub OAuth Login for Phoenix

phoenixoauthgithubueberauthauthentication

You ship a developer tool and 40 percent of visitors who open the signup form bounce before submitting. Asking a Phoenix developer to invent a new password for "yet another dev SaaS" is a friction point you cannot afford. A "Sign in with GitHub" button next to the email field is what closes the gap.

This feature installs GitHub OAuth on top of the existing Phoenix authentication generated by the authentication feature. It is not a replacement for password login — it is an additional path that links to the same users table by email.

Give developers a one-click sign-in path

GitHub OAuth is the de-facto "are you a developer" sign-in for this audience. The implementation matters: linking by email means a customer can sign in with either method without ending up with two accounts, and storing the OAuth identity in a separate table keeps the users table clean for the parts that need to be provider-agnostic.

What This Feature Adds

  • {:ueberauth, "~> 0.10.8"} and {:ueberauth_github, "~> 0.8.3"} added to mix.exs
  • Ueberauth configuration wiring the GitHub strategy
  • A MyApp.UserIdentities.UserIdentity schema with a generated migration linking OAuth identities to users by foreign key
  • A callback controller that finds the user by email, links the OAuth identity, and signs them in
  • Router entries for the OAuth request and callback routes
  • Tests covering the callback flow

How It Fits Into Your Phoenix Application

The OAuth callback runs after Ueberauth completes the upstream flow. It looks up an existing user by the email returned from GitHub, links a UserIdentity row for them, and signs them in using the same session machinery as the password flow. New users get a row in users plus a row in user_identities; existing users get an additional user_identities row without disturbing their existing record.

user = Users.get_user_with_identities(user_id)
github_identity = Enum.find(user.user_identities, &(&1.provider == "github"))

Because identities are linked by email, a user who originally signed up with a password and later uses "Sign in with GitHub" with the same email gets linked instead of duplicated.

Installation Notes

  • Required configuration: GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET in your environment. The feature does not generate the GitHub OAuth app for you — create one in the GitHub developer settings and copy the secrets in.
  • Hard dependency in practice: authentication. Without the user schema and session machinery from that feature, the callback has nothing to link into. The manifest does not declare it as a hard dependency, but the implementation assumes the generated users table.
  • Run mix ecto.migrate to create the user_identities table.
  • Extending to other providers (Google, GitLab) is a matter of adding the relevant ueberauth_* strategy package and a configuration line — the identity schema is provider-agnostic.

Build This With Live SaaS Kit

Install saas_kit, then mix saaskit.feature.install authentication followed by mix saaskit.feature.install oauth to ship the password flow and GitHub sign-in side by side.