Open-source project
ueberauth/ueberauth avatar
ueberauth/ueberauth

Überauth and the Two-Phase Authentication Flow in Plug Applications

An Elixir Authentication System for Plug-based Web Applications

1,718 stars121 forksElixirMIT

At a glance

What is it?
Überauth is an Elixir framework for handling the initial authentication challenge in Plug-based applications. It coordinates request and callback phases, but application code must still create or locate users and maintain authenticated sessions.
Who is it for?
Application teams using Elixir and Plug should consider Überauth when they need a shared strategy interface for OAuth or form-based login challenges. Teams expecting a complete session or authorization system should choose a solution such as Guardian or the authentication generated by `mix phx.gen.auth` instead.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 12 days ago.
What is it written in?
Mainly Elixir, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Überauth Solves in a Plug Authentication Stack

Überauth addresses the entry point of authentication, not the full lifecycle of an authenticated request. Its README describes it as a two-phase framework that gives applications a common API for login strategies and is most often used with third-party identity providers. The intended audience is Elixir developers building Plug-based web applications, including Phoenix applications that need to combine OAuth with locally managed users.

The boundary matters. Überauth can initiate an OAuth authorization request, collect information from a login form, process the provider callback, and prepare either a `Ueberauth.Auth` or `Ueberauth.Failure` result. It does not authenticate every later request. The application remains responsible for deciding whether an existing user matches the returned identity, creating a database record, placing a user identifier in the session, renewing the session, and rejecting unauthenticated access.

This division makes Überauth useful as an adapter layer. A GitHub OAuth strategy, for example, can normalize provider-specific behavior while the application keeps ownership of its account schema and session policy. The README also says the framework integrates with `mix phx.gen.auth`; alternatively, an application can use Guardian for request authentication. Überauth therefore fits between an identity challenge and the application's established account and session mechanism.

The README also positions Überauth as an Elixir framework inspired by OmniAuth, while noting that its operation differs. It is not presented as a general policy engine for permissions, roles, or per-request authorization.

Überauth Request, Callback, and Plug Data Flow

Überauth models authentication as two plug-mediated phases. Strategies are plugs that decorate or intercept requests, and each strategy may implement either or both phases depending on its requirements.

In the request phase, the selected strategy receives `handle_request!`. An OAuth strategy can stop processing and redirect the user to the provider's authorization URL. A form-based strategy can let the request continue so the host application can display fields such as an email address and password. The request phase is concerned with collecting information, not deciding what should happen after that information has been collected.

Once the provider or local form is complete, it calls the callback URL. The strategy intercepts that request through `handle_callback!`. On success, it prepares the connection for creation of a `Ueberauth.Auth` struct. On failure, it places error information for a `Ueberauth.Failure` result. The application controller then handles both cases explicitly.

For OAuth, the path is therefore:

`request route` to `Ueberauth.Strategy.Github` to `GitHub OAuth page` to `callback route` to `handle_callback!` to `Ueberauth.Auth` to application user creation.

This flow does not remove the need for route-level validation, user matching, session management, or authorization checks. It defines an interface around the initial challenge. A strategy that does not redirect may also decorate the request with Überauth information and allow downstream plugs to continue the pipeline.

Installing the GitHub Strategy in a Phoenix Application

The README's Phoenix walkthrough begins by creating an application setup at GitHub Developer and choosing a strategy. It then uses the GitHub strategy as the concrete provider. Add the documented dependency to `mix.exs`:

elixir
def deps do
  [
    {:ueberauth_github, "~> 0.8"}
  ]
end

This is a library dependency rather than a standalone executable. The README does not provide a separate installation command for Überauth itself in this walkthrough.

Next, register GitHub as a provider in the Überauth configuration:

elixir
config :ueberauth, Ueberauth,
  providers: [
    github: {Ueberauth.Strategy.Github, []}
  ]

The provider configuration belongs in `config/runtime.exs`. The documented values are read from the `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET` environment variables:

elixir
config :ueberauth, Ueberauth.Strategy.Github.OAuth,
  client_id: System.get_env("GITHUB_CLIENT_ID"),
  client_secret: System.get_env("GITHUB_CLIENT_SECRET")

The README does not document how those environment variables are populated, so their host or deployment configuration must be handled separately. At this point, the application has the core provider registration and provider credentials, but it still needs routes and controller logic to complete a usable login flow.

Wiring Phoenix Request and Callback Routes

The documented Phoenix router creates two browser-facing routes under `/auth`. The first begins the request phase, while the second receives the provider callback:

elixir
scope "/auth", MyAppWeb do
  pipe_through :browser

  get "/:provider", AuthController, :request
  get "/:provider/callback", AuthController, :callback
end

The request route must be reachable through the configured strategy. For the GitHub OAuth example, that means initiating a request through Überauth so the strategy can redirect to GitHub. The callback route must match the callback expected by that provider's OAuth configuration.

The controller uses `plug Ueberauth`, which gives the controller access to the framework's request and callback handling. The README's controller example demonstrates the two result structs the application must account for: `%Ueberauth.Auth{}` for success and `%Ueberauth.Failure{}` for failure.

A small implementation detail can affect sign-in behavior. The documented success path calls `MyAppWeb.UserAuth.log_in_user(conn, user)` when the application uses `mix phx.gen.auth`. If it does not, the example renews the session, stores `user.id` under the `:user_id` session key, and redirects to the root route. Those are application responsibilities, not hidden behavior supplied by the strategy.

The README does not show the full request action or the implementation of `create_user_from_ueberauth!`. Those pieces remain application-specific rather than being copied from the provider integration.

Handling Ueberauth.Auth and Ueberauth.Failure

The callback controller has two concrete branches. The failure branch recognizes `%Ueberauth.Failure{}`, places an error flash message, and redirects away from the failed callback:

elixir
def callback(%{assigns: %{ueberauth_failure: %Ueberauth.Failure{}}} = conn, _params) do
  conn
  |> put_flash(:error, "Failed to authenticate")
  |> redirect(to: ~p"/")
end

The success branch recognizes `%Ueberauth.Auth{}` and passes that struct into application code responsible for creating a user. The README uses `MyApp.Accounts.create_user_from_ueberauth!(auth)` for that conversion. This is the point where provider data becomes a local account, and the framework does not prescribe how duplicate accounts, provider identifiers, profile fields, or transaction failures should be handled.

The success branch then delegates session establishment to `MyAppWeb.UserAuth.log_in_user/2` when using `mix phx.gen.auth`:

elixir
def callback(%{assigns: %{ueberauth_auth: %Ueberauth.Auth{} = auth}} = conn, _params) do
  user = MyApp.Accounts.create_user_from_ueberauth!(auth)

  MyAppWeb.UserAuth.log_in_user(conn, user)
end

The bang in `create_user_from_ueberauth!` reflects the shown function name, but the README does not document its error behavior. An adopter would need to decide how provider callback failures, existing users, and database errors are surfaced instead of assuming the strategy covers them.

For applications without `mix phx.gen.auth`, the documented session branch is:

elixir
conn
|> renew_session()
|> put_session(:user_id, user.id)
|> redirect(to: ~p"/")

This sample establishes a local session, but it does not show subsequent request guards or logout behavior.

Strategy Extensibility and the Limits of Überauth's Scope

Überauth's strategy interface supports more than redirects. The framework can accommodate OAuth providers and simple email or password authentication, but each strategy decides whether it intercepts the request or allows it to continue. This makes the system flexible for local forms as well as third-party services, although the README excerpt does not document a built-in username and password strategy.

The framework also has clear limits. It supplies only the initial authentication challenge. It does not establish a policy for per-request authentication, session persistence, role checks, account provisioning, token storage, or logout. The README mentions Guardian and `mix phx.gen.auth` as integration points, which confirms that additional libraries or generated application code remain necessary.

A genuine failure mode is incomplete callback handling. If an application only treats successful `Ueberauth.Auth` values and ignores `Ueberauth.Failure`, the provider error path can disappear without a useful application response. Another boundary is provider configuration. Missing `GITHUB_CLIENT_ID` or `GITHUB_CLIENT_SECRET` values cannot be repaired by Überauth itself, because the README places responsibility for those environment variables in deployment configuration.

Überauth is also the wrong tool when the requirement is simply “keep this user logged in.” In that case, the complete request-level mechanism or generated authentication code described by the README may be sufficient without adopting a strategy framework. It is more relevant when one application needs a consistent plug interface across multiple identity flows.

Überauth Compared with Guardian and Phoenix Authentication

The clearest alternative named in the README is Guardian. Guardian is associated with authenticating requests, while Überauth is explicitly limited to the initial authentication challenge. Their approaches therefore occupy different layers. Überauth delegates to a strategy for request and callback processing; Guardian can own the continuing authentication layer used by a Phoenix application.

The second alternative is the code produced by `mix phx.gen.auth`. The README says Überauth integrates with those generators. Its GitHub example uses `MyAppWeb.UserAuth.log_in_user(conn, user)` when that generated authentication layer is present. This is not an interchangeable replacement for Überauth. It supplies application authentication behavior, while Überauth and `ueberauth_github` collect and normalize the provider challenge.

A team should therefore judge the projects by responsibility, not by treating them as competing authentication libraries. Use Überauth when the problem is coordinating multiple strategies or separating an OAuth callback from local account and session logic. Use Guardian or generated authentication code when the priority is the authenticated state of subsequent application requests. The documentation does not claim that Überauth replaces those layers.

Überauth Releases, MIT Licensing, and Upgrade Surface

The repository is not archived, and its last push was on 2026-10-11. The listed releases include `v0.11.0` on 2026-10-11, `v0.10.8` on 2024-02-27, and `v0.10.7` on 2024-01-04. These dates show a recent release after the earlier 2024 releases, but the README does not provide a detailed migration guide for the difference between those versions.

Überauth is distributed under the MIT license. The repository includes a `LICENSE` file and an MIT license badge in the README. The documentation does not add commercial restrictions or modify the stated terms. Applications should still account for the licenses and compatibility of the separately selected strategy, including `ueberauth_github`, because adding a strategy can introduce dependencies beyond the core framework.

The upgrade surface includes more than the core package version. A Phoenix application may have configuration for `Ueberauth`, provider registration for `Ueberauth.Strategy.Github`, environment-backed credentials, router phases, controller result patterns, and user-provisioning code. The README gives no rollback procedure and does not enumerate breaking changes, so those interfaces need checking against the selected strategy's documentation before upgrading. The repository's Makefile provides quality tasks including compilation, formatting checks, Credo, Coveralls, and Dialyzer, but it does not document a consumer upgrade command.

Editorial conclusion

Application teams using Elixir and Plug should consider Überauth when they need a shared strategy interface for OAuth or form-based login challenges. Teams expecting a complete session or authorization system should choose a solution such as Guardian or the authentication generated by `mix phx.gen.auth` instead. Before adoption, verify the selected strategy's configuration, callback behavior, failure handling, and how its `Ueberauth.Auth` data maps to the application's user model.

Frequently asked questions

Does Überauth authenticate every request after login?

No. Überauth handles the initial authentication challenge, while the application remains responsible for authenticating each request through its own session code or a library such as Guardian.

How are the request and callback phases different in Überauth?

The request phase collects information and may redirect to an OAuth provider or display a local form. The callback phase processes the returned information through `handle_callback!` and prepares a `Ueberauth.Auth` or `Ueberauth.Failure` result.

What must a Phoenix application implement after GitHub returns to the callback route?

It must handle `Ueberauth.Auth` and `Ueberauth.Failure`, convert the authentication data into a local user, and establish the session. The README uses `MyApp.Accounts.create_user_from_ueberauth!` and either `MyAppWeb.UserAuth.log_in_user/2` or its own session code as examples.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. ueberauth/ueberauth on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ueberauth-ueberauth.svg)](https://hysenlabs.com/projects/ueberauth-ueberauth)

Was this useful?