Skip to content

Commit 147dfb9

Browse files
committed
Merge branch 'master' into hotfix-twitter-login
2 parents 97395a7 + 0cda67d commit 147dfb9

File tree

9 files changed

+132
-36
lines changed

9 files changed

+132
-36
lines changed

README.md

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
1-
[![Build Status](https://travis-ci.org/NoamB/sorcery.svg?branch=master)](https://travis-ci.org/NoamB/sorcery)
2-
[![Code Climate](https://codeclimate.com/github/NoamB/sorcery.png)](https://codeclimate.com/github/NoamB/sorcery)
3-
[![Inline docs](http://inch-ci.org/github/NoamB/sorcery.png?branch=master)](http://inch-ci.org/github/NoamB/sorcery)
1+
# Sorcery: Magical Authentication
42

5-
# sorcery
6-
7-
## MAINTAINER NEEDED
8-
9-
Currently Sorcery project is not actively maintained. I (@arnvald) try to keep looking at issues and help with any problems, but I don't develop the library anymore.
10-
Therefore if you are interested in taking over the project, please check this issue: [https://github.com/NoamB/sorcery/issues/777](https://github.com/NoamB/sorcery/issues/777)
3+
[![Gem Version](https://badge.fury.io/rb/sorcery.svg)](https://rubygems.org/gems/sorcery)
4+
[![Gem Downloads](https://img.shields.io/gem/dt/sorcery.svg)](https://rubygems.org/gems/sorcery)
5+
[![Build Status](https://travis-ci.org/Sorcery/sorcery.svg?branch=master)](https://travis-ci.org/Sorcery/sorcery)
6+
[![Code Climate](https://codeclimate.com/github/Sorcery/sorcery.svg)](https://codeclimate.com/github/Sorcery/sorcery)
7+
[![Inline docs](http://inch-ci.org/github/Sorcery/sorcery.svg?branch=master)](http://inch-ci.org/github/Sorcery/sorcery)
8+
[![Join the chat at https://gitter.im/Sorcery/sorcery](https://badges.gitter.im/join_chat.svg)](https://gitter.im/Sorcery/sorcery?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
119

1210
## Project
1311

14-
[![Join the chat at https://gitter.im/NoamB/sorcery](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/NoamB/sorcery?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
1512
Magical Authentication for Rails. Supports ActiveRecord,
1613
DataMapper, Mongoid and MongoMapper.
1714

1815
Inspired by restful_authentication, Authlogic and Devise. Crypto code taken
1916
almost unchanged from Authlogic. OAuth code inspired by OmniAuth and Ryan
2017
Bates's railscasts about it.
2118

22-
**Rails 5 status:** [Sorcery 0.9.1](http://rubygems.org/gems/sorcery/versions/0.9.0) should work fine with Rails 5. We can't guarantee it at this point, though, so please open an issue for any problem with Rails 5.
19+
**Rails 5 status:** [Sorcery 0.9.1](http://rubygems.org/gems/sorcery/versions/0.9.1) should work fine with Rails 5. We can't guarantee it at this point, though, so please open an issue for any problem with Rails 5.
20+
2321
**Rails 4 status:** [Sorcery 0.9.0](http://rubygems.org/gems/sorcery/versions/0.9.0) is fully tested and ready for Rails 4.0, 4.1 and 4.2.
22+
2423
**Mongoid status:** Version 0.9.0 works with Mongoid 4.
2524

26-
https://github.com/NoamB/sorcery/wiki/Simple-Password-Authentication
25+
https://github.com/Sorcery/sorcery/wiki/Simple-Password-Authentication
2726

2827
## Philosophy
2928

@@ -44,10 +43,11 @@ can write your own authentication flow. It was built with a few goals in mind:
4443
Hopefully, I've achieved this. If not, let me know.
4544

4645
## Useful Links
46+
4747
[Documentation](http://rubydoc.info/gems/sorcery) |
48-
[Railscast](http://railscasts.com/episodes/283-authentication-with-sorcery) | [Simple tutorial](https://github.com/NoamB/sorcery/wiki/Simple-Password-Authentication) | [Example Rails 4 app](https://github.com/NoamB/sorcery-example-app)
48+
[Railscast](http://railscasts.com/episodes/283-authentication-with-sorcery) | [Simple tutorial](https://github.com/Sorcery/sorcery/wiki/Simple-Password-Authentication) | [Example Rails 4 app](https://github.com/Sorcery/sorcery-example-app)
4949

50-
Check out the tutorials in the [Wiki](https://github.com/NoamB/sorcery/wiki) for more!
50+
Check out the tutorials in the [Wiki](https://github.com/Sorcery/sorcery/wiki) for more!
5151

5252
## API Summary
5353

@@ -56,6 +56,7 @@ explaining and the rest are commented:
5656

5757

5858
### core
59+
5960
```ruby
6061
require_login # this is a before action
6162
login(email, password, remember_me = false)
@@ -71,18 +72,21 @@ User.authenticates_with_sorcery!
7172
```
7273

7374
### http basic auth
75+
7476
```ruby
7577
require_login_from_http_basic # this is a before action
7678
```
7779

7880
### external
81+
7982
```ruby
8083
login_at(provider) # sends the user to an external service (twitter etc.) to authenticate.
8184
login_from(provider) # tries to login from the external provider's callback.
8285
create_from(provider) # create the user in the local app db.
8386
```
8487

8588
### remember me
89+
8690
```ruby
8791
auto_login(user, should_remember=false) # login without credentials, optional remember_me
8892
remember_me!
@@ -91,6 +95,7 @@ force_forget_me! # completely forgets all sessions by clearing the token, eve
9195
```
9296

9397
### reset password
98+
9499
```ruby
95100
User.load_from_reset_password_token(token)
96101
@user.generate_reset_password_token! # if you want to send the email by youself
@@ -99,6 +104,7 @@ User.load_from_reset_password_token(token)
99104
```
100105

101106
### user activation
107+
102108
```ruby
103109
User.load_from_activation_token(token)
104110
@user.setup_activation
@@ -186,12 +192,13 @@ end
186192
Sidekiq and Resque integrations are coming soon.
187193

188194
## Single Table Inheritance (STI) Support
195+
189196
STI is supported via the `user.subclasses_inherit_config` setting in config/initializers/sorcery.rb.
190197

191198
## Full Features List by module
192199

193-
**Core** (see [lib/sorcery/model.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model.rb) and
194-
[lib/sorcery/controller.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/controller.rb)):
200+
**Core** (see [lib/sorcery/model.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model.rb) and
201+
[lib/sorcery/controller.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller.rb)):
195202

196203
* login/logout, optional return user to requested url on login, configurable
197204
redirect for non-logged-in users.
@@ -201,7 +208,7 @@ STI is supported via the `user.subclasses_inherit_config` setting in config/init
201208
* allow multiple fields to serve as username.
202209

203210

204-
**User Activation** (see [lib/sorcery/model/submodules/user_activation.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model/submodules/user_activation.rb)):
211+
**User Activation** (see [lib/sorcery/model/submodules/user_activation.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model/submodules/user_activation.rb)):
205212

206213
* User activation by email with optional success email.
207214
* configurable attribute names.
@@ -210,49 +217,49 @@ STI is supported via the `user.subclasses_inherit_config` setting in config/init
210217
* Optionally prevent non-active users to login.
211218

212219

213-
**Reset Password** (see [lib/sorcery/model/submodules/reset_password.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model/submodules/reset_password.rb)):
220+
**Reset Password** (see [lib/sorcery/model/submodules/reset_password.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model/submodules/reset_password.rb)):
214221

215222
* Reset password with email verification.
216223
* configurable mailer, method name, and attribute name.
217224
* configurable temporary token expiration.
218225
* configurable time between emails (hammering protection).
219226

220227

221-
**Remember Me** (see [lib/sorcery/model/submodules/remember_me.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model/submodules/remember_me.rb)):
228+
**Remember Me** (see [lib/sorcery/model/submodules/remember_me.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model/submodules/remember_me.rb)):
222229

223230
* Remember me with configurable expiration.
224231
* configurable attribute names.
225232
* configurable to persist globally (supporting multiple browsers at the same time), or starting anew after each login
226233

227234

228-
**Session Timeout** (see [lib/sorcery/controller/submodules/session_timeout.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/controller/submodules/session_timeout.rb)):
235+
**Session Timeout** (see [lib/sorcery/controller/submodules/session_timeout.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller/submodules/session_timeout.rb)):
229236

230237
* Configurable session timeout.
231238
* Optionally session timeout will be calculated from last user action.
232239

233240

234-
**Brute Force Protection** (see [lib/sorcery/model/submodules/brute_force_protection.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model/submodules/brute_force_protection.rb)):
241+
**Brute Force Protection** (see [lib/sorcery/model/submodules/brute_force_protection.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model/submodules/brute_force_protection.rb)):
235242

236243
* Brute force login hammering protection.
237244
* configurable logins before lock and lock duration.
238245

239246

240-
**Basic HTTP Authentication** (see [lib/sorcery/controller/submodules/http_basic_auth.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/controller/submodules/http_basic_auth.rb)):
247+
**Basic HTTP Authentication** (see [lib/sorcery/controller/submodules/http_basic_auth.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller/submodules/http_basic_auth.rb)):
241248

242249
* A before action for requesting authentication with HTTP Basic.
243250
* automatic login from HTTP Basic.
244251
* automatic login is disabled if session key changed.
245252

246253

247-
**Activity Logging** (see [lib/sorcery/model/submodules/activity_logging.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/model/submodules/activity_logging.rb)):
254+
**Activity Logging** (see [lib/sorcery/model/submodules/activity_logging.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/model/submodules/activity_logging.rb)):
248255

249256
* automatic logging of last login, last logout, last activity time and IP
250257
address for last login.
251258
* configurable timeout by which to decide whether to include a user in the
252259
list of logged in users.
253260

254261

255-
**External** (see [lib/sorcery/controller/submodules/external.rb](https://github.com/NoamB/sorcery/blob/master/lib/sorcery/controller/submodules/external.rb)):
262+
**External** (see [lib/sorcery/controller/submodules/external.rb](https://github.com/Sorcery/sorcery/blob/master/lib/sorcery/controller/submodules/external.rb)):
256263

257264
* OAuth1 and OAuth2 support (currently: Twitter, Facebook, Github, Google, Heroku,
258265
LinkedIn, VK, LiveID, Xing, and Salesforce)

lib/generators/sorcery/templates/initializer.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

7474

7575
# -- external --
76-
# What providers are supported by this app, i.e. [:twitter, :facebook, :github, :linkedin, :xing, :google, :liveid, :salesforce] .
76+
# What providers are supported by this app, i.e. [:twitter, :facebook, :github, :linkedin, :xing, :google, :liveid, :salesforce, :slack] .
7777
# Default: `[]`
7878
#
7979
# config.external_providers =
@@ -144,6 +144,11 @@
144144
# config.vk.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=vk"
145145
# config.vk.user_info_mapping = {:login => "domain", :name => "full_name"}
146146
#
147+
#config.slack.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=slack"
148+
#config.slack.key = ''
149+
#config.slack.secret = ''
150+
#config.slack.user_info_mapping = {email: 'email'}
151+
#
147152
# To use liveid in development mode you have to replace mydomain.com with
148153
# a valid domain even in development. To use a valid domain in development
149154
# simply add your domain in your /etc/hosts file in front of 127.0.0.1

lib/sorcery/controller/submodules/external.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def self.included(base)
2020
require 'sorcery/providers/jira'
2121
require 'sorcery/providers/salesforce'
2222
require 'sorcery/providers/paypal'
23+
require 'sorcery/providers/slack'
2324

2425
Config.module_eval do
2526
class << self

lib/sorcery/providers/slack.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
module Sorcery
2+
module Providers
3+
# This class adds support for OAuth with slack.com.
4+
5+
class Slack < Base
6+
7+
include Protocols::Oauth2
8+
9+
attr_accessor :auth_path, :scope, :token_url, :user_info_path
10+
11+
def initialize
12+
super
13+
14+
@scope = 'identity.basic, identity.email'
15+
@site = 'https://slack.com/'
16+
@user_info_path = 'https://slack.com/api/users.identity'
17+
@auth_path = '/oauth/authorize'
18+
@token_url = '/api/oauth.access'
19+
end
20+
21+
def get_user_hash(access_token)
22+
response = access_token.get(user_info_path, params: { token: access_token.token })
23+
auth_hash(access_token).tap do |h|
24+
h[:user_info] = JSON.parse(response.body)
25+
h[:user_info]['email'] = h[:user_info]['user']['email']
26+
h[:uid] = h[:user_info]['user']['id']
27+
end
28+
end
29+
30+
# calculates and returns the url to which the user should be redirected,
31+
# to get authenticated at the external provider's site.
32+
def login_url(params, session)
33+
authorize_url({ authorize_url: auth_path })
34+
end
35+
36+
# tries to login the user from access token
37+
def process_callback(params, session)
38+
args = {}.tap do |a|
39+
a[:code] = params[:code] if params[:code]
40+
end
41+
42+
get_access_token(args, token_url: token_url, token_method: :post)
43+
end
44+
end
45+
end
46+
end

sorcery.gemspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,3 @@ Gem::Specification.new do |s|
3434
s.add_development_dependency "rspec-rails", "~> 3.1.0"
3535
s.add_development_dependency "test-unit", "~> 3.1.0"
3636
end
37-

spec/controllers/controller_oauth2_spec.rb

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
expect(flash[:notice]).to eq "Success!"
153153
end
154154

155-
[:github, :google, :liveid, :vk, :salesforce, :paypal].each do |provider|
155+
[:github, :google, :liveid, :vk, :salesforce, :paypal, :slack].each do |provider|
156156

157157
describe "with #{provider}" do
158158

@@ -205,7 +205,7 @@
205205
end
206206

207207
sorcery_reload!([:user_activation,:external], :user_activation_mailer => ::SorceryMailer)
208-
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal])
208+
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack])
209209

210210
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
211211
sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
@@ -228,8 +228,13 @@
228228
sorcery_controller_external_property_set(:paypal, :key, "eYVNBjBDi33aa9GkA3w")
229229
sorcery_controller_external_property_set(:paypal, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
230230
sorcery_controller_external_property_set(:paypal, :callback_url, "http://blabla.com")
231+
sorcery_controller_external_property_set(:slack, :key, "eYVNBjBDi33aa9GkA3w")
232+
sorcery_controller_external_property_set(:slack, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
233+
sorcery_controller_external_property_set(:slack, :callback_url, "http://blabla.com")
231234
end
232235

236+
237+
233238
after(:all) do
234239
if SORCERY_ORM == :active_record
235240
ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/activation")
@@ -287,7 +292,7 @@
287292
end
288293
end
289294

290-
%w(facebook github google liveid vk salesforce).each do |provider|
295+
%w(facebook github google liveid vk salesforce slack).each do |provider|
291296
context "when #{provider}" do
292297
before(:each) do
293298
sorcery_controller_property_set(:register_login_time, true)
@@ -327,7 +332,7 @@
327332

328333
let(:user) { double('user', id: 42) }
329334

330-
%w(facebook github google liveid vk salesforce).each do |provider|
335+
%w(facebook github google liveid vk salesforce slack).each do |provider|
331336
context "when #{provider}" do
332337
before(:each) do
333338
sorcery_model_property_set(:authentications_class, Authentication)
@@ -389,7 +394,13 @@ def stub_all_oauth2_requests!
389394
"first_name"=>"Noam",
390395
"last_name"=>"Ben Ari"
391396
}
392-
]}.to_json }
397+
],
398+
"user"=> {
399+
"name"=>"Sonny Whether",
400+
"id"=>"123",
401+
"email"=>"bobby@example.com"
402+
}
403+
}.to_json }
393404
allow(access_token).to receive(:get) { response }
394405
allow(access_token).to receive(:token) { "187041a618229fdaf16613e96e1caabc1e86e46bbfad228de41520e63fe45873684c365a14417289599f3" }
395406
# access_token params for VK auth
@@ -398,7 +409,7 @@ def stub_all_oauth2_requests!
398409
end
399410

400411
def set_external_property
401-
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal])
412+
sorcery_controller_property_set(:external_providers, [:facebook, :github, :google, :liveid, :vk, :salesforce, :paypal, :slack])
402413
sorcery_controller_external_property_set(:facebook, :key, "eYVNBjBDi33aa9GkA3w")
403414
sorcery_controller_external_property_set(:facebook, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
404415
sorcery_controller_external_property_set(:facebook, :callback_url, "http://blabla.com")
@@ -420,6 +431,9 @@ def set_external_property
420431
sorcery_controller_external_property_set(:paypal, :key, "eYVNBjBDi33aa9GkA3w")
421432
sorcery_controller_external_property_set(:paypal, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
422433
sorcery_controller_external_property_set(:paypal, :callback_url, "http://blabla.com")
434+
sorcery_controller_external_property_set(:slack, :key, "eYVNBjBDi33aa9GkA3w")
435+
sorcery_controller_external_property_set(:slack, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
436+
sorcery_controller_external_property_set(:slack, :callback_url, "http://blabla.com")
423437
end
424438

425439
def provider_url(provider)
@@ -429,7 +443,8 @@ def provider_url(provider)
429443
google: "https://accounts.google.com/o/oauth2/auth?client_id=#{::Sorcery::Controller::Config.google.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&state",
430444
liveid: "https://oauth.live.com/authorize?client_id=#{::Sorcery::Controller::Config.liveid.key}&display&redirect_uri=http%3A%2F%2Fblabla.com&response_type=code&scope=wl.basic+wl.emails+wl.offline_access&state",
431445
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",
432-
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"
446+
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",
447+
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"
433448
}[provider]
434449
end
435450
end

spec/rails_app/app/controllers/sorcery_controller.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ def login_at_test_salesforce
121121
login_at(:salesforce)
122122
end
123123

124+
def login_at_test_slack
125+
login_at(:slack)
126+
end
127+
124128
def login_at_test_with_state
125129
login_at(:facebook, {state: 'bla'})
126130
end
@@ -199,6 +203,14 @@ def test_login_from_salesforce
199203
end
200204
end
201205

206+
def test_login_from_slack
207+
if @user = login_from(:slack)
208+
redirect_to 'bla', notice: 'Success!'
209+
else
210+
redirect_to 'blu', alert: 'Failed!'
211+
end
212+
end
213+
202214
def test_return_to_with_external_twitter
203215
if @user = login_from(:twitter)
204216
redirect_back_or_to 'bla', notice: 'Success!'
@@ -273,6 +285,14 @@ def test_return_to_with_external_salesforce
273285
end
274286
end
275287

288+
def test_return_to_with_external_slack
289+
if @user = login_from(:slack)
290+
redirect_back_or_to 'bla', notice: 'Success!'
291+
else
292+
redirect_to 'blu', alert: 'Failed!'
293+
end
294+
end
295+
276296
def test_create_from_provider
277297
provider = params[:provider]
278298
login_from(provider)

0 commit comments

Comments
 (0)