Sinatra::CanvasAuth
CanvasAuth is a Sinatra extension that implements the OAuth2 flow used for authenticating a user via Canvas LMS.
This gem handles redirection of unauthenticated/unauthorized users, as well as the routing & API calls necessary for logging in/obtaining an access token, logging out/deleting an access token.
Installation
Add this line to your application's Gemfile:
gem 'sinatra-canvas_auth'
And then execute:
$ bundle
Or install it yourself as:
$ gem install sinatra-canvas_auth
Usage
If you are developing a "classic-style" Sinatra app, require the files at the top of your app, enable sessions, and set the required configuration options.
require sinatra
require sinatra/canvas_auth
configure do
enable :sessions
set :canvas_url, 'https://ucdenver.instructure.com'
set :client_id, 10230000000000045
set :client_secret, '659df93f24affc25948ee437f8ac825edfa903d95e3a5ace0bb5ac4fb61686c6'
end
get '/' do
'Hello World'
end
For "modular-style" apps, you must also explicitly register the extension
require sinatra/base
require sinatra/canvas_auth
class App < Sinatra::Base
configure do
enable :sessions
set :canvas_url, 'https://ucdenver.instructure.com'
set :client_id, 10230000000000045
set :client_secret, '659df93f24affc25948ee437f8ac825edfa903d95e3a5ace0bb5ac4fb61686c6'
end
register Sinatra::CanvasAuth
get '/' do
'Hello World'
end
end
Configuration
CanvasAuth pulls settings from your Sinatra app's configuration, which can be set with the built-in DSL.
For simplicity, examples in this documentation hard-code configuration within the application, though it is often wise to use alternate methods when configuring sensitive data (e.g. API keys), especially when working with open source. Here are just a few options that can help you with this:
CanvasAuth requires a baseline configuration to function, as Canvas API settings will differ between instances. Below is a full list of the available configuraiton options.
Required Settings
-
canvas_url (String)
The full URL of the Canvas instance used for authentication.
set :canvas_url, 'https://ucdenver.instructure.com'
-
client_id (String)
The client id (AKA "ID") for the developer key associated with your app. Developer keys can be requested here, or created directly by Canvas admins by clicking "Developer Keys" on the sidebar under your account's admin panel.
set :client_id, 10230000000000045
-
client_secret (String)
The 64 character client secret (AKA "Key") for the developer key associated with your app.
set :client_secret, '659df93f24affc25948ee437f8ac825edfa903d95e3a5ace0bb5ac4fb61686c6'
Optional Settings
-
auth_paths (Array)
Default: [/.*/]
To only require authentication for certain routes, they may be explicitly specified here with either strings or regular expression. By default, all app routes will require authentication.
set :auth_paths, ['/admin', /^\/courses\/(\d)+$/]
Alternative syntax:
authenticate '/admin', /^\/courses\/(\d)+$/
-
public_paths (Array)
Default: []
The inverse of auth_paths, routes matching strings or regexps in this array will not require authentication
set :public_paths, ['/homepage', /^\/assets\/.+$/]
-
unauthorized_redirect (String)
Default: "/unauthorized"
If the above "authorized" setting is provided and returns falsy when called, the user will be redirected to this path.
set :unauthorized_redirect, '/not_allowed'
-
logout_redirect (String)
Default: "/logged-out"
After a user is logged out, they will be redirected to this path.
set :logout_redirect, '/goodbye'
-
failure_redirect (String)
Default: "/login-failure"
If the user declines to grant the app access to their Canvas account, or the API request for a Canvas token raises an unexpected error, the user will be redirected to this path.
set :error_path, '/auth-error'
Callbacks
The following are optional hooks called by CanvasAuth which allow you to customize certain behavior. They should be defined as helper methods within your application.
-
oauth_callback(oauth_response)
Once the OAuth authentication request has been made, this method is called with the API response from Canvas as an argument. This may be used to define a custom response handling action, such as saving the user's token in a database.
helpers do
def oauth_callback(oauth_response)
uid = oauth_response['user']['id']
token = oauth_response['access_token']
db_connection.execute("UPDATE users SET access_token = ? where uid = ?", token, uid)
end
end
-
authorized()
This method may be defined to check the authorization priveleges of a user once they have logged in. It should return truthy for authorized users, falsy otherwise. Since this is called without parameters, it generally makes use of session variables and/or settings which were set during the oauth_callback method or elsewhere in the app.
helpers do
def authorized
session[:allowed_roles].includes?(session[:user_roles])
end
end
Miscellaneous Notes
-
CanvasAuth automatically assigns session['user_id']
and session['access_token']
to the values returned by the OAuth response, so there is no need to do this manually in your oauth_callback proc.
-
The following routes are defined by CanvasAuth for use in the OAuth flow and should not be overridden by your application:
- GET /canvas-auth-login
- GET /canvas-auth-logout
- POST /canvas-auth-token
-
The following routes are also defined by CanvasAuth, and may be overridden by your application, should you wish to replace the default view/behavior provided:
- GET /unauthorized
- GET /logged-out
- GET /login-failure
-
All routes defined by CanvasAuth are permanently exempt from the requiring authentication, to avoid redirect loops.
Contributing
Feeback, bug reports, and pull requests are welcome and appreciated.
- Fork it ( https://github.com/CUOnline/sinatra-canvas_auth/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request