View Source Ueberauth (Überauth v0.10.8)

Ueberauth is a two-phase authentication framework that provides a clear API - allowing for many strategies to be created and shared within the community. It is heavily inspired by Omniauth. You could call it a port but it is significantly different in operation - but almost the same by concept. Huge hat tip to Intridea.

Ueberauth provides only the initial authentication challenge, (initial OAuth flow, collecting the information from a login form, etc). It does not authenticate each request, that's up to your application. You could issue a token or put the result into a session for your applications needs. Libraries like Guardian can help you with that aspect of authentication.

The two phases are request and callback. These phases are implemented by Strategies.

strategies

Strategies

Strategies are plugs that decorate or intercept requests (or both).

Strategies implement the two phases and then may allow the request to flow through to your downstream plugs. Implementing the request and callback phases is optional depending on the strategies requirements. If a strategy does not redirect, the request will be decorated with Ueberauth information and allowed to carry on through the pipeline.

request-phase

Request Phase

The request phase is where you request information about the user. This could be a redirect to an OAuth2 authorization url or a form for collecting username and password. The request phase is concerned with only the collection of information. When a request comes in on the request phase url the relevant strategy will receive the Ueberauth.Strategy.handle_request!/1 call.

In some cases (default) the application using Ueberauth is responsible for implementing the request phase. That is, you should setup a route to receive the request phase and provide a form etc. In some cases, like OAuth, the request phase is used to redirect your user to a 3rd party site to fulfill the request.

For example, an OAuth strategy for GitHub will receive the request phase url and stop the request, redirecting you to GitHub’s OAuth challenge url with some query parameters. Once you complete the GitHub OAuth flow, the user will be redirected back to the host site to the callback URL.

Another example is simple email/password authentication. A request is made by the client to the request phase path and the host application displays a form. The strategy will likely not do anything with the incoming Ueberauth.Strategy.handle_request!/1 request and simply pass through to the application. Once the form is completed, the POST should go to the callback url where it is handled (passwords checked, users created / authenticated).

callback-phase

Callback Phase

The callback phase is where the fun happens. Once a successful request phase has been completed, the request phase provider (OAuth provider or host site etc) should call the callback url. The strategy will intercept the request via the Ueberauth.Strategy.handle_callback!/1. If successful it should prepare the connection so the Ueberauth.Auth struct can be created, or set errors to indicate a failure.

See Ueberauth.Strategy for more information on constructing the Ueberauth.Auth struct.

setup

Setup

In your configuration file provide a list of the providers you intend to use.

Example

config :ueberauth, Ueberauth,
  providers: [
    facebook: {Ueberauth.Strategy.Facebook, [opt1: "value", opts2: "value"]},
    github: {Ueberauth.Strategy.Github, [opt1: "value", opts2: "value"]}
  ]

This will define two providers for you. The general structure of the providers value is:

config :ueberauth, Ueberauth,
  providers: [
    <provider name>: {<Strategy Module>, [<strategy options>]}
  ]

We use the configuration options for defining these to allow for dependency injection in different environments. The provider name will be used to construct request and response paths (by default) but will also be returned in the Ueberauth.Auth struct as the provider field.

Once you've setup your providers, in your router you need to configure the plug to run. The plug should run before your application routes.

In phoenix, plug this module in your controller:

defmodule MyApp.AuthController do
  use MyApp.Web, :controller
  plug Ueberauth

  ...
end

Its URL matching is done via pattern matching rather than explicit runtime checks so your strategies will only fire for relevant requests.

Now that you have this, your strategies will intercept relevant requests for each strategy for both request and callback phases. The default URLs are (for our Facebook & GitHub example)

# Request phase paths
/auth/facebook
/auth/github

# Callback phase paths
/auth/facebook/callback
/auth/github/callback

If you want to include only some of the providers with your plug you can specify a list of configured providers

defmodule MyApp.Admin.AuthController do
  use MyApp.Web, :controller
  plug Ueberauth, providers: [:identity], base_path: "/admin/auth"
end

This will allow you to have different login points in your application selectively using some or all of the providers.

Configuration of different Providers per OTP app

If you wish to use Ueberauth in multiple OTP apps, and configure each instance of Ueberauth with a different list of Providers, you will need to do some things differently. When providing configuration for Ueberauth, you should set anything that differs by OTP app under the name of your OTP app, for example:

config :my_app, Ueberauth,
  providers: [
    
  ]

Further, when using the Ueberauth plug, you should pass the :otp_app option, for example:

defmodule MyApp.Admin.AuthController do
  use MyApp.Web, :controller
  plug Ueberauth,
    otp_app: :my_app,
    providers: [:identity],
    base_path: "/admin/auth"
end

This ensures that in addition to globally configured values under :ueberauth, values set under your own namespace are used with priority.

Customizing Paths

These paths can be configured on a per strategy basis by setting options on the provider.

Note: These paths are absolute

Example

config :ueberauth, Ueberauth,
  base_path: "/login", # default is "/auth"
  providers: [
    identity: {Ueberauth.Strategies.Identity, [request_path: "/login/identity",
                                               callback_path: "/login/identity/callback"]}
  ],
  json_library: Poison # or Jason

Customizing Schemes

By default, Ueberauth uses your Plug.Conn scheme.

A custom scheme can be provided through the request header X-Forwarded-Proto.

For example, in Nginx you can set it.

proxy_set_header X-Forwarded-Proto $scheme;

Another option is to override this via options to your strategy.

providers: [
  identity: {Ueberauth.Strategies.Identity, [callback_scheme: "https"]}
]

Customizing Ports

By default, Ueberauth uses your Plug.Conn port.

To override this via options to your strategy.

providers: [
  identity: {Ueberauth.Strategies.Identity, [callback_port: 4000]}
]

Http Methods

By default, all callback URLs are only available via the "GET" method. You can override this via options to your strategy.

providers: [
  identity: {Ueberauth.Strategies.Identity, [callback_methods: ["POST"]]}
]

Strategy Options

All options that are passed into your strategy are available at runtime to modify the behaviour of the strategy.

Link to this section Summary

Functions

Fetch a successful auth from the Plug.Conn.

Fetch the configured JSON library.

Request authentication against a provider.

Request authentication against a provider.

Link to this section Types

@type method() :: String.t()
@type path() :: String.t()
@type route() :: {{path(), method()}, mfa()}
@type routes() :: [route()]

Link to this section Functions

@spec auth(Plug.Conn.t()) :: Ueberauth.Auth.t()

Fetch a successful auth from the Plug.Conn.

This should only be called after the callback phase has run.

Implements Plug.call/2

Implements Plug.init/1

Link to this function

json_library(otp_app \\ nil)

View Source

Fetch the configured JSON library.

A JSON library is required for Ueberauth to operate.

In config.exs your implicit or explicit configuration is:

config :ueberauth, Ueberauth, json_library: Jason

Or:

config :ueberauth, json_library: Jason

If you are using per-app configuration, you can also use:

config :my_app, Ueberauth, json_library: Jason

The JSON library defaults to Jason but can be configured to Poison.

In mix.exs you will need something like:

def deps() do
  [
    ...
    {:jason, "<version>"} # or {:poison, "<version>"}
  ]
end

This file will serve underlying Ueberauth libraries as a hook to grab the configured JSON library.

Link to this function

run_callback(conn, provider_name, arg, options \\ [])

View Source

Request authentication against a provider.

def callback(conn, %{"provider_name" => provider_name} = _params) do
  provider_config = case provider_name do
    "github" ->
      { Ueberauth.Strategy.Github, [
        default_scope: "user",
        request_path:  provider_auth_path(conn, :request, provider_name),
        callback_path: provider_auth_path(conn, :callback, provider_name),
      ]}
  end
  conn
  |> Ueberauth.run_callback(provider_name, provider_config)
  |> handle_callback(params, provider)
end
Link to this function

run_request(conn, provider_name, arg, options \\ [])

View Source

Request authentication against a provider.

specified dynamically in arguments. For example, you can specify in a controller:

def request(conn, %{"provider_name" => provider_name} = _params) do
  provider_config = case provider_name do
    "github" ->
      { Ueberauth.Strategy.Github, [
        default_scope: "user",
        request_path:  provider_auth_path(conn, :request, provider_name),
        callback_path: provider_auth_path(conn, :callback, provider_name),
      ]}
  end
  conn
  |> Ueberauth.run_request(provider_name, provider_config)
end