Devise: create a local OmniAuth strategy for Slack
Tags: rails, omniauth, devise, slack
Published: 2019-12-09 12:16:07

---
title: Devise: create a local OmniAuth strategy for Slack
published: true
description: This article explains how to create a custom OmniAuth strategy and then load it using Devise. This allows you to easily develop your strategy without having to create a gem.
tags: rails, omniauth, devise, slack
cover_image: https://thepracticaldev.s3.amazonaws.com/i/d0d0pwncd1rfcryv25h9.jpg
---

<center><small>_Photo by [Adeolu Eletu](https://unsplash.com/@adeolueletu?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_</small></center>

👋 Hi there, this article explains how to create a custom OmniAuth strategy and then load it using Devise. This allows you to easily develop your strategy without having to create a gem.

If you don't know what Devise or OmniAuth are, I guess you can stop here. I am glad you read that far already.

At the end of the article there's also a call for help because I am a new Rails developer and I can't figure everything out!

# Backstory

I am building a product and I want users to be able to [sign in with Slack](https://api.slack.com/docs/sign-in-with-slack).

Since I am using [Devise](https://github.com/plataformatec/devise) I found out that Devise can work with [OmniAuth](https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview) to allow sign in from various OAuth providers like Facebook, Twitter: those are called OmniAuth strategies.

I found the Slack strategy on GitHub: [omniauth-slack](https://github.com/kmrshntr/omniauth-slack/). But after doing a due diligence I discovered three things:
1. The Slack strategy is not official and not maintained: last commit April 6 2017, lots of issues and pending PRs
2. [The Slack strategy forks](https://github.com/kmrshntr/omniauth-slack/network) are not maintained or filled with a lot of complex features I don't need
3. The actual code required to make a custom Slack strategy is 40 lines of Ruby. Which might explain why it's not maintained.

What do I do? [NIH syndrome](https://en.wikipedia.org/wiki/Not_invented_here) to the rescue! **I am gonna write another Slack OmniAuth strategy**. To be honest, since I am learning Ruby and Rails I was mostly curious how Devise and OmniAuth were really working together.

# Creating a custom OmniAuth strategy

The OmniAuth documentation provides information on [how to create a new strategy](https://github.com/omniauth/omniauth/wiki/Strategy-Contribution-Guide) but it does not tells you how to load such code. Most people will create reusable gems and then add that to their **Gemfile**.

Since I was already far away from my initial need (Allow people to sign in with Slack), I did not wanted to now dig into how to create gems and develop them locally, that would be for another time, maybe.

All I wanted to do was for this line:

**config/initializers/devise.rb**
```rb
  config.omniauth :slack, ENV['SLACK_CLIENT_ID'], ENV['SLACK_CLIENT_SECRET'],
                  scope: 'identity.basic,identity.email,identity.team,identity.avatar'
```

To load my own Slack OmniAuth strategy.

Now the first question I asked myself is: where do I put my custom strategy so that Rails and devise can access it?

# Loading custom code in Rails

As a new Rails developer not used to autoloading, auto reloading and conventions. It was not very clear to me where to put my code but eventually I settled on **lib/omniauth/slack.rb**.

From the outside, it seems the Rails community [is confused](https://www.freecodecamp.org/news/what-happens-when-you-run-rails-new/#lib) about the question of adding custom code and loading/autoloading it.

This directory is not part of the autoloading mechanism so you have to put `require 'omniauth/slack'` at the top of the file **config/initializers/devise.rb**. The whole OmniAuth and Devise ways of detecting strategies and loading them are completely blurry to me. If you know a better way, let me know.

Knowing 1. where to put my strategy and 2. how to load it **were the big challenges for me.**

Now onto the actual Slack strategy implementation.

# The Slack strategy

Here's the actual code that will allow you to add a sign-in with Slack feature on your Rails application:

**lib/omniauth/slack.rb**
```rb
require 'omniauth-oauth2'

module OmniAuth
  module Strategies
    class Slack < OmniAuth::Strategies::OAuth2
      option :client_options,
             site: 'https://slack.com',
             token_url: 'api/oauth.access'

      uid do
        "#{raw_info.dig('user', 'id')}-#{raw_info.dig('team', 'id')}"
      end

      info do
        {
          name: raw_info.dig('user', 'name'),
          email: raw_info.dig('user', 'email')
        }
      end

      extra do
        { raw_info: raw_info }
      end

      def raw_info
        @raw_info ||= access_token.get('/api/users.identity').parsed
      end

      def callback_url
        full_host + script_name + callback_path
      end
    end
  end
end
```

# Further considerations

_This is the part where I need your help now..._


Ideally I would like to avoid the line `require omniauth/slack` at the top of **config/initializers/devise.rb** but I have no idea on how to do that.

I also have to reload my Rails application whenever I make a change to the strategy. I suspect this is because of Devise or OmniAuth doing something fancy here. I tried to create a separate class and adding the `lib` folder to the autoloading mechanism and the auto reloading of this dummy class was working. But somehow not in the case of an OmniAuth strategy.

Finally, inside **lib/omniauth/slack.rb** I have to use either `raw_info['team']['name'] or `raw_info.dig('team', 'name')` while inside the Rails controller I can access `request.env['omniauth.auth'].extra.raw_info.team.name` and I have no idea why or where is this magic documented.

---

🔚 That's it!

[As always](https://dev.to/vvo), do note that this post is from someone learning Rails. If you read something obviously wrong and/or would like to add to this article then do it in the comments and I will be very happy to update my text.

If you're trying to implement a Slack sign-in feature on your application and you're struggling, also jump in the comments and let me know.

If you have your own point of view on Devise and OmniAuth I would be glad to hear it too.

Thanks for reading, if you enjoyed this post, share it for others to discover it:

{% twitter 1204012267706171392 %}

![This is a cat GIF, I love cat GIFs](https://thepracticaldev.s3.amazonaws.com/i/dcdc020iwx656m8k1h53.gif)