exvo_auth 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +245 -0
- data/Rakefile +11 -0
- data/exvo_auth.gemspec +33 -0
- data/lib/exvo_auth.rb +31 -0
- data/lib/exvo_auth/autonomous/auth.rb +18 -0
- data/lib/exvo_auth/autonomous/base.rb +20 -0
- data/lib/exvo_auth/autonomous/cache.rb +33 -0
- data/lib/exvo_auth/autonomous/consumer.rb +36 -0
- data/lib/exvo_auth/autonomous/http.rb +43 -0
- data/lib/exvo_auth/autonomous/provider.rb +24 -0
- data/lib/exvo_auth/controllers/base.rb +123 -0
- data/lib/exvo_auth/controllers/merb.rb +27 -0
- data/lib/exvo_auth/controllers/rails.rb +19 -0
- data/lib/exvo_auth/dejavu.rb +24 -0
- data/lib/exvo_auth/middleware.rb +15 -0
- data/lib/exvo_auth/models/message.rb +72 -0
- data/lib/exvo_auth/session_store.rb +37 -0
- data/lib/exvo_auth/version.rb +3 -0
- data/test/helper.rb +9 -0
- data/test/test_exvo_auth.rb +42 -0
- data/test/test_integration.rb +17 -0
- metadata +216 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright © 2011-2012 Exvo.com Development BV
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
# exvo_auth
|
2
|
+
|
3
|
+
This gem supplements the [omniauth-exvo](https://github.com/Exvo/omniauth-exvo/) gem. Together they implement the oauth2 protocol for handling users and applications authentication at Exvo.
|
4
|
+
|
5
|
+
This gem depends on the [exvo_helpers](https://github.com/Exvo/exvo_helpers) gem for all of its configuration.
|
6
|
+
|
7
|
+
|
8
|
+
Note, that this gem was previously named "exvo-auth".
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
## Requirements
|
13
|
+
|
14
|
+
* Runs on Ruby 1.8.7 & 1.9.2 (preferred version)
|
15
|
+
* Rails 3.0+ (works with Rails 3.1) or Merb
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
## Installation
|
20
|
+
|
21
|
+
Add it to Gemfile:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
gem "exvo_auth"
|
25
|
+
```
|
26
|
+
|
27
|
+
Run bundle:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
$ bundle
|
31
|
+
```
|
32
|
+
|
33
|
+
The preferred way to configure this gem is via the ENV variables:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
ENV['AUTH_CLIENT_ID'] = "foo"
|
37
|
+
ENV['AUTH_CLIENT_SECRET'] = "bar"
|
38
|
+
ENV['AUTH_DEBUG'] = "true" # [OPTIONAL] dumps all HTTP traffic to STDERR, useful during development; it *has to be a string, not a boolean*
|
39
|
+
ENV['AUTH_REQUIRE_SSL'] = "false" # [OPTIONAL] disable SSL, useful in development (note that all apps API urls must be http, not https); it *has to be a string, not a boolean*
|
40
|
+
ENV['AUTH_HOST'] = "test.exvo.com" # [OPTIONAL] override the default auth host
|
41
|
+
```
|
42
|
+
|
43
|
+
But you can also set things directly in the `config/application.rb` file (before the middleware declaration):
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
Exvo::Helpers.auth_client_id = "foo"
|
47
|
+
Exvo::Helpers.auth_client_secret = "bar"
|
48
|
+
Exvo::Helpers.auth_debug = true # boolean
|
49
|
+
Exvo::Helpers.auth_require_ssl = false # boolean
|
50
|
+
Exvo::Helpers.auth_host = "test.exvo.com"
|
51
|
+
```
|
52
|
+
|
53
|
+
Add this line to `config/application.rb`:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
config.middleware.use ExvoAuth::Middleware
|
57
|
+
```
|
58
|
+
|
59
|
+
Add routes (Rails example):
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
match "/auth/exvo/callback" => "sessions#create"
|
63
|
+
match "/auth/failure" => "sessions#failure"
|
64
|
+
match "/sign_out" => "sessions#destroy"
|
65
|
+
```
|
66
|
+
|
67
|
+
Include controller helpers in your `ApplicationController.rb`:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
include ExvoAuth::Controllers::Rails # (or Merb)
|
71
|
+
```
|
72
|
+
|
73
|
+
Implement a sessions controller (Rails example):
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class SessionsController < ApplicationController
|
77
|
+
def create
|
78
|
+
sign_in_and_redirect!
|
79
|
+
end
|
80
|
+
|
81
|
+
def destroy
|
82
|
+
sign_out_and_redirect!
|
83
|
+
end
|
84
|
+
|
85
|
+
def failure
|
86
|
+
render :text => "Sorry!"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
It's good to have your `SessionsController`'s `#create` action a little more extended, so that each time the user logs in into the app, his user data (like email, nickname, etc.) is updated from the auth app (i.e. from his profile):
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
def create
|
95
|
+
auth_hash = request.env["omniauth.auth"]
|
96
|
+
user = User.find_or_create_by_uid(auth_hash["uid"])
|
97
|
+
|
98
|
+
if user && user.update_from_auth_hash(auth_hash)
|
99
|
+
sign_in_and_redirect!
|
100
|
+
else
|
101
|
+
fail "Could not update user"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
106
|
+
and your `#update_from_auth_hash` method at `User` model might look like this:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
def update_from_auth_hash(auth_hash)
|
110
|
+
update_attributes({
|
111
|
+
:nickname => auth_hash["info"]["nickname"],
|
112
|
+
:email => auth_hash["info"]["email"],
|
113
|
+
:plan => auth_hash["extra"]["raw_info"]["plan"],
|
114
|
+
:language => auth_hash["extra"]["raw_info"]["language"]
|
115
|
+
})
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
Note, that you don't have to update all user attributes. You can update only ones you want.
|
120
|
+
|
121
|
+
|
122
|
+
This is what you get (and what you can use/save for the local user) from auth (example data as of 2012-01):
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
request.env["omniauth.auth"].to_hash.inspect
|
126
|
+
|
127
|
+
{
|
128
|
+
"provider" => "exvo",
|
129
|
+
"uid" => 1,
|
130
|
+
|
131
|
+
"credentials" => {
|
132
|
+
"token" => "a2d09701559b9f26a8284d6f94670477d882ad6d9f3d92ce9917262a6b54085fa3fb99e111340459",
|
133
|
+
"expires" => false
|
134
|
+
},
|
135
|
+
|
136
|
+
"info" => {
|
137
|
+
"nickname" => "Pawel",
|
138
|
+
"email" => "pawel@exvo.com",
|
139
|
+
"name" => "Pawel"
|
140
|
+
},
|
141
|
+
|
142
|
+
"extra" => {
|
143
|
+
"raw_info" => {
|
144
|
+
"id" => 1,
|
145
|
+
"nickname" => "Pawel",
|
146
|
+
"country_code" => nil,
|
147
|
+
"plan" => "basic",
|
148
|
+
"language" => "en",
|
149
|
+
"email" => "pawel@exvo.com",
|
150
|
+
"referring_user_id" => nil
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
154
|
+
```
|
155
|
+
|
156
|
+
|
157
|
+
Implement `#find_or_create_user_by_uid(uid)` in your `ApplicationController`:
|
158
|
+
|
159
|
+
This method will be called by `#current_user`. Previously we did this in `sessions_controller` but since the sharing sessions changes this controller will not be used in most cases because the session comes from another app through a shared cookie. This method should find user by uid or create it.
|
160
|
+
|
161
|
+
Exemplary implementation (Rails):
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
def find_or_create_user_by_uid(uid)
|
165
|
+
User.find_or_create_by_uid(uid)
|
166
|
+
end
|
167
|
+
```
|
168
|
+
|
169
|
+
It's best to leave this method as it is (without updating any user data inside this method, better to do this in the SessionsController#create action). Updating user in this method might lead to some very hard to debug cyclic executions possibly leading to stack-level too deep errors and/or general slowness, so please proceed with extreme caution.
|
170
|
+
|
171
|
+
|
172
|
+
## Sign up and sign in paths for use in links
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
sign in path: "/auth/exvo"
|
176
|
+
sign up path: "/auth/exvo?x_sign_up=true" # this is OAuth2 custom param
|
177
|
+
sign in path with a return address: "/auth/exvo?state=url" # using OAuth2 state param
|
178
|
+
```
|
179
|
+
|
180
|
+
You have a handy methods available in controllers (and views in Rails): `sign_in_path` and `sign_up_path`.
|
181
|
+
|
182
|
+
|
183
|
+
## Require authentication in your controllers
|
184
|
+
|
185
|
+
In `ApplicationController` (for all controllers) or in some controller just add:
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
before_filter :authenticate_user!
|
189
|
+
```
|
190
|
+
|
191
|
+
## Fetching user information
|
192
|
+
|
193
|
+
All info about any particular user can be obtained using auth api (`/users/uid.json` path).
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
## Inter-Application Communication
|
198
|
+
|
199
|
+
You need to have "App Authorization" created by Exvo first.
|
200
|
+
|
201
|
+
Contact us and provide following details:
|
202
|
+
|
203
|
+
* `consumer_id` - Id of an app that will be a consumer (this is you)
|
204
|
+
* `provider_id` - Id of the provider app
|
205
|
+
* `scope` - The tag associated with the api you want to use in the provider app
|
206
|
+
|
207
|
+
|
208
|
+
### Consumer side
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
consumer = ExvoAuth::Autonomous::Consumer.new(
|
212
|
+
:app_id => "this is client_id of the app you want to connect to"
|
213
|
+
)
|
214
|
+
consumer.get(*args) # interface is exactly the same like in HTTParty. All http methods are available (post, put, delete, head, options).
|
215
|
+
```
|
216
|
+
|
217
|
+
|
218
|
+
### Provider side
|
219
|
+
|
220
|
+
See `#authenticate_app_in_scope!(scope)` method in `ExvoAuth::Controllers::Rails` (or Merb). This method lets you create a before filter.
|
221
|
+
Scopes are used by providing app to check if a given consuming app should have access to a given resource inside a scope.
|
222
|
+
If scopes are empty, then provider app should not present any resources to consumer.
|
223
|
+
|
224
|
+
|
225
|
+
Example of the before filter for provider controller:
|
226
|
+
|
227
|
+
```ruby
|
228
|
+
before_filter { |c| c.authenticate_app_in_scope!("payments") }
|
229
|
+
```
|
230
|
+
|
231
|
+
In the provider controller, which is just a fancy name for API controller, you can use `#current_app_id` method to get the `app_id` of the app connecting.
|
232
|
+
|
233
|
+
|
234
|
+
## Dejavu
|
235
|
+
|
236
|
+
Replay non-GET requests after authentication redirects.
|
237
|
+
|
238
|
+
Limitations:
|
239
|
+
|
240
|
+
* doesn't work with file uploads
|
241
|
+
* all request params become query params when replayed
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
Copyright © 2011-2012 Exvo.com Development BV, released under the MIT license
|
data/Rakefile
ADDED
data/exvo_auth.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "exvo_auth/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "exvo_auth"
|
7
|
+
gem.version = ExvoAuth::VERSION
|
8
|
+
gem.authors = ["Jacek Becela", "Paweł Gościcki"]
|
9
|
+
gem.email = ["jacek.becela@gmail.com", "pawel.goscicki@gmail.com"]
|
10
|
+
gem.homepage = "https://github.com/Exvo/exvo_auth"
|
11
|
+
gem.summary = "User and App authentication for Exvo"
|
12
|
+
gem.description = "Collection of users and applications authentication methods for use when you want your users or applications authorize using the Exvo platform."
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split("\n")
|
15
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.add_dependency "httparty"
|
20
|
+
gem.add_dependency "activemodel", "~> 3.0"
|
21
|
+
gem.add_dependency "actionpack", "~> 3.0"
|
22
|
+
gem.add_dependency "exvo_helpers", "~> 0.2"
|
23
|
+
|
24
|
+
gem.add_development_dependency "mocha"
|
25
|
+
gem.add_development_dependency "test-unit"
|
26
|
+
gem.add_development_dependency "rake"
|
27
|
+
gem.add_development_dependency "guard"
|
28
|
+
gem.add_development_dependency "guard-test"
|
29
|
+
gem.add_development_dependency "rb-fsevent"
|
30
|
+
gem.add_development_dependency "rb-inotify"
|
31
|
+
gem.add_development_dependency "simplecov"
|
32
|
+
gem.add_development_dependency "simplecov-rcov"
|
33
|
+
end
|
data/lib/exvo_auth.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
require 'httparty'
|
3
|
+
require 'uri'
|
4
|
+
require 'base64'
|
5
|
+
require 'exvo_helpers'
|
6
|
+
|
7
|
+
module ExvoAuth
|
8
|
+
autoload :Middleware, 'exvo_auth/middleware'
|
9
|
+
autoload :SessionStore, 'exvo_auth/session_store'
|
10
|
+
autoload :Dejavu, 'exvo_auth/dejavu'
|
11
|
+
autoload :VERSION, 'exvo_auth/version'
|
12
|
+
|
13
|
+
module Controllers
|
14
|
+
autoload :Base, 'exvo_auth/controllers/base'
|
15
|
+
autoload :Rails, 'exvo_auth/controllers/rails'
|
16
|
+
autoload :Merb, 'exvo_auth/controllers/merb'
|
17
|
+
end
|
18
|
+
|
19
|
+
module Models
|
20
|
+
autoload :Message, 'exvo_auth/models/message'
|
21
|
+
end
|
22
|
+
|
23
|
+
module Autonomous
|
24
|
+
autoload :Base, 'exvo_auth/autonomous/base'
|
25
|
+
autoload :Consumer, 'exvo_auth/autonomous/consumer'
|
26
|
+
autoload :Provider, 'exvo_auth/autonomous/provider'
|
27
|
+
autoload :Cache, 'exvo_auth/autonomous/cache'
|
28
|
+
autoload :Auth, 'exvo_auth/autonomous/auth'
|
29
|
+
autoload :Http, 'exvo_auth/autonomous/http'
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
class ExvoAuth::Autonomous::Auth
|
4
|
+
include Singleton
|
5
|
+
include ExvoAuth::Autonomous::Http
|
6
|
+
|
7
|
+
def base_uri
|
8
|
+
Exvo::Helpers.auth_uri
|
9
|
+
end
|
10
|
+
|
11
|
+
def username
|
12
|
+
Exvo::Helpers.auth_client_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def password
|
16
|
+
Exvo::Helpers.auth_client_secret
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class ExvoAuth::Autonomous::Base
|
2
|
+
attr_reader :params
|
3
|
+
@@cache = ExvoAuth::Autonomous::Cache.new
|
4
|
+
|
5
|
+
def initialize(params = {})
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def validate_params!(*keys)
|
12
|
+
missing = keys - params.keys
|
13
|
+
raise(ArgumentError, "Please configure following keys: #{missing.join(", ")}") if missing.any?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Makes testing easy
|
17
|
+
def auth
|
18
|
+
ExvoAuth::Autonomous::Auth.instance
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class ExvoAuth::Autonomous::Cache
|
2
|
+
def initialize
|
3
|
+
@data = {}
|
4
|
+
end
|
5
|
+
|
6
|
+
def read(key)
|
7
|
+
o = @data[key]
|
8
|
+
o[:value] if o && (now - o[:timestamp]) < 3600 # cache for one hour
|
9
|
+
end
|
10
|
+
|
11
|
+
def write(key, value)
|
12
|
+
@data[key] = {
|
13
|
+
:value => value,
|
14
|
+
:timestamp => now
|
15
|
+
}
|
16
|
+
|
17
|
+
value
|
18
|
+
end
|
19
|
+
|
20
|
+
def fetch(key)
|
21
|
+
if block_given?
|
22
|
+
read(key) || write(key, yield)
|
23
|
+
else
|
24
|
+
read(key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def now
|
31
|
+
Time.now
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class ExvoAuth::Autonomous::Consumer < ExvoAuth::Autonomous::Base
|
2
|
+
include ExvoAuth::Autonomous::Http
|
3
|
+
|
4
|
+
def initialize(params = {})
|
5
|
+
super
|
6
|
+
validate_params!(:app_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
def base_uri
|
10
|
+
authorization["url"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def username
|
14
|
+
Exvo::Helpers.auth_client_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def password
|
18
|
+
authorization["access_token"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def authorization
|
22
|
+
@@cache.fetch(params) do
|
23
|
+
authorization!
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def authorization!
|
28
|
+
response = auth.get("/apps/consumer/authorizations/#{URI.escape(params[:app_id])}.json")
|
29
|
+
|
30
|
+
if response["authorization"]
|
31
|
+
@@cache.write(params, response["authorization"])
|
32
|
+
else
|
33
|
+
raise "Authorization not found. You need an auhorization to contact provider app (#{ params[:app_id] })"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ExvoAuth::Autonomous::Http
|
2
|
+
def get(*args)
|
3
|
+
http.get(*args)
|
4
|
+
end
|
5
|
+
|
6
|
+
def post(*args)
|
7
|
+
http.post(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def put(path, options = {})
|
11
|
+
# This fixes 411 responses from nginx (on heroku)
|
12
|
+
# when Content-Length is missing on put requests.
|
13
|
+
options[:body] ||= ""
|
14
|
+
http.put(path, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete(*args)
|
18
|
+
http.delete(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
def head(*args)
|
22
|
+
http.head(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def options(*args)
|
26
|
+
http.options(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def http
|
32
|
+
basement.base_uri(base_uri)
|
33
|
+
basement.basic_auth(username, password)
|
34
|
+
basement
|
35
|
+
end
|
36
|
+
|
37
|
+
def basement
|
38
|
+
@basement ||= Class.new do
|
39
|
+
include HTTParty
|
40
|
+
debug_output if Exvo::Helpers.auth_debug
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ExvoAuth::Autonomous::Provider < ExvoAuth::Autonomous::Base
|
2
|
+
def initialize(params = {})
|
3
|
+
super
|
4
|
+
validate_params!(:app_id, :access_token)
|
5
|
+
end
|
6
|
+
|
7
|
+
def scopes
|
8
|
+
@@cache.fetch(params) do
|
9
|
+
scopes!
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def scopes!
|
14
|
+
response = auth.get("/apps/provider/authorizations/#{URI.escape(params[:app_id])}.json",
|
15
|
+
:query => { :access_token => params[:access_token] }
|
16
|
+
)
|
17
|
+
|
18
|
+
if scope = response["scope"]
|
19
|
+
@@cache.write(params, scope.split)
|
20
|
+
else
|
21
|
+
[] # only cache positive responses
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module ExvoAuth::Controllers::Base
|
2
|
+
# A before filter to protect your sensitive actions.
|
3
|
+
def authenticate_user!(opts = {})
|
4
|
+
if !signed_in?
|
5
|
+
store_request!
|
6
|
+
|
7
|
+
callback_value = params[callback_key]
|
8
|
+
|
9
|
+
if callback_value
|
10
|
+
redirect_to non_interactive_sign_in_path(callback_key => callback_value)
|
11
|
+
else
|
12
|
+
redirect_to opts[:redirect_to] || sign_in_path
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Usually this method is called from your sessions#create.
|
18
|
+
def sign_in_and_redirect!
|
19
|
+
session[:user_uid] = request.env["omniauth.auth"]["uid"]
|
20
|
+
|
21
|
+
url = if params[:state] == "popup"
|
22
|
+
Exvo::Helpers..auth_uri + "/close_popup.html"
|
23
|
+
elsif params[:state] # if not popup then an url
|
24
|
+
params[:state]
|
25
|
+
else
|
26
|
+
request_replay_url || "/"
|
27
|
+
end
|
28
|
+
|
29
|
+
redirect_to url
|
30
|
+
end
|
31
|
+
|
32
|
+
# Redirect to sign_out_url, signs out and redirects back to "/" (by default).
|
33
|
+
# Usuallly this method is called from your sessions#destroy.
|
34
|
+
def sign_out_and_redirect!(return_to = "/")
|
35
|
+
session.clear
|
36
|
+
remove_instance_variable(:@current_user) if instance_variable_defined?(:@current_user)
|
37
|
+
redirect_to sign_out_url(return_to)
|
38
|
+
end
|
39
|
+
|
40
|
+
def authenticate_app_in_scope!(scope)
|
41
|
+
raise("SSL not configured. Your api needs to be exposed using https protocol.") unless request.ssl? || Exvo::Helpers.auth_require_ssl == false
|
42
|
+
|
43
|
+
send(basic_authentication_method_name) do |app_id, access_token|
|
44
|
+
current_scopes = ExvoAuth::Autonomous::Provider.new(
|
45
|
+
:app_id => app_id,
|
46
|
+
:access_token => access_token
|
47
|
+
).scopes
|
48
|
+
|
49
|
+
@current_app_id = app_id
|
50
|
+
|
51
|
+
current_scopes.include?(scope.to_s)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def sign_in_path
|
56
|
+
"/auth/exvo"
|
57
|
+
end
|
58
|
+
|
59
|
+
def sign_up_path
|
60
|
+
"/auth/exvo?x_sign_up=true"
|
61
|
+
end
|
62
|
+
|
63
|
+
def callback_key
|
64
|
+
"_callback"
|
65
|
+
end
|
66
|
+
|
67
|
+
def current_user
|
68
|
+
return @current_user unless @current_user.nil?
|
69
|
+
@current_user = session[:user_uid] && find_or_create_user_by_uid(session[:user_uid])
|
70
|
+
end
|
71
|
+
|
72
|
+
def current_app_id
|
73
|
+
@current_app_id
|
74
|
+
end
|
75
|
+
|
76
|
+
def signed_in?
|
77
|
+
!!current_user
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
def find_or_create_user_by_uid(uid)
|
83
|
+
raise "Implement find_or_create_user_by_uid in a controller"
|
84
|
+
end
|
85
|
+
|
86
|
+
def sign_out_url(return_to)
|
87
|
+
Exvo::Helpers.auth_uri + "/users/sign_out?" + Rack::Utils.build_query({ :return_to => return_to })
|
88
|
+
end
|
89
|
+
|
90
|
+
def non_interactive_sign_in_path(params = {})
|
91
|
+
path = "/auth/exvo"
|
92
|
+
query = Rack::Utils.build_query(params)
|
93
|
+
query.empty? ? path : "#{path}?#{query}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def current_request
|
97
|
+
request.params.reject{ |k, v| ["controller", "action"].include?(k) || v.nil? }.merge(
|
98
|
+
:_dejavu => {
|
99
|
+
:script_name => request.script_name, # for Rack::Request
|
100
|
+
:path_info => request.path_info, # for Rack::Request
|
101
|
+
:request_path => request.path, # for Merb::Request
|
102
|
+
:method => request_method,
|
103
|
+
:content_type => request.content_type
|
104
|
+
}
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def store_request!
|
109
|
+
session[:stored_request] = Base64.encode64(MultiJson.encode(current_request))
|
110
|
+
end
|
111
|
+
|
112
|
+
def request_replay_url
|
113
|
+
if stored_request = session.delete(:stored_request)
|
114
|
+
params = MultiJson.decode(Base64.decode64(stored_request))
|
115
|
+
dejavu = params.delete("_dejavu")
|
116
|
+
if dejavu["method"] == "GET"
|
117
|
+
dejavu["script_name"] + dejavu["path_info"] + (params.any? ? "?" + Rack::Utils.build_nested_query(params) : "")
|
118
|
+
else
|
119
|
+
"/auth/dejavu?" + Rack::Utils.build_nested_query(params.merge(:_dejavu => dejavu))
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ExvoAuth::Controllers::Merb
|
2
|
+
def self.included(base)
|
3
|
+
base.send :include, ExvoAuth::Controllers::Base
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
def authenticate_user!
|
9
|
+
super
|
10
|
+
throw :halt unless signed_in?
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def request_method
|
16
|
+
request.method.to_s.upcase
|
17
|
+
end
|
18
|
+
|
19
|
+
def basic_authentication_method_name
|
20
|
+
:basic_authentication
|
21
|
+
end
|
22
|
+
|
23
|
+
def redirect_to(*args)
|
24
|
+
redirect(*args)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ExvoAuth::Controllers::Rails
|
2
|
+
def self.included(base)
|
3
|
+
base.send :include, ExvoAuth::Controllers::Base
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
base.helper_method :current_user, :signed_in?, :sign_up_path, :sign_in_path
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
protected
|
10
|
+
|
11
|
+
def request_method
|
12
|
+
request.request_method
|
13
|
+
end
|
14
|
+
|
15
|
+
def basic_authentication_method_name
|
16
|
+
:authenticate_or_request_with_http_basic
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class ExvoAuth::Dejavu
|
2
|
+
def initialize(app)
|
3
|
+
@app = app
|
4
|
+
end
|
5
|
+
|
6
|
+
def call(env)
|
7
|
+
dejavu(env) if Rack::Request.new(env).path == "/auth/dejavu"
|
8
|
+
@app.call(env)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def dejavu(env)
|
14
|
+
params = Rack::Request.new(env).params
|
15
|
+
dejavu = params.delete("_dejavu")
|
16
|
+
|
17
|
+
env["QUERY_STRING"] = Rack::Utils.build_nested_query(params) # Will not work with file uploads.
|
18
|
+
env["SCRIPT_NAME"] = dejavu["script_name"] # for Rack::Request
|
19
|
+
env["PATH_INFO"] = dejavu["path_info"] # for Rack::Request
|
20
|
+
env["REQUEST_PATH"] = dejavu["request_path"] # for Merb::Request
|
21
|
+
env["REQUEST_METHOD"] = dejavu["method"]
|
22
|
+
env["CONTENT_TYPE"] = dejavu["content_type"]
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class ExvoAuth::Models::Message
|
2
|
+
include ActiveModel::Validations
|
3
|
+
include ActiveModel::Serialization
|
4
|
+
|
5
|
+
class RecordInvalid < StandardError; end
|
6
|
+
class RecordNotFound < StandardError; end
|
7
|
+
|
8
|
+
validates :label, :presence => true, :format => /^[_a-z0-9]+$/ix
|
9
|
+
validates :text, :presence => true
|
10
|
+
validates :user_uid, :presence => true, :numericality => true
|
11
|
+
|
12
|
+
attr_accessor :id, :label, :text, :user_uid, :created_at, :read
|
13
|
+
|
14
|
+
def initialize(attributes = {})
|
15
|
+
attributes.each do |name, value|
|
16
|
+
send("#{name}=", value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create(attributes = {})
|
21
|
+
message = new(attributes)
|
22
|
+
if message.valid?
|
23
|
+
message.deliver
|
24
|
+
message
|
25
|
+
else
|
26
|
+
raise RecordInvalid, message.errors.full_messages.join(", ")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.all
|
31
|
+
auth = ExvoAuth::Autonomous::Auth.instance
|
32
|
+
response = auth.get("/api/private/app_messages.json")
|
33
|
+
response.map{ |m| new(m) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find(id)
|
37
|
+
auth = ExvoAuth::Autonomous::Auth.instance
|
38
|
+
response = auth.get("/api/private/app_messages/#{id}.json")
|
39
|
+
if response.code == 200
|
40
|
+
new(response)
|
41
|
+
else
|
42
|
+
raise RecordNotFound, "Couldn't find #{model_name} with ID=#{id}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def deliver
|
47
|
+
auth = ExvoAuth::Autonomous::Auth.instance
|
48
|
+
attributes = {
|
49
|
+
:label => label,
|
50
|
+
:text => text,
|
51
|
+
:user_uid => user_uid
|
52
|
+
}
|
53
|
+
response = auth.post("/api/private/app_messages.json", :body => attributes)
|
54
|
+
case response.code
|
55
|
+
when 201 then
|
56
|
+
response.parsed_response.each do |k, v|
|
57
|
+
send("#{k}=", v)
|
58
|
+
end
|
59
|
+
when 422 then
|
60
|
+
response.parsed_response.each{ |attr, error| errors.add(attr, error) }
|
61
|
+
raise RecordInvalid, errors.full_messages.join(", ")
|
62
|
+
else
|
63
|
+
raise "Unknown error"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def persisted?
|
69
|
+
!!id
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "action_dispatch"
|
2
|
+
require 'active_support/core_ext/hash/reverse_merge'
|
3
|
+
|
4
|
+
# For Merb apps only. This replaces merb sessions with Rails3 sessions. We use this to share sessions between merb and rails apps.
|
5
|
+
class ExvoAuth::SessionStore
|
6
|
+
def initialize(app, options = {})
|
7
|
+
raise "Please configure :secret_token" unless @secret_token = options[:secret_token]
|
8
|
+
raise "Please configure :domain" unless @domain = options[:domain]
|
9
|
+
|
10
|
+
@app = ActionDispatch::Cookies.new(ActionDispatch::Session::CookieStore.new(ActionDispatch::Flash.new(app), :key => "_exvo_session", :domain => @domain, :expire_after => 2.weeks))
|
11
|
+
end
|
12
|
+
def call(env)
|
13
|
+
@app.call(env.reverse_merge!(env_defaults))
|
14
|
+
end
|
15
|
+
def env_defaults
|
16
|
+
@env_defaults ||= {
|
17
|
+
"action_dispatch.secret_token" => @secret_token
|
18
|
+
}
|
19
|
+
end
|
20
|
+
def self.replace_merb_sessions_with_rails_3_sessions! # this is crazy
|
21
|
+
[Merb::BootLoader::MixinSession, Merb::BootLoader::SetupSession, Merb::BootLoader::Cookies].each do |c|
|
22
|
+
c.class_eval do
|
23
|
+
def self.run; end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Merb::Controller.class_eval do
|
27
|
+
def session; request.session end
|
28
|
+
def cookies; request.env["action_dispatch.cookies"] ||= ActionDispatch::Cookies::CookieJar.build(request) end
|
29
|
+
end
|
30
|
+
Merb::Request.class_eval do
|
31
|
+
def session?; true end
|
32
|
+
def session; Rack::Request.new(env).session end
|
33
|
+
def cookies; Rack::Request.new(env).cookies end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
data/test/helper.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestExvoAuth < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Exvo::Helpers.auth_client_id = "foo"
|
6
|
+
Exvo::Helpers.auth_client_secret = "bar"
|
7
|
+
end
|
8
|
+
|
9
|
+
test "consumer sanity" do
|
10
|
+
c = ExvoAuth::Autonomous::Consumer.new(:app_id => "baz")
|
11
|
+
authorization = { "access_token" => "qux", "url" => "https://foo/api" }
|
12
|
+
auth = stub(:get => { "authorization" => authorization })
|
13
|
+
c.expects(:auth).returns(auth)
|
14
|
+
|
15
|
+
assert_equal authorization, c.send(:authorization)
|
16
|
+
assert_equal authorization, c.send(:authorization) # second time from cache, without touching httparty
|
17
|
+
end
|
18
|
+
|
19
|
+
test "provider sanity" do
|
20
|
+
p = ExvoAuth::Autonomous::Provider.new(:app_id => "baz", :access_token => "qux")
|
21
|
+
auth = stub(:get => {"scope" => "qux quux"})
|
22
|
+
p.expects(:auth).returns(auth)
|
23
|
+
|
24
|
+
assert_equal ["qux", "quux"], p.scopes
|
25
|
+
assert_equal ["qux", "quux"], p.scopes # second time from cache, without touching httparty
|
26
|
+
end
|
27
|
+
|
28
|
+
test "integration of httparty interface with auth" do
|
29
|
+
c = ExvoAuth::Autonomous::Consumer.new(:app_id => "baz")
|
30
|
+
basement = mock("basement")
|
31
|
+
basement.expects(:base_uri)
|
32
|
+
basement.expects(:basic_auth)
|
33
|
+
basement.expects(:get).with("/bar").returns(true)
|
34
|
+
c.expects(:basement).at_least_once.returns(basement)
|
35
|
+
assert_true c.get("/bar")
|
36
|
+
end
|
37
|
+
|
38
|
+
test "basement includes httparty" do
|
39
|
+
c = ExvoAuth::Autonomous::Consumer.new(:app_id => "baz")
|
40
|
+
assert_true c.send(:basement).included_modules.include?(HTTParty)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestIntegration < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Exvo::Helpers.auth_host = "staging.auth.exvo.com"
|
6
|
+
Exvo::Helpers.auth_client_id = "foo"
|
7
|
+
Exvo::Helpers.auth_client_secret = "bar"
|
8
|
+
Exvo::Helpers.auth_require_ssl = true
|
9
|
+
end
|
10
|
+
|
11
|
+
test "integration with staging.auth.exvo.com" do
|
12
|
+
c = ExvoAuth::Autonomous::Consumer.new(:app_id => "bar")
|
13
|
+
authorization = c.send(:authorization)
|
14
|
+
assert authorization["access_token"].size > 0
|
15
|
+
assert_equal "https://bar/api", authorization["url"]
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exvo_auth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.15.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jacek Becela
|
9
|
+
- Paweł Gościcki
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-01-26 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: httparty
|
17
|
+
requirement: &77112060 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *77112060
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: activemodel
|
28
|
+
requirement: &77110930 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *77110930
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: actionpack
|
39
|
+
requirement: &77108390 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '3.0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *77108390
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: exvo_helpers
|
50
|
+
requirement: &77089050 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0.2'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *77089050
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: mocha
|
61
|
+
requirement: &77087470 !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: *77087470
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: test-unit
|
72
|
+
requirement: &77086220 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: *77086220
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rake
|
83
|
+
requirement: &77085280 !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: *77085280
|
92
|
+
- !ruby/object:Gem::Dependency
|
93
|
+
name: guard
|
94
|
+
requirement: &77082500 !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
type: :development
|
101
|
+
prerelease: false
|
102
|
+
version_requirements: *77082500
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: guard-test
|
105
|
+
requirement: &77030890 !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: *77030890
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
name: rb-fsevent
|
116
|
+
requirement: &76952630 !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: *76952630
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rb-inotify
|
127
|
+
requirement: &76941060 !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ! '>='
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: *76941060
|
136
|
+
- !ruby/object:Gem::Dependency
|
137
|
+
name: simplecov
|
138
|
+
requirement: &76936810 !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
140
|
+
requirements:
|
141
|
+
- - ! '>='
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: *76936810
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: simplecov-rcov
|
149
|
+
requirement: &76882790 !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ! '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
type: :development
|
156
|
+
prerelease: false
|
157
|
+
version_requirements: *76882790
|
158
|
+
description: Collection of users and applications authentication methods for use when
|
159
|
+
you want your users or applications authorize using the Exvo platform.
|
160
|
+
email:
|
161
|
+
- jacek.becela@gmail.com
|
162
|
+
- pawel.goscicki@gmail.com
|
163
|
+
executables: []
|
164
|
+
extensions: []
|
165
|
+
extra_rdoc_files: []
|
166
|
+
files:
|
167
|
+
- .gitignore
|
168
|
+
- Gemfile
|
169
|
+
- MIT-LICENSE
|
170
|
+
- README.md
|
171
|
+
- Rakefile
|
172
|
+
- exvo_auth.gemspec
|
173
|
+
- lib/exvo_auth.rb
|
174
|
+
- lib/exvo_auth/autonomous/auth.rb
|
175
|
+
- lib/exvo_auth/autonomous/base.rb
|
176
|
+
- lib/exvo_auth/autonomous/cache.rb
|
177
|
+
- lib/exvo_auth/autonomous/consumer.rb
|
178
|
+
- lib/exvo_auth/autonomous/http.rb
|
179
|
+
- lib/exvo_auth/autonomous/provider.rb
|
180
|
+
- lib/exvo_auth/controllers/base.rb
|
181
|
+
- lib/exvo_auth/controllers/merb.rb
|
182
|
+
- lib/exvo_auth/controllers/rails.rb
|
183
|
+
- lib/exvo_auth/dejavu.rb
|
184
|
+
- lib/exvo_auth/middleware.rb
|
185
|
+
- lib/exvo_auth/models/message.rb
|
186
|
+
- lib/exvo_auth/session_store.rb
|
187
|
+
- lib/exvo_auth/version.rb
|
188
|
+
- test/helper.rb
|
189
|
+
- test/test_exvo_auth.rb
|
190
|
+
- test/test_integration.rb
|
191
|
+
homepage: https://github.com/Exvo/exvo_auth
|
192
|
+
licenses: []
|
193
|
+
post_install_message:
|
194
|
+
rdoc_options: []
|
195
|
+
require_paths:
|
196
|
+
- lib
|
197
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
198
|
+
none: false
|
199
|
+
requirements:
|
200
|
+
- - ! '>='
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
|
+
none: false
|
205
|
+
requirements:
|
206
|
+
- - ! '>='
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
requirements: []
|
210
|
+
rubyforge_project:
|
211
|
+
rubygems_version: 1.8.10
|
212
|
+
signing_key:
|
213
|
+
specification_version: 3
|
214
|
+
summary: User and App authentication for Exvo
|
215
|
+
test_files: []
|
216
|
+
has_rdoc:
|