-
-
Save petros/9522426 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationController < ActionController::Base | |
include SessionAuthentication | |
# ... | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class AuthenticatedUser | |
# Raise if the user must be a member of the team on GitHub. | |
class TeamMembershipRequired < StandardError; end | |
# Public: Find or create User from the OmniAuth::AuthHash returned after | |
# OAuthing with GitHub. | |
# | |
# omniauth_authhash - OmniAuth::AuthHash instance. | |
# | |
# Returns a User. | |
def self.find(omniauth_authhash) | |
user = new(omniauth_authhash) | |
user.authenticate! | |
user.save! | |
end | |
def initialize(omniauth_authhash) | |
@omniauth_authhash = omniauth_authhash | |
end | |
# Public: OmniAuth::AuthHash passed in at initialization. | |
# | |
# Returns an OmniAuth::AuthHash. | |
attr_reader :omniauth_authhash | |
# Public: The GitHub id of the user. | |
# | |
# Returns an Integer. | |
def github_id | |
omniauth_authhash.uid | |
end | |
# Public: Users name on GitHub. | |
# | |
# Returns a String. | |
def name | |
omniauth_authhash.info.name | |
end | |
# Public: Users nickname on GitHub. | |
# | |
# Returns a String. | |
def username | |
omniauth_authhash.info.nickname | |
end | |
# Public: The access token of the user, needed for making API requests on | |
# behalf of the user. | |
# | |
# Returns a String. | |
def access_token | |
omniauth_authhash.credentials.token | |
end | |
# Public: Is this user on the team specified by ENV["GITHUB_TEAM_ID"]? | |
# | |
# Returns a TrueClass or FalseClass. | |
def team_member? | |
omniauth_authhash.credentials.team_member? | |
end | |
# Public: User instance, found or initialized by github_id. | |
# | |
# Returns a User. | |
def user | |
@user ||= begin | |
user = User.find_or_initialize_by(:github_id => github_id) | |
user.name = name | |
user.username = username | |
user.access_token = access_token | |
user | |
end | |
end | |
# Public: Raises an error if the user is not a team member or does not have | |
# a github.com email address. | |
def authenticate! | |
raise TeamMembershipRequired unless team_member? | |
end | |
# Public: Save authenticated user and the users email addresses. | |
# | |
# Returns a User. | |
def save! | |
user.save! | |
user | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateUsers < ActiveRecord::Migration | |
def change | |
create_table :users do |t| | |
t.string :name | |
t.integer :github_id, :null => false | |
t.string :username | |
t.string :access_token | |
t.timestamps | |
end | |
add_index :users, :github_id, :unique => true | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rails.application.config.middleware.use OmniAuth::Builder do | |
provider :githubteammember, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], :scope => "user" | |
end | |
OmniAuth.config.on_failure = Proc.new { |env| | |
if env["omniauth.error"].kind_of? OmniAuth::Strategies::OAuth2::CallbackError | |
[302, {"Location" => "/", "Content-Type"=> "text/html"}, []] | |
end | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Intercom::Application.routes.draw do | |
get "/auth/githubteammember/callback" => "sessions#create" | |
get "/signout" => "sessions#signout" | |
get "/auth/failure" => "sessions#failure" | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'active_support/concern' | |
require 'active_support/core_ext' | |
# SessionAuthentication adds session authentication to a controller. | |
# It includes helper methods for views and a signin_required method to use | |
# in a before_filter to ensure a request is by a signed in user. | |
module SessionAuthentication | |
extend ActiveSupport::Concern | |
included do | |
helper_method :current_user, :signed_in? | |
before_filter :signin_required | |
end | |
# Public: Returns the current user or kicks off authentication. | |
# | |
# Returns a User or NilClass. | |
def current_user | |
return @current_user if defined?(@current_user) | |
self.current_user = user_from_session | |
end | |
# Internal: Set the current user and add to session. | |
# | |
# user - The user object you would like to make the current user. | |
def current_user=(user) | |
return unless user.present? | |
@current_user = user | |
session[:user_id] = user.id | |
end | |
# Public: Sign in the user and redirect to the saved url or root path. | |
# | |
# user - The user object you would like to make the current user. | |
def sign_in_and_redirect(user) | |
self.current_user = user | |
redirect_to session[:return_to] || root_path | |
end | |
# Public: Validates signed in state. | |
# | |
# Returns a TrueClass or FalseClass. | |
def signed_in? | |
!!current_user | |
end | |
# Public: Require that the the user making the request is signed in. | |
def signin_required | |
signed_in? || permission_denied | |
end | |
# Public: Treat the web request or api request as unauthorized. | |
def permission_denied | |
session[:return_to] = request.path if request.path | |
redirect_to "/auth/githubteammember" | |
end | |
# Internal: Attempt to find user from session if session[:user_id] is present. | |
# | |
# Returns a User or NilClass. | |
def user_from_session | |
session[:return_to] = request.path if request.path | |
user_finder.find_by_id(session[:user_id]) if session[:user_id].present? | |
end | |
# Internal: Accessing the user finder through this method | |
# allows us to test the interaction more easily | |
def user_finder | |
@user_finder ||= User | |
end | |
# Internal: Set user finder to an alternative source. | |
attr_writer(:user_finder) | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SessionsController < ApplicationController | |
skip_before_filter :signin_required, :only => [:create, :failure] | |
rescue_from AuthenticatedUser::TeamMembershipRequired do | |
render :text => "Authentication failure." | |
end | |
# Public: Create and log in a user from the Omniauth auth payload. | |
def create | |
user = AuthenticatedUser.find(request.env["omniauth.auth"]) | |
sign_in_and_redirect user | |
end | |
# Public: Remove user's session and redirect. | |
def signout | |
reset_session | |
redirect_to "https://github.com" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# TokenAuthentication adds token authentication to a controller and provides | |
# an authentication_required method that can be used in a before_filter to | |
# ensure that requests are authenticated. | |
module TokenAuthentication | |
# Public: Require that the request has a valid authentication token. | |
def authentication_required | |
authenticated? || permission_denied | |
end | |
# Public: Does the request have an authenticated_user? | |
# | |
# Returns a TrueClass or FalseClass. | |
def authenticated? | |
!!authenticated_user | |
end | |
# Public: The authenticated_user if one is set. | |
# | |
# Returns a User or NilClass. | |
def authenticated_user | |
return @authenticated_user if defined?(@authenticated_user) | |
self.authenticated_user = user_from_token | |
end | |
# Internal: Set the authenticated_user. | |
# | |
# user - A User found by their token. | |
def authenticated_user=(user) | |
return unless user.present? | |
@authenticated_user = user | |
end | |
# Internal: Halts the request with an unauthorized response. | |
def permission_denied | |
head :unauthorized | |
end | |
# Internal: Attempt to find user from Authorization header or access_token | |
# parameter. | |
# | |
# Returns a User or NilClass. | |
def user_from_token | |
token = request.headers["Authorization"] | |
if token =~ /^token ([\w]+)$/i | |
token = $1 | |
else | |
token = params.delete("access_token") | |
end | |
User.find_by_access_token(token) if token.present? | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
# Public: Full name. | |
# column :name | |
# Returns a String. | |
# Public: GitHub id. | |
# column :github_id | |
# Returns an Integer. | |
validates :github_id, :presence => true, :uniqueness => true | |
# Public: Username. | |
# column :username | |
# Returns a String. | |
# Public: Access token for making GitHub API requests. | |
# column :access_token | |
# Returns a String. | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment