Tristan Dunn

Authenticate with the Dribbble API

The Dribbble API supports user authentication with OAuth 2.0, allowing applications to comment, like, and more as the authenticated user. We can also use it to verify a user, which is what we’re going to do.

Why would you want to verify a user? Maybe you’re selling a product that requires the user to be a player on Dribbble. Or you want to use Dribbble as the authentication for your application. Basically any circumstance where you want to know it’s a specific person, possibly with a specific status.

Creating an Application

We need an application to use when authenticating a user. The application provides a client ID and secret for us to use, as well as provides information to the user about the application.

If you don’t already have one, create an application on Dribbble. Enter a name, description, and website URL which help users identify the application. The callback URL is where Dribbble will redirect the user after an authorization attempt, which we use to complete the authentication or handle any errors. For this example we’re going to use http://localhost:3000/sessions/new, which refers to the new action for a sessions controller in our local Rails application.

Preparing Rails

Next we need to create and set up our Rails application. We’ll just generate an application by running rails new dribbble-example. There are also a couple of dependencies to add and configuration that we should perform to help ease the authentication process.

Dependencies

We’ll add two dependencies to the Gemfile. The oauth2 dependency is the OAuth 2.0 client we’ll be using for authentication. And the dotenv-rails dependency that allows us to set environment variables for the client ID and secret, instead of hard coding them into the Rails application.

gem "oauth2"

group :development do
  gem "dotenv-rails"
end
Adding the dependencies to the Gemfile.

Don’t forget to run bundle to install them.

Configuration

To configure the environment variables we’ll create a .env file in the root directory of the Rails application. Your client ID and secret on your application page, which is available under your applications on Dribbble.

DRIBBBLE_CLIENT_ID="aa47c7086a79cbd534bc677159f9e813a63ddc1c1e2f3fbf04fdf8d616cda375"
DRIBBBLE_CLIENT_SECRET="467652ff939bc8b39020e393453f79eb5efb7b550089d49ee487b62be4d82db8"
Adding the client ID and secret to the .env file.

There’s no harm in exposing the client ID, but the secret should not be public. It’s recommended to ignore the .env file in the .gitignore file, otherwise it’s no better than hard coding the values.

Authenticating

Our application is going to be simple. A homepage with a “Connect with Dribbble” link when unauthenticated, an action for creating a token, and an alternative homepage displaying the user’s name when authenticated.

Authorization

When a user is not authenticated we need to link to Dribbble to start the OAuth process, so we’ll start by creating a Token class for generation the authorization URL. It’s a decent amount of code to start with, but it’s predominately configuration options. Note that we’re requesting the default public scope, but you can choose from others depending on your needs.

class Token
  # Settings for the OAuth client.
  CLIENT_ID      = ENV["DRIBBBLE_CLIENT_ID"].freeze
  CLIENT_SCOPE   = "public".freeze
  CLIENT_SECRET  = ENV["DRIBBBLE_CLIENT_SECRET"].freeze
  CLIENT_OPTIONS = {
    site:          "https://api.dribbble.com".freeze,
    token_url:     "https://dribbble.com/oauth/token".freeze,
    authorize_url: "https://dribbble.com/oauth/authorize".freeze
  }.freeze

  # Generate an authorization URL with our client settings.
  def self.authorize_url
    client = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, CLIENT_OPTIONS)
    client.auth_code.authorize_url(scope: CLIENT_SCOPE)
  end
end
The initial app/models/token.rb file.

We need a page for displaying the authorization link now, so let’s add a simple Pages controller.

class PagesController < ApplicationController
  def index
  end
end
A minimal app/controllers/pages_controller.rb file.

And we of course need to set up a route for it, which we’ll just have it be the root.

Rails.application.routes.draw do
  root to: "pages#index"
end
Adding a root route to the config/routes.rb file.

Lastly we need a view to display the link.

<%= link_to "Connect with Dribbble", Token.authorize_url %>
Super minimal app/views/pages/index.html.erb file.

Creating a Token

After a user authorizes our application then Dribbble will redirect them to our callback URL with a code. We can use the code provided to request an access token, which allows us to perform API requests on behalf of the user.

To start we’ll add a create_from_code method to our Token class. We will also extract the client creation to a separate method for reuse.

class Token
  # Settings for the OAuth client.
  CLIENT_ID      = ENV["DRIBBBLE_CLIENT_ID"].freeze
  CLIENT_SCOPE   = "public".freeze
  CLIENT_SECRET  = ENV["DRIBBBLE_CLIENT_SECRET"].freeze
  CLIENT_OPTIONS = {
    site:          "https://api.dribbble.com".freeze,
    token_url:     "https://dribbble.com/oauth/token".freeze,
    authorize_url: "https://dribbble.com/oauth/authorize".freeze
  }.freeze

  # Create an OAuth client with our settings.
  def self.client
    OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, CLIENT_OPTIONS)
  end

  # Create a token with our client using the code provided.
  def self.create_from_code(code)
    client.auth_code.get_token(code).token
  end

  # Generate an authorization URL with our client.
  def self.authorize_url
    client.auth_code.authorize_url(scope: CLIENT_SCOPE)
  end
end
Adding a create_from_code method to the app/models/token.rb file.

Next we can create our SessionsController and use the new method for creating an access token that we’ll store in the user’s session.

class SessionsController < ApplicationController
  def new
    # Create an access token from the provided code.
    session[:token] = Token.create_from_code(params[:code])

    # Redirect back to the homepage.
    redirect_to root_path
  end
end
Creating the app/controllers/sessions_controller.rb file.

Now we can add a route for the new action. Remember that this is the action that Dribbble redirects to, so make sure it matches in your application settings if you’re using a different name.

Rails.application.routes.draw do
  resources :sessions, only: [:new]

  root to: "pages#index"
end
Adding sessions route to the config/routes.rb file.

Using the Token

We can now use the access token to make API requests on behalf of the user. Let’s make a basic User class that fetches the attributes for the authorized user, which we’ll use to display a message to them.

class User
  # Create an OAuth2::AccessToken from the provided access token and our client.
  def initialize(access_token)
    @token = OAuth2::AccessToken.from_hash(Token.client, access_token: access_token)
  end

  # Fetch the user's attributes as parsed JSON with indifferent access and
  # memoize.
  def attributes
    @attributes ||= @token.get("/v1/user").parsed.with_indifferent_access
  end
end
Creating the app/models/user.rb file.

We’ll create a user in our root controller when a token is present.

class PagesController < ApplicationController
  def index
    if session[:token].present?
      @user = User.new(session[:token])
    end
  end
end
Adding user creation to the app/controllers/pages_controller.rb file.

Which we can conditionally use in the view to greet the user.

<% if @user.present? %>
  Welcome, <%= @user.attributes[:name] %>!
<% else %>
  <%= link_to "Connect with Dribbble", Token.authorize_url %>
<% end %>
Conditional app/views/pages/index.html.erb file.

Summary

While the resulting application is rather basic it gives you an idea how to integrate the Dribbble API into a new or existing application. Check out the official documentation for what you can do with an authenticated user.

Also, in a real application there are changes or additions you may want to make. If you need to make requests in a background job, you’ll probably want to store the access token in the database. If you’re displaying user information from the API, as we are here, you’ll want to cache it to avoid making an API request for every user request. Error handling would also be a welcomed addition. And a reminder that if you want more than read-only access you’ll need to request other scopes.

See the dribbble-example repository for the complete source code to the application. Now on to the hard part, the idea. E-mail me if you make an application, or if you have any comments or questions.