Connecting your Ruby on Rails application with the Azure Active Directory is a powerful tool to get Office 365 data into your app. In this simple example we store some basic data in our session. This could be extended to manage your calendar or emails for example. You can also use it as a single sign-on mechanism for a user model of your website.
In order to access the Office 365 data, we first need to set up the web application in the Azure Active Directory:
- Open a browser and navigate to the Azure Active Directory admin center. Login using a personal account (aka: Microsoft Account) or Work or School Account.
- Select Azure Active Directory in the left-hand navigation, then select App registrations under Manage.
-
Select New registration. On the Register an application page, set the values as follows:
- Set Name to
Ruby Graph Tutorial
. - Set Supported account types to Accounts in any organizational directory and personal Microsoft accounts.
- Under Redirect URI, set the first drop-down to
Web
and set the value tohttp://localhost:3000/auth/microsoft_graph_auth/callback
.
- Set Name to
- Choose Register. On the Ruby Graph Tutorial page, copy the value of the Application (client) ID and save it, you will need it in the next step.
- Select Certificates & secrets under Manage. Select the New client secret button. Enter a value in Description and select one of the options for Expires and choose Add.
- Copy the client secret value before you leave this page. You will need it in the next step.
Once the registration is completed we set up our Rails application.
Add the omniauth-oauth2 gem to our Gemfile
:
# Gemfile
gem 'omniauth-oauth2'
Setup the OmniAuth
strategy as in the sample app:
# lib/microsoft_graph_auth.rb
require 'omniauth-oauth2'
module OmniAuth
module Strategies
# Implements an OmniAuth strategy to get a Microsoft Graph
# compatible token from Azure AD
class MicrosoftGraphAuth < OmniAuth::Strategies::OAuth2
option :name, :microsoft_graph_auth
# Configure the Microsoft identity platform endpoints
option :client_options,
site: 'https://login.microsoftonline.com',
authorize_url: '/common/oauth2/v2.0/authorize',
token_url: '/common/oauth2/v2.0/token'
# Send the scope parameter during authorize
option :authorize_options, [:scope]
# Unique ID for the user is the id field
uid { raw_info['id'] }
# Get additional information after token is retrieved
extra do
{
'raw_info' => raw_info
}
end
def raw_info
# Get user profile information from the /me endpoint
@raw_info ||= access_token.get('https://graph.microsoft.com/v1.0/me?$select=displayName,mail,mailboxSettings,userPrincipalName').parsed
end
# Override callback URL
# OmniAuth by default passes the entire URL of the callback, including
# query parameters. Azure fails validation because that doesn't match the
# registered callback.
def callback_url
options[:redirect_uri] || (full_host + script_name + callback_path)
end
end
end
end
Add an initializer to load the strategy when the application starts. Here we provide the APP_ID
and APP_SECRET
, that we got from the Azure Active Directory admin center, as environment variables.
scope
defines which data the user will grant access to. For a full reference you can check the Microsoft Graph Permissions Reference.
# config/initializers/omniauth_graph.rb
require 'microsoft_graph_auth'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :microsoft_graph_auth,
ENV['AZURE_APP_ID'],
ENV['AZURE_APP_SECRET'],
:scope => 'openid profile email offline_access user.read mailboxsettings.read calendars.readwrite'
end
Add the controller to handle the callback from Azure. The callback
action in this example only stores the provided displayName
as user_name
in our session.
# app/controllers/auth_controller.rb
class AuthController < ApplicationController
def callback
# Access the authentication hash for omniauth
auth_hash = request.env['omniauth.auth']
# Save the user's display name
session[:user_name] = auth_hash.dig(:extra, :raw_info, :displayName)
redirect_to root_url
end
end
Configure the route for the callback and a simple example page:
# config/routes.rb
Rails.application.routes.draw do
get 'home/index'
root 'home/index'
# Route for OmniAuth callback
match '/auth/:provider/callback', to: 'auth#callback', via: [:get, :post]
end
Add a view containing a login button if no user data is saved in the session already, otherwise show the data.
# app/views/home/index.html.erb
<% if session[:user_name] %>
<h4>Welcome <%= session[:user_name] %>!</h4>
<% else %>
<%= form_tag("/auth/microsoft_graph_auth", method: "post") do %>
<button type="submit" class="btn btn-primary btn-large">Click here to sign in</button>
<% end %>
<% end %>
When you click on the button to sign in you will be redirected to https://login.microsoftonline.com
.
Login here using your Office 365 account and it will ask you to confirm to access the data based on the permissions defined in the previously defined scope.
Once the login is completed, you will be redirected back to your sample application and will be able to see your Office 365 display name in your Rails application.
For a full working example with more extensive features like a calendar view, you can check out the sample app linked in the resources.
Happy Coding!