Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ doc
# jeweler generated
pkg

# byebug generated
.byebug_history

# for RVM
.rvmrc

Expand Down
41 changes: 9 additions & 32 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 0.10.2

* Added support for Microsoft OAuth (thanks to @athix) [#37](https://github.com/Sorcery/sorcery/pull/37)

## 0.10.1

* Fixed LinkedIn bug [#36](https://github.com/Sorcery/sorcery/pull/36)

## 0.10.0
Expand Down Expand Up @@ -77,46 +83,17 @@

## 0.8.4

* Few security fixes in `external` module
* Few security fixes in `external` module

## 0.8.3 (yanked because of bad Jeweler release)

## 0.8.2

* Activity logging feature has a new column called `last_login_from_ip_address` (string type). If you use ActiveRecord, you will have to add this column to DB ([#465](https://github.com/NoamB/sorcery/issues/465))

## 0.8.1
<!-- TO BE WRITTEN -->

## 0.8.0
<!-- TO BE WRITTEN -->

## 0.7.13
<!-- TO BE WRITTEN -->

## 0.7.12
<!-- TO BE WRITTEN -->

## 0.7.11
<!-- TO BE WRITTEN -->

## 0.7.10
<!-- TO BE WRITTEN -->

## 0.7.9
<!-- TO BE WRITTEN -->

## 0.7.8
<!-- TO BE WRITTEN -->

## 0.7.7
<!-- TO BE WRITTEN -->

## 0.7.6
<!-- TO BE WRITTEN -->
## 0.7.5-0.8.1

## 0.7.5
<!-- TO BE WRITTEN -->
<!-- HERE BE DRAGONS (Changelogs never written) -->

## 0.7.1-0.7.4

Expand Down
10 changes: 10 additions & 0 deletions lib/generators/sorcery/templates/initializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@
# config.google.user_info_mapping = {:email => "email", :username => "name"}
# config.google.scope = "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
#
# For Microsoft Graph, the key will be your App ID, and the secret will be your app password/public key.
# The callback URL "can't contain a query string or invalid special characters", see: https://docs.microsoft.com/en-us/azure/active-directory/active-directory-v2-limitations#restrictions-on-redirect-uris
# More information at https://graph.microsoft.io/en-us/docs
#
# config.microsoft.key = ""
# config.microsoft.secret = ""
# config.microsoft.callback_url = "http://0.0.0.0:3000/oauth/callback/microsoft"
# config.microsoft.user_info_mapping = {:email => "userPrincipalName", :username => "displayName"}
# config.microsoft.scope = "openid email https://graph.microsoft.com/User.Read"
#
# config.vk.key = ""
# config.vk.secret = ""
# config.vk.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=vk"
Expand Down
1 change: 1 addition & 0 deletions lib/sorcery/controller/submodules/external.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def self.included(base)
require 'sorcery/providers/paypal'
require 'sorcery/providers/slack'
require 'sorcery/providers/wechat'
require 'sorcery/providers/microsoft'

Config.module_eval do
class << self
Expand Down
59 changes: 59 additions & 0 deletions lib/sorcery/providers/microsoft.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module Sorcery
module Providers
# This class adds support for OAuth with Microsoft Graph.
#
# config.microsoft.key = <key>
# config.microsoft.secret = <secret>
# ...
#
class Microsoft < Base
include Protocols::Oauth2

attr_accessor :auth_url, :scope, :token_url, :user_info_url

def initialize
super

@site = 'https://login.microsoftonline.com'
@auth_url = '/common/oauth2/v2.0/authorize'
@token_url = '/common/oauth2/v2.0/token'
@user_info_url = 'https://graph.microsoft.com/v1.0/me'
@scope = 'openid email https://graph.microsoft.com/User.Read'
@state = SecureRandom.hex(16)
end

def authorize_url(options = {})
oauth_params = {
client_id: @key,
response_type: 'code'
}
options.merge!(oauth_params)
super(options)
end

def get_user_hash(access_token)
response = access_token.get(user_info_url)

auth_hash(access_token).tap do |h|
h[:user_info] = JSON.parse(response.body)
h[:uid] = h[:user_info]['id']
end
end

# calculates and returns the url to which the user should be redirected,
# to get authenticated at the external provider's site.
def login_url(_params, _session)
authorize_url(authorize_url: auth_url)
end

# tries to login the user from access token
def process_callback(params, _session)
args = {}.tap do |a|
a[:code] = params[:code] if params[:code]
end

get_access_token(args, token_url: token_url, token_method: :post)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/sorcery/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Sorcery
VERSION = '0.10.1'
VERSION = '0.10.2'
end
1 change: 1 addition & 0 deletions sorcery.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ Gem::Specification.new do |s|
s.add_development_dependency 'simplecov', '>= 0.3.8'
s.add_development_dependency 'rspec-rails', '~> 3.5.0'
s.add_development_dependency 'test-unit', '~> 3.1.0'
s.add_development_dependency 'byebug', '~> 9.0.0'
end
17 changes: 12 additions & 5 deletions spec/controllers/controller_oauth2_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
expect(flash[:notice]).to eq 'Success!'
end

[:github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat].each do |provider|
[:github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat, :microsoft].each do |provider|
describe "with #{provider}" do
it 'login_at redirects correctly' do
get :"login_at_test_#{provider}"
Expand Down Expand Up @@ -201,7 +201,7 @@
end

sorcery_reload!([:user_activation,:external], :user_activation_mailer => ::SorceryMailer)
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat])
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat, :microsoft])

# TODO: refactor
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
Expand Down Expand Up @@ -231,6 +231,9 @@
sorcery_controller_external_property_set(:wechat, :key, "eYVNBjBDi33aa9GkA3w")
sorcery_controller_external_property_set(:wechat, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
sorcery_controller_external_property_set(:wechat, :callback_url, "http://blabla.com")
sorcery_controller_external_property_set(:microsoft, :key, "eYVNBjBDi33aa9GkA3w")
sorcery_controller_external_property_set(:microsoft, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
sorcery_controller_external_property_set(:microsoft, :callback_url, "http://blabla.com")
end

after(:all) do
Expand Down Expand Up @@ -260,7 +263,7 @@
expect(ActionMailer::Base.deliveries.size).to eq old_size
end

[:github, :google, :liveid, :vk, :salesforce, :paypal, :wechat].each do |provider|
[:github, :google, :liveid, :vk, :salesforce, :paypal, :wechat, :microsoft].each do |provider|
it "does not send activation email to external users (#{provider})" do
old_size = ActionMailer::Base.deliveries.size
create_new_external_user provider
Expand Down Expand Up @@ -409,7 +412,7 @@ def stub_all_oauth2_requests!
end

def set_external_property
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat])
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack, :wechat, :microsoft])
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
Expand Down Expand Up @@ -437,6 +440,9 @@ def set_external_property
sorcery_controller_external_property_set(:wechat, :key, "eYVNBjBDi33aa9GkA3w")
sorcery_controller_external_property_set(:wechat, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
sorcery_controller_external_property_set(:wechat, :callback_url, "http://blabla.com")
sorcery_controller_external_property_set(:microsoft, :key, "eYVNBjBDi33aa9GkA3w")
sorcery_controller_external_property_set(:microsoft, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
sorcery_controller_external_property_set(:microsoft, :callback_url, "http://blabla.com")
end

def provider_url(provider)
Expand All @@ -448,7 +454,8 @@ def provider_url(provider)
vk: "https://oauth.vk.com/authorize?client_id=#{::Sorcery::Controller::Config.vk.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=#{::Sorcery::Controller::Config.vk.scope}&state",
salesforce: "https://login.salesforce.com/services/oauth2/authorize?client_id=#{::Sorcery::Controller::Config.salesforce.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope#{'=' + ::Sorcery::Controller::Config.salesforce.scope unless ::Sorcery::Controller::Config.salesforce.scope.nil?}&state",
slack: "https://slack.com/oauth/authorize?client_id=#{::Sorcery::Controller::Config.slack.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=identity.basic%2C+identity.email&state",
wechat: "https://open.weixin.qq.com/connect/qrconnect?appid=#{::Sorcery::Controller::Config.wechat.key}&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=snsapi_login&state=#wechat_redirect"
wechat: "https://open.weixin.qq.com/connect/qrconnect?appid=#{::Sorcery::Controller::Config.wechat.key}&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=snsapi_login&state=#wechat_redirect",
microsoft: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=#{::Sorcery::Controller::Config.microsoft.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=openid+email+https%3A%2F%2Fgraph.microsoft.com%2FUser.Read&state"
}[provider]
end
end
20 changes: 20 additions & 0 deletions spec/rails_app/app/controllers/sorcery_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ def login_at_test_wechat
login_at(:wechat)
end

def login_at_test_microsoft
login_at(:microsoft)
end

def login_at_test_google
login_at(:google)
end
Expand Down Expand Up @@ -174,6 +178,14 @@ def test_login_from_wechat
end
end

def test_login_from_microsoft
if @user = login_from(:microsoft)
redirect_to 'bla', notice: 'Success!'
else
redirect_to 'blu', alert: 'Failed!'
end
end

def test_login_from_google
if @user = login_from(:google)
redirect_to 'bla', notice: 'Success!'
Expand Down Expand Up @@ -272,6 +284,14 @@ def test_return_to_with_external_wechat
end
end

def test_return_to_with_external_microsoft
if @user = login_from(:microsoft)
redirect_back_or_to 'bla', notice: 'Success!'
else
redirect_to 'blu', alert: 'Failed!'
end
end

def test_return_to_with_external_google
if @user = login_from(:google)
redirect_back_or_to 'bla', notice: 'Success!'
Expand Down
3 changes: 3 additions & 0 deletions spec/rails_app/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
get :test_login_from_github
get :test_login_from_paypal
get :test_login_from_wechat
get :test_login_from_microsoft
get :test_login_from_google
get :test_login_from_liveid
get :test_login_from_vk
Expand All @@ -34,6 +35,7 @@
get :login_at_test_github
get :login_at_test_paypal
get :login_at_test_wechat
get :login_at_test_microsoft
get :login_at_test_google
get :login_at_test_liveid
get :login_at_test_vk
Expand All @@ -46,6 +48,7 @@
get :test_return_to_with_external_github
get :test_return_to_with_external_paypal
get :test_return_to_with_external_wechat
get :test_return_to_with_external_microsoft
get :test_return_to_with_external_google
get :test_return_to_with_external_liveid
get :test_return_to_with_external_vk
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require 'rails/all'
require 'rspec/rails'
require 'timecop'
require 'byebug'

def setup_orm; end

Expand Down