loading...
Cover image for Ruby on Rails integration guide for passwordless authentication with DID.app

Ruby on Rails integration guide for passwordless authentication with DID.app

crowdhailer profile image Peter Saxton Originally published at did.app ・4 min read

Just want the code? see this commit for the complete set of changes.

What is DID.app

DID.app is an Identity Provider, that authenticates users by verifying access to either an email address or securely stored private key.

This allows your users to sign in with just a single click.

Requirements

The Ruby on Rails install guide can help you install Rails and required dependencies.

New Rails project

Start a new Rails project.

rails new my_app --skip-active-record --skip-javascript
cd my_app

--skip-active-record --skip-javascript We don't need a database or JS bundle for this example

Add Faraday to your Gemfile then run bundle install.

gem 'faraday', '~> 1.0', '>= 1.0.1'

For this guide we will use Faraday to make HTTP requests.
However you can replace this with your preferred client library.

To finish setting up our new Rails project we will create a welcome page, using the Rails generator.

bin/rails generate controller Welcome index

Update the routes.rb so our new welcome page is set as the homepage for our new app.

Rails.application.routes.draw do
  get 'welcome/index'
  root 'welcome#index'
end

You should now have a working Rails application.
Start it with the following command:

./bin/rails server

Visit http://localhost:3000 and check you see the new homepage.

screenshot of new rails app

Outline of Authentication Flow

Authenticating end users takes two steps.

  1. Redirect a user to DID.app with an authentication request from your application.
  2. Fetch user information associated with the code returned in the authentication response.

Redirect user to authenticate with DID.app

Start the authentication process by redirecting a user to the authorization endpoint.
The redirect must include the authentication request parameters.

This form needs to be added to a template.
It is up to you where you locate your sign in button.
We added it to our application layout in /app/views/layouts/application.html.erb.
This ensures a user can sign in from anywhere.

<form action="https://auth.did.app/oidc/authorize" method="get">
  <input name="client_id" value="<%= ENV["CLIENT_ID"] %>" type="hidden" />
  <input name="redirect_uri" value="<%= callback_url %>" type="hidden" />

  <button type="submit">Sign in</button>
</form>

The CLIENT_ID is a value provided to you by DID.app that we will generate later.

The callback_url refers to a controller action that we will implement in the next section.

Create a session controller to handle authentication callback

Once a user has authenticated with DID.app, they will be redirected to the url that was specified in the authentication request.
We need to create a route to handle this.

First add the route into routes.rb.

Rails.application.routes.draw do
  # Other routes
  # ...

  get '/session/callback', to: 'session#callback', as: 'callback'
end

Create a new file for a session controller.
Add the following code to implement the callback route:

require 'faraday'
require 'json'

class SessionController < ApplicationController
  def callback
    response = Faraday.post(
      "https://auth.did.app/oidc/token",
      client_id: ENV["CLIENT_ID"],
      client_secret: ENV["CLIENT_SECRET"],
      code: params["code"]
    )
    data = JSON.parse(response.body)

    session[:current_user_id] = data["userinfo"]["sub"]
    redirect_to root_path
  end
end

The redirect url back to your app will include a query parameter containing a one-time code.
To finish authenticating a user, this code needs to be exchanged for a token and user information.

From this user information we extract the sub parameter which is short for subject. This parameter is a stable identifier for the user.
A verified email address is also returned as part of the user information.

This request will require your CLIENT_ID and CLIENT_SECRET.
It is good practice to keep these values out of your source code so we are using environment variables to configure them.

Display Sign Out Button to Authenticated User

Once a user has authenticated, we no longer want to show them a sign in button.
Probably the most helpful thing to show instead would be a sign out button.

Update the code added to your application layout.
We want to show our sign in button only if our session doesn't have a current user id.
If we do have a user id, and therefore an authenticated session, we should show a sign out button.

<% if session[:current_user_id] %>
  <%= link_to 'Sign out', sign_out_path %>
<% else %>
  <!-- Sign in form from earlier -->
  <form action="https://auth.did.app/oidc/authorize" method="get">
    <input name="client_id" value="<%= ENV["CLIENT_ID"] %>" type="hidden" />
    <input name="redirect_uri" value="<%= callback_url %>" type="hidden" />

    <button type="submit">Sign in</button>
  </form>
<% end %>

Create Sign Out Action

First add a sign out route to routes.rb, this action can also exist in our session controller.

Rails.application.routes.draw do
  # Other routes
  # ...

  get '/session/terminate', to: 'session#terminate', as: 'sign_out'
end

In the session controller add the route to sign out a user.

class SessionController < ApplicationController
  # callback action
  # ...

  def terminate
    reset_session
    redirect_to root_path
  end
end

Signing out a user is done by clearing the session information.

Get App Identifiers DID.app

The final step is to get a CLIENT_ID and CLIENT_SECRET for your app.
You will need an account, Sign up to create one.

After signing up, you will be directed to set up your first app.
Because we will run on localhost we need to use test app, select test mode.

Screenshot of creating an app on DID

After setting the details for the app, copy the client id and secret for use in our application.

Try it out

Start Rails, passing in the required configuration as environment variables.

CLIENT_ID=test_abc CLIENT_SECRET=test_abcdef ./bin/rails server

Visit localhost:3000,
you should see your new Rails app with a shiny sign in button.

Any problems, see this commit for the complete set of changes.

Have a question?

If you have any further questions contact us at team@did.app.

Posted on by:

crowdhailer profile

Peter Saxton

@crowdhailer

Founder at DID.app, because I think it is time to kill the password for the benefit of our users.

Discussion

markdown guide