oauth2_provider 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE.txt +21 -0
- data/README.textile +271 -0
- data/app/controllers/oauth2/provider/oauth_authorize_controller.rb +65 -0
- data/app/controllers/oauth2/provider/oauth_clients_controller.rb +51 -0
- data/app/controllers/oauth2/provider/oauth_token_controller.rb +56 -0
- data/app/controllers/oauth2/provider/oauth_user_tokens_controller.rb +26 -0
- data/app/models/oauth2/provider/oauth_authorization.rb +31 -0
- data/app/models/oauth2/provider/oauth_client.rb +31 -0
- data/app/models/oauth2/provider/oauth_token.rb +35 -0
- data/app/views/oauth2/provider/layouts/oauth_clients.html.erb +17 -0
- data/app/views/oauth2/provider/oauth_authorize/index.html.erb +8 -0
- data/app/views/oauth2/provider/oauth_clients/edit.html.erb +20 -0
- data/app/views/oauth2/provider/oauth_clients/index.html.erb +26 -0
- data/app/views/oauth2/provider/oauth_clients/new.html.erb +19 -0
- data/app/views/oauth2/provider/oauth_clients/show.html.erb +22 -0
- data/app/views/oauth2/provider/oauth_user_tokens/index.html.erb +14 -0
- data/config/routes.rb +11 -0
- data/generators/oauth2_provider/oauth2_provider_generator.rb +25 -0
- data/generators/oauth2_provider/templates/config/initializers/oauth2_provider.rb +14 -0
- data/generators/oauth2_provider/templates/db/migrate/create_oauth_authorizations.rb +18 -0
- data/generators/oauth2_provider/templates/db/migrate/create_oauth_clients.rb +16 -0
- data/generators/oauth2_provider/templates/db/migrate/create_oauth_tokens.rb +19 -0
- data/init.rb +3 -0
- data/lib/oauth2/provider/application_controller_methods.rb +52 -0
- data/lib/oauth2/provider/clock.rb +20 -0
- data/tasks/gem.rake +33 -0
- metadata +81 -0
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2010 ThoughtWorks, Inc. (http://thoughtworks.com)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,271 @@
|
|
1
|
+
h1. Introduction
|
2
|
+
|
3
|
+
This plugin implements v09 of the OAuth2 draft spec "http://tools.ietf.org/html/draft-ietf-oauth-v2-09":http://tools.ietf.org/html/draft-ietf-oauth-v2-09.
|
4
|
+
The latest version of the spec is available at "http://tools.ietf.org/html/draft-ietf-oauth-v2":http://tools.ietf.org/html/draft-ietf-oauth-v2
|
5
|
+
|
6
|
+
Currently only the web-server profile "http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-1.4.1":http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-1.4.1 is supported.
|
7
|
+
|
8
|
+
h1. What is OAuth?
|
9
|
+
|
10
|
+
OAuth is an open-source specification for building a framework for allowing a third-party app (the "client") to access protected resources from another application (the "provider," or "resource owner") at the request of a "user" of the client app. Oauth allows the user to enter his user credentials (ex. username and password) only to the provider app, which then grants the client app permission to view the protected resources on behalf of the user.
|
11
|
+
|
12
|
+
A very good overview of the basic OAuth workflow is "here":http://hueniverse.com/2007/10/beginners-guide-to-oauth-part-ii-protocol-workflow/.
|
13
|
+
|
14
|
+
Common terms:
|
15
|
+
|
16
|
+
* Provider/Resource Owner - the app that hosts the protected resource. A real world example is Twitter which uses OAuth as the protocol for all its clients.
|
17
|
+
* Client - the app that requests to see the resource data on behalf of the user. Any Twitter client that shows tweets is an example of this.
|
18
|
+
* User/end user - the entity who initiates the OAuth flow to allow the client to access protected data from the provider.
|
19
|
+
* Client id/client secret - Often, provider apps will maintain a list of clients that are allowed to access their data. Client apps can be identified in a number of ways, including with an id and a secret.
|
20
|
+
|
21
|
+
h1. What's Included
|
22
|
+
|
23
|
+
* The OAuth 2.0 (v9) plugin (RAILS_ROOT/vendor/plugins/oauth2_provider)
|
24
|
+
* Units and functional tests (RAILS_ROOT/test)
|
25
|
+
* A sample host Rails application (RAILS_ROOT)
|
26
|
+
** Create sample app user at /users/new
|
27
|
+
** Create sample app OAuth client at /oauth/clients
|
28
|
+
** Access OAuth-allowed protected resource /protected_resource
|
29
|
+
** List and revoke a user's tokens at /oauth/user_tokens
|
30
|
+
|
31
|
+
h1. Assumptions
|
32
|
+
|
33
|
+
Usage of this plugin assumes that you already have a RAILS app that has unique users who access user-specific data by logging in, or some other method of user authentication.
|
34
|
+
|
35
|
+
h1. Supported Features
|
36
|
+
|
37
|
+
* Web server flow as described at "http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-1.4.1":http://tools.ietf.org/html/draft-ietf-oauth-v2-09#section-1.4.1
|
38
|
+
* Endpoint for clients to request authorization 'code'
|
39
|
+
* Endpoint to request an access token using the authorization 'code'
|
40
|
+
* Admin screens for:
|
41
|
+
* End users to manage/revoke access tokens given out to 3rd party OAuth2 clients
|
42
|
+
* Admins to manage OAuth2 clients
|
43
|
+
|
44
|
+
h1. Available Endpoint URLs
|
45
|
+
|
46
|
+
See config/routes.rb in the plugin for more details.
|
47
|
+
|
48
|
+
*API only URLs*
|
49
|
+
* /oauth/authorize (Oauth2::Provider::OauthAuthorizeController) - used by the user-agent (browser) to request an authorization 'code'
|
50
|
+
* /oauth/token (Oauth2::Provider::OauthTokenController) - used by the OAuth2 client to request access token to access protected resources
|
51
|
+
|
52
|
+
*Accessed from the browser*
|
53
|
+
* /oauth/user_tokens (Oauth2::Provider::OauthUserTokensController) - used by end users to view and revoke access to 3rd party OAuth2 clients.
|
54
|
+
* /oauth/clients (Oauth2::Provider::OauthClientsController) - to manage oauth clients (should be available only to admins)
|
55
|
+
|
56
|
+
It is the responsibility of the host application to avoid routing conflicts. The simplest thing to do is avoid defining any paths starting with /oauth
|
57
|
+
|
58
|
+
h1. Installation
|
59
|
+
|
60
|
+
Copy the plugin into your rails application's vendor/plugins directory.
|
61
|
+
|
62
|
+
Execute the configuration script from your RAILS_ROOT:
|
63
|
+
|
64
|
+
$ ./script/generate oauth2_provider
|
65
|
+
|
66
|
+
This will create:
|
67
|
+
* config/initializers/oauth2_provider.rb
|
68
|
+
* db/migrate/TIMESTAMP_create_oauth_authorizations.rb
|
69
|
+
* db/migrate/TIMESTAMP_create_oauth_clients.rb
|
70
|
+
* db/migrate/TIMESTAMP_create_oauth_tokens.rb
|
71
|
+
|
72
|
+
h2. Configuration
|
73
|
+
|
74
|
+
h3. Host Application
|
75
|
+
|
76
|
+
h4. Rails initializer
|
77
|
+
|
78
|
+
Edit the file config/initializers/oauth2_provider.rb in which you
|
79
|
+
* must call filter skipping methods on OauthTokenController, ensuring any authentication filters to not run for this controllers actions
|
80
|
+
* must setup authorization for OauthClientsController, limiting access to only application administrators
|
81
|
+
* must setup authorization for OauthUserTokensController, limiting access to logged in users (this step might not actually require you to write code, we're just putting it here to make sure you consider this issue)
|
82
|
+
* might call filter skipping or similar methods on the other provided controllers should it be necessary for them to run
|
83
|
+
|
84
|
+
A sample initializer:
|
85
|
+
|
86
|
+
<pre>
|
87
|
+
module Oauth2
|
88
|
+
module Provider
|
89
|
+
|
90
|
+
# make sure no authentication for OauthTokenController
|
91
|
+
OauthTokenController.skip_before_filter(:login_required)
|
92
|
+
|
93
|
+
# use host app's custom authorization filter to protect OauthClientsController
|
94
|
+
OauthClientsController.before_filter(:ensure_admin_user)
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
</pre>
|
100
|
+
|
101
|
+
|
102
|
+
h4. ApplicationController
|
103
|
+
|
104
|
+
Make the following changes:
|
105
|
+
* Include Oauth2::Provider::ApplicationControllerMethods module
|
106
|
+
* Define a 'current_user_id_for_oauth' method that returns the id of the currently logged-in user, serving as a foreign-key to any tokens that are stored in the database.
|
107
|
+
* alias_method_chain 'user_id_for_oauth_access_token' into your authentication filter. This method is supplied by Oauth2::Provider::ApplicationControllerMethods and converts an Oauth access token passed in a request's header to a user_id known by the host application. This user_id corresponds to whatever your current_user_id method returns.
|
108
|
+
|
109
|
+
*Before*
|
110
|
+
|
111
|
+
<pre>
|
112
|
+
class ApplicationController < ActionController::Base
|
113
|
+
|
114
|
+
# the host application's authentication filter, you'll
|
115
|
+
# see in the 'After' section below that you can user
|
116
|
+
# alias_method_chain to merge OAuth 2.0 authentication
|
117
|
+
# with your current authentication filter.
|
118
|
+
before_filter :login_required
|
119
|
+
|
120
|
+
# this checks whether the user is logged in for purposes
|
121
|
+
# of an authentication filter. obviously, your host application
|
122
|
+
# will have very different code than this. this example is
|
123
|
+
# pulled from the sample host application with which the plugin ships.
|
124
|
+
def login_required
|
125
|
+
current_user_id = session[:user_id]
|
126
|
+
if current_user_id
|
127
|
+
User.current = User.new(current_user_id)
|
128
|
+
else
|
129
|
+
raise "Lack of rights!"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
</pre>
|
135
|
+
|
136
|
+
*After*
|
137
|
+
|
138
|
+
<pre>
|
139
|
+
class ApplicationController < ActionController::Base
|
140
|
+
|
141
|
+
# the host application's authentication filter
|
142
|
+
before_filter :login_required
|
143
|
+
|
144
|
+
# include Oauth2::Provider::ApplicationControllerMethods
|
145
|
+
include Oauth2::Provider::ApplicationControllerMethods
|
146
|
+
|
147
|
+
# this checks whether the user is logged in for purposes
|
148
|
+
# of an authentication filter. obviously, your host application
|
149
|
+
# will have very different code than this. this example is
|
150
|
+
# pulled from the sample host application with which the plugin ships.
|
151
|
+
def login_required
|
152
|
+
current_user_id = session[:user_id]
|
153
|
+
if current_user_id
|
154
|
+
User.current = User.new(current_user_id)
|
155
|
+
else
|
156
|
+
raise "Lack of rights!"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# required by the OAuth plugin to figure out the currently logged in user
|
161
|
+
# must be a string representation of the user.
|
162
|
+
# A 'username', 'email' or a db primary key are good candidates.
|
163
|
+
protected def current_user_id_for_oauth
|
164
|
+
super
|
165
|
+
end
|
166
|
+
|
167
|
+
# use alias_method_chain to wrap your existing authentication filter
|
168
|
+
# with behavior that will use any valid passed Oauth access token header,
|
169
|
+
# falling back to your standard filter if the request is not an Oauth request.
|
170
|
+
#
|
171
|
+
# clearly, your host application will have different code than
|
172
|
+
# this example, with different authentication models and different filter
|
173
|
+
# method names.
|
174
|
+
#
|
175
|
+
# As for this example, OAuth2::Provider::ApplicationControllerMethods supplies
|
176
|
+
# a user_id_for_oauth_access_token to lookup the user_id for a given access token.
|
177
|
+
# The host app must then use that
|
178
|
+
# user_id to setup the user session, do any authorization checks, etc. in this
|
179
|
+
# example (from the included sample host app) we simply store the user_id in
|
180
|
+
# the user's session.
|
181
|
+
#
|
182
|
+
# Note that user_id_for_oauth_access_token returns nil if an action
|
183
|
+
# has not been enabled for Oauth (see below).
|
184
|
+
def login_required_with_oauth
|
185
|
+
if user_id = self.user_id_for_oauth_access_token
|
186
|
+
session[:user_id] = user_id
|
187
|
+
elsif looks_like_oauth_request?
|
188
|
+
render :text => "Denied!", :status => :unauthorized
|
189
|
+
else
|
190
|
+
login_required_without_oauth
|
191
|
+
end
|
192
|
+
end
|
193
|
+
alias_method_chain :login_required, :oauth
|
194
|
+
|
195
|
+
end
|
196
|
+
</pre>
|
197
|
+
|
198
|
+
h4. Oauth enable particular controller actions
|
199
|
+
|
200
|
+
By default, no action supports OAuth. That is, if you would like for OAuth to work for any particular action you must declare that in the controller. Below is a simple example where a concrete controller definition specifies where Oauth is allowed. If you look at the plugin source you'll see that oauth_allowed can also be passed a block, returning true or false, for more sophisticated implementations.
|
201
|
+
|
202
|
+
<pre>
|
203
|
+
class ProtectedResourceController < ApplicationController
|
204
|
+
|
205
|
+
# Supported options are:
|
206
|
+
# :only => [:oauth_protected_action...]
|
207
|
+
# :except => [:oauth_unprotected_action...]
|
208
|
+
# If no options are specified, defaults to oauth for all actions
|
209
|
+
oauth_allowed :only => :index
|
210
|
+
|
211
|
+
def index
|
212
|
+
render :text => "current user is #{current_user.email}"
|
213
|
+
end
|
214
|
+
|
215
|
+
def no_oauth_here
|
216
|
+
render :text => "this content not available via Oauth"
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
</pre>
|
221
|
+
|
222
|
+
h3. Database
|
223
|
+
|
224
|
+
This plugin stores OAuth2 client, authorization codes, and access token into a DB table. It is therefore required that a host app create the necessary ActiveRecord migrations in their application.
|
225
|
+
|
226
|
+
* In your RAILS_ROOT, run rake db:migrate, this will run all the migrations that were created as when you executed the oauth2_provider generator. You can't do this step until you do the initializers file.
|
227
|
+
|
228
|
+
|
229
|
+
h1. Verify plugin working correctly in your application
|
230
|
+
|
231
|
+
* OAuth enable the actions for which you wish to allow OAuth as an authentication means
|
232
|
+
* Setup a new OAuth client at /oauth/clients
|
233
|
+
* Open /oauth/authorize?redirect_uri=REDIRECT_URI&client_id=CLIENT_ID&response_type=code in a browser. You should see a form asking you to authorize the client to access the host application on your behalf. Check the tickbox and submit.
|
234
|
+
* Your browser is redirected to your redirect URI (hint: use example.com for this test) and you should now see your authorization code as the "code" parameter. Save this code, you will need it for the next step.
|
235
|
+
* For this step you'll need to use curl as you need to perform a POST and there is no form provided by the plugin. Use curl to POST to /oauth/token, passing the following key/value pairs as form data: code=AUTHORIZATION_CODE&grant_type=authorization-code&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=REDIRECT_URI
|
236
|
+
* The response to the above POST will be JSON containing your access token, and its expiration time in seconds.
|
237
|
+
|
238
|
+
<pre>{:access_token => ACCESS_TOKEN, :expires_in => ACCESS_TOKEN_EXPIRES_IN, :refresh_token => REFRESH_TOKEN}</pre>
|
239
|
+
|
240
|
+
* You can now use the ACCESS_TOKEN to access the protected resource. This would require the 'Authorization' HTTP header (NOTE that the quotes are required around the ACCESS_TOKEN)
|
241
|
+
|
242
|
+
<pre>Authorization: Token token="ACCESS_TOKEN"</pre>
|
243
|
+
|
244
|
+
* You should expect to see the contents of the protected resource now.
|
245
|
+
|
246
|
+
|
247
|
+
h1. License (Stuff that lawyers make us say)
|
248
|
+
|
249
|
+
OAuth2 Provider Generator is MIT Licensed.
|
250
|
+
|
251
|
+
The MIT License
|
252
|
+
|
253
|
+
Copyright © 2010 ThoughtWorks, Inc. (http://thoughtworks.com)
|
254
|
+
|
255
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
256
|
+
of this software and associated documentation files (the “Software”), to deal
|
257
|
+
in the Software without restriction, including without limitation the rights
|
258
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
259
|
+
copies of the Software, and to permit persons to whom the Software is
|
260
|
+
furnished to do so, subject to the following conditions:
|
261
|
+
|
262
|
+
The above copyright notice and this permission notice shall be included in
|
263
|
+
all copies or substantial portions of the Software.
|
264
|
+
|
265
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
266
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
267
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
268
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
269
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
270
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
271
|
+
THE SOFTWARE.
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthAuthorizeController < ::ApplicationController
|
4
|
+
|
5
|
+
def index
|
6
|
+
return unless validate_params
|
7
|
+
end
|
8
|
+
|
9
|
+
def authorize
|
10
|
+
return unless validate_params
|
11
|
+
|
12
|
+
unless params[:authorize] == '1'
|
13
|
+
redirect_to "#{params[:redirect_uri]}?error=access-denied"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
|
17
|
+
authorization = @client.create_authorization_for_user_id(current_user_id_for_oauth)
|
18
|
+
state_param = if params[:state].blank?
|
19
|
+
""
|
20
|
+
else
|
21
|
+
"&state=#{CGI.escape(params[:state])}"
|
22
|
+
end
|
23
|
+
|
24
|
+
redirect_to "#{params[:redirect_uri]}?code=#{authorization.code}&expires_in=#{authorization.expires_in}#{state_param}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# TODO: support 'code', 'token', 'code-and-token'
|
30
|
+
VALID_RESPONSE_TYPES = ['code']
|
31
|
+
|
32
|
+
def validate_params
|
33
|
+
if params[:client_id].blank? || params[:response_type].blank?
|
34
|
+
redirect_to "#{params[:redirect_uri]}?error=invalid-request"
|
35
|
+
return false
|
36
|
+
end
|
37
|
+
|
38
|
+
unless VALID_RESPONSE_TYPES.include?(params[:response_type])
|
39
|
+
redirect_to "#{params[:redirect_uri]}?error=unsupported-response-type"
|
40
|
+
return
|
41
|
+
end
|
42
|
+
|
43
|
+
if params[:redirect_uri].blank?
|
44
|
+
render :text => "You did not specify the 'redirect_uri' parameter!", :status => :bad_request
|
45
|
+
return false
|
46
|
+
end
|
47
|
+
|
48
|
+
@client = OauthClient.find_by_client_id(params[:client_id])
|
49
|
+
|
50
|
+
if @client.nil?
|
51
|
+
redirect_to "#{params[:redirect_uri]}?error=invalid-client-id"
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
|
55
|
+
if @client.redirect_uri != params[:redirect_uri]
|
56
|
+
redirect_to "#{params[:redirect_uri]}?error=redirect-uri-mismatch"
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthClientsController < ApplicationController
|
4
|
+
|
5
|
+
def index
|
6
|
+
@oauth_clients = OauthClient.all
|
7
|
+
end
|
8
|
+
|
9
|
+
def show
|
10
|
+
@oauth_client = OauthClient.find(params[:id])
|
11
|
+
end
|
12
|
+
|
13
|
+
def new
|
14
|
+
@oauth_client = OauthClient.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def edit
|
18
|
+
@oauth_client = OauthClient.find(params[:id])
|
19
|
+
end
|
20
|
+
|
21
|
+
def create
|
22
|
+
@oauth_client = OauthClient.new(params[:oauth_client])
|
23
|
+
|
24
|
+
if @oauth_client.save
|
25
|
+
flash[:notice] = 'OauthClient was successfully created.'
|
26
|
+
redirect_to(@oauth_client)
|
27
|
+
else
|
28
|
+
render :action => "new"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def update
|
33
|
+
@oauth_client = OauthClient.find(params[:id])
|
34
|
+
|
35
|
+
if @oauth_client.update_attributes(params[:oauth_client])
|
36
|
+
flash[:notice] = 'OauthClient was successfully updated.'
|
37
|
+
redirect_to(@oauth_client)
|
38
|
+
else
|
39
|
+
render :action => "edit"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def destroy
|
44
|
+
@oauth_client = OauthClient.find(params[:id])
|
45
|
+
@oauth_client.destroy
|
46
|
+
|
47
|
+
redirect_to(oauth_clients_url)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthTokenController < ApplicationController
|
4
|
+
|
5
|
+
def get_token
|
6
|
+
|
7
|
+
authorization = OauthAuthorization.find_by_code(params[:code])
|
8
|
+
authorization.delete unless authorization.nil?
|
9
|
+
|
10
|
+
original_token = OauthToken.find_by_refresh_token(params[:refresh_token])
|
11
|
+
original_token.delete unless original_token.nil?
|
12
|
+
|
13
|
+
unless ['authorization-code', 'refresh-token'].include?(params[:grant_type])
|
14
|
+
render_error('unsupported-grant-type')
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
client = OauthClient.find_by_client_id_and_client_secret(
|
19
|
+
params[:client_id], params[:client_secret]
|
20
|
+
)
|
21
|
+
|
22
|
+
if client.nil?
|
23
|
+
render_error('invalid-client-credentials')
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
27
|
+
if client.redirect_uri != params[:redirect_uri]
|
28
|
+
render_error('invalid-grant')
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
if params[:grant_type] == 'authorization-code'
|
33
|
+
if authorization.nil? || authorization.expired? || authorization.oauth_client != client
|
34
|
+
render_error('invalid-grant')
|
35
|
+
return
|
36
|
+
end
|
37
|
+
token = authorization.generate_access_token
|
38
|
+
else # refresh-token
|
39
|
+
if original_token.nil? || original_token.oauth_client != client
|
40
|
+
render_error('invalid-grant')
|
41
|
+
return
|
42
|
+
end
|
43
|
+
token = original_token.refresh
|
44
|
+
end
|
45
|
+
|
46
|
+
render :content_type => 'application/json', :text => token.access_token_attributes.to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def render_error(error_code)
|
51
|
+
render :status => :bad_request, :json => {:error => error_code}.to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthUserTokensController < ApplicationController
|
4
|
+
|
5
|
+
def index
|
6
|
+
@tokens = OauthToken.find_all_by_user_id(current_user_id_for_oauth)
|
7
|
+
end
|
8
|
+
|
9
|
+
def revoke
|
10
|
+
token = OauthToken.find_by_id(params[:token_id])
|
11
|
+
if token.nil?
|
12
|
+
render :text => "User not authorized to perform this action!", :status => :bad_request
|
13
|
+
return
|
14
|
+
end
|
15
|
+
if token.user_id != current_user_id_for_oauth
|
16
|
+
render :text => "User not authorized to perform this action!", :status => :bad_request
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
token.delete
|
21
|
+
redirect_to :action => :index
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthAuthorization < ::ActiveRecord::Base
|
4
|
+
|
5
|
+
belongs_to :oauth_client, :class_name => "Oauth2::Provider::OauthClient"
|
6
|
+
|
7
|
+
EXPIRY_TIME = 1.hour
|
8
|
+
|
9
|
+
def generate_access_token
|
10
|
+
token = oauth_client.create_token_for_user_id(user_id)
|
11
|
+
self.delete
|
12
|
+
token
|
13
|
+
end
|
14
|
+
|
15
|
+
def expires_in
|
16
|
+
(Time.at(expires_at.to_i) - Clock.now).to_i
|
17
|
+
end
|
18
|
+
|
19
|
+
def expired?
|
20
|
+
expires_in <= 0
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
def before_create
|
25
|
+
self.expires_at = Clock.now + EXPIRY_TIME
|
26
|
+
self.code = ActiveSupport::SecureRandom.hex(32)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthClient < ActiveRecord::Base
|
4
|
+
|
5
|
+
validates_presence_of :name, :redirect_uri
|
6
|
+
before_create :generate_keys
|
7
|
+
has_many :oauth_tokens, :class_name => "Oauth2::Provider::OauthToken", :dependent => :delete_all
|
8
|
+
has_many :oauth_authorizations, :class_name => "Oauth2::Provider::OauthAuthorization", :dependent => :delete_all
|
9
|
+
validates_format_of :redirect_uri, :with => Regexp.new("^(https|http)://.+$")
|
10
|
+
|
11
|
+
def create_token_for_user_id(user_id)
|
12
|
+
oauth_tokens.create!(:user_id => user_id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_authorization_for_user_id(user_id)
|
16
|
+
oauth_authorizations.create!(:user_id => user_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.model_name
|
20
|
+
ActiveSupport::ModelName.new('OauthClient')
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def generate_keys
|
25
|
+
self.client_id = ActiveSupport::SecureRandom.hex(32)
|
26
|
+
self.client_secret = ActiveSupport::SecureRandom.hex(32)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
class OauthToken < ::ActiveRecord::Base
|
4
|
+
|
5
|
+
belongs_to :oauth_client, :class_name => "Oauth2::Provider::OauthClient"
|
6
|
+
|
7
|
+
EXPIRY_TIME = 90.days
|
8
|
+
|
9
|
+
def access_token_attributes
|
10
|
+
{:access_token => access_token, :expires_in => expires_in, :refresh_token => refresh_token}
|
11
|
+
end
|
12
|
+
|
13
|
+
def expires_in
|
14
|
+
(Time.at(expires_at.to_i) - Clock.now).to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def expired?
|
18
|
+
expires_in <= 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def refresh
|
22
|
+
self.delete
|
23
|
+
oauth_client.create_token_for_user_id(user_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def before_create
|
28
|
+
self.access_token = ActiveSupport::SecureRandom.hex(32)
|
29
|
+
self.expires_at = Clock.now + EXPIRY_TIME
|
30
|
+
self.refresh_token = ActiveSupport::SecureRandom.hex(32)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
|
4
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
5
|
+
<head>
|
6
|
+
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
|
7
|
+
<title>OauthClients: <%= controller.action_name %></title>
|
8
|
+
<%= stylesheet_link_tag 'scaffold' %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
Currently Logged in: <%= current_user.email if logged_in? %>
|
12
|
+
<p style="color: green"><%= flash[:notice] %></p>
|
13
|
+
|
14
|
+
<%= yield %>
|
15
|
+
|
16
|
+
</body>
|
17
|
+
</html>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<form action="<%= url_for(:action => :authorize) %>" method="post" id="oauth_authorize">
|
2
|
+
Do you wish to allow the service named '<%= @client.name %>' to access this application on your behalf? <input type="checkbox" name="authorize" id="authorize" value="1" />
|
3
|
+
<input type="hidden" name="client_id" id="client_id" value="<%= params[:client_id] %>" />
|
4
|
+
<input type="hidden" name="redirect_uri" id="redirect_uri" value="<%= params[:redirect_uri] %>" />
|
5
|
+
<input type="hidden" name="response_type" id="response_type" value="<%= params[:response_type] %>" />
|
6
|
+
<input type="hidden" name="state" id="state" value="<%= params[:state] %>" />
|
7
|
+
<input type="submit" value="Submit" />
|
8
|
+
</form>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h1>Editing oauth_client</h1>
|
2
|
+
|
3
|
+
<% form_for(@oauth_client) do |f| %>
|
4
|
+
<%= f.error_messages %>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<%= f.label :name %><br />
|
8
|
+
<%= f.text_field :name %>
|
9
|
+
</p>
|
10
|
+
<p>
|
11
|
+
<%= f.label :redirect_uri %><br />
|
12
|
+
<%= f.text_field :redirect_uri %>
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
<%= f.submit 'Update' %>
|
16
|
+
</p>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<%= link_to 'Show', @oauth_client %> |
|
20
|
+
<%= link_to 'Back', oauth_clients_path %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<h1>Listing oauth_clients</h1>
|
2
|
+
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Name</th>
|
6
|
+
<th>Client id</th>
|
7
|
+
<th>Client secret</th>
|
8
|
+
<th>Redirect URI</th>
|
9
|
+
</tr>
|
10
|
+
|
11
|
+
<% @oauth_clients.each do |oauth_client| %>
|
12
|
+
<tr>
|
13
|
+
<td><%=h oauth_client.name %></td>
|
14
|
+
<td><%=h oauth_client.client_id %></td>
|
15
|
+
<td><%=h oauth_client.client_secret %></td>
|
16
|
+
<td><%=h oauth_client.redirect_uri %></td>
|
17
|
+
<td><%= link_to 'Show', oauth_client %></td>
|
18
|
+
<td><%= link_to 'Edit', edit_oauth_client_path(oauth_client) %></td>
|
19
|
+
<td><%= link_to 'Destroy', oauth_client, :confirm => 'Are you sure?', :method => :delete %></td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</table>
|
23
|
+
|
24
|
+
<br />
|
25
|
+
|
26
|
+
<%= link_to 'New oauth_client', new_oauth_client_path %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<h1>New oauth_client</h1>
|
2
|
+
|
3
|
+
<% form_for(@oauth_client) do |f| %>
|
4
|
+
<%= f.error_messages %>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<%= f.label :name %><br />
|
8
|
+
<%= f.text_field :name %>
|
9
|
+
</p>
|
10
|
+
<p>
|
11
|
+
<%= f.label :redirect_uri %><br />
|
12
|
+
<%= f.text_field :redirect_uri %>
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
<%= f.submit 'Create' %>
|
16
|
+
</p>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<%= link_to 'Back', oauth_clients_path %>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<p>
|
2
|
+
<b>Name:</b>
|
3
|
+
<%=h @oauth_client.name %>
|
4
|
+
</p>
|
5
|
+
|
6
|
+
<p>
|
7
|
+
<b>Client:</b>
|
8
|
+
<%=h @oauth_client.client_id %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<p>
|
12
|
+
<b>Client secret:</b>
|
13
|
+
<%=h @oauth_client.client_secret %>
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<p>
|
17
|
+
<b>Redirect URI:</b>
|
18
|
+
<%=h @oauth_client.redirect_uri %>
|
19
|
+
</p>
|
20
|
+
|
21
|
+
<%= link_to 'Edit', edit_oauth_client_path(@oauth_client) %> |
|
22
|
+
<%= link_to 'Back', oauth_clients_path %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<table>
|
2
|
+
<tr>
|
3
|
+
<th>Client</th>
|
4
|
+
<th>Token</th>
|
5
|
+
<th> </th>
|
6
|
+
</tr>
|
7
|
+
<% @tokens.each do |token| -%>
|
8
|
+
<tr>
|
9
|
+
<td><%= token.oauth_client.name %></td>
|
10
|
+
<td><%= token.access_token %></td>
|
11
|
+
<td><%= link_to('Destroy', {:action => :revoke, :token_id => token.id, :controller => 'Oauth2::Provider::OauthUserTokens'}, {:confirm => 'Are you sure?', :method => :delete})%></td>
|
12
|
+
</tr>
|
13
|
+
<% end -%>
|
14
|
+
</table>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
ActionController::Routing::Routes.draw do |map|
|
2
|
+
|
3
|
+
map.resources :oauth_clients, :controller => 'Oauth2::Provider::OauthClients', :as => 'oauth/clients'
|
4
|
+
|
5
|
+
map.connect '/oauth/authorize', :controller => 'Oauth2::Provider::OauthAuthorize', :action => :authorize, :conditions => {:method => :post}
|
6
|
+
map.connect '/oauth/authorize', :controller => 'Oauth2::Provider::OauthAuthorize', :action => :index, :conditions => {:method => :get}
|
7
|
+
map.connect '/oauth/token', :controller => 'Oauth2::Provider::OauthToken', :action => :get_token, :conditions => {:method => :post}
|
8
|
+
|
9
|
+
map.connect '/oauth/user_tokens/revoke/:token_id', :controller => 'Oauth2::Provider::OauthUserTokens', :action => :revoke, :conditions => {:method => :delete}
|
10
|
+
map.connect '/oauth/user_tokens', :controller => 'Oauth2::Provider::OauthUserTokens', :action => :index, :conditions => {:method => :get}
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Oauth2ProviderGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.template 'config/initializers/oauth2_provider.rb', "config/initializers/oauth2_provider.rb"
|
5
|
+
|
6
|
+
['create_oauth_clients', 'create_oauth_tokens', 'create_oauth_authorizations'].each_with_index do |file_name, index|
|
7
|
+
m.template "db/migrate/#{file_name}.rb", "db/migrate/#{version_with_prefix(index)}_#{file_name}.rb", :migration_file_name => file_name
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def after_generate
|
14
|
+
puts "*"*80
|
15
|
+
puts "Please edit the file 'config/initializers/oauth2_provider.rb' as per your needs!"
|
16
|
+
puts "The readme file in the plugin contains more information about configuration."
|
17
|
+
puts "*"*80
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def version_with_prefix(prefix)
|
22
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S") + "#{prefix}"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
|
4
|
+
raise 'OAuth2 provider not configured yet!'
|
5
|
+
# please go through the readme and configure this file before you can use this plugin!
|
6
|
+
|
7
|
+
# make sure no authentication for OauthTokenController
|
8
|
+
OauthTokenController.skip_before_filter(:login_required)
|
9
|
+
|
10
|
+
# use host app's custom authorization filter to protect OauthClientsController
|
11
|
+
OauthClientsController.before_filter(:ensure_admin_user)
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateOauthAuthorizations < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :oauth_authorizations do |t|
|
4
|
+
t.string :user_id
|
5
|
+
t.integer :oauth_client_id
|
6
|
+
t.string :code
|
7
|
+
t.timestamp :expires_at
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.down
|
15
|
+
drop_table :oauth_authorizations
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateOauthClients < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :oauth_clients do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :client_id
|
6
|
+
t.string :client_secret
|
7
|
+
t.string :redirect_uri
|
8
|
+
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :oauth_clients
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateOauthTokens < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :oauth_tokens do |t|
|
4
|
+
t.string :user_id
|
5
|
+
t.integer :oauth_client_id
|
6
|
+
t.string :access_token
|
7
|
+
t.string :refresh_token
|
8
|
+
t.timestamp :expires_at
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.down
|
16
|
+
drop_table :oauth_tokens
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Oauth2
|
2
|
+
module Provider
|
3
|
+
module ApplicationControllerMethods
|
4
|
+
|
5
|
+
def self.included(controller_class)
|
6
|
+
controller_class.cattr_accessor :oauth_options, :oauth_options_proc
|
7
|
+
|
8
|
+
def controller_class.oauth_allowed(options = {}, &block)
|
9
|
+
raise 'options cannot contain both :only and :except' if options[:only] && options[:except]
|
10
|
+
|
11
|
+
[:only, :except].each do |k|
|
12
|
+
if values = options[k]
|
13
|
+
options[k] = Array(values).map(&:to_s).to_set
|
14
|
+
end
|
15
|
+
end
|
16
|
+
self.oauth_options = options
|
17
|
+
self.oauth_options_proc = block
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def user_id_for_oauth_access_token
|
25
|
+
return nil unless oauth_allowed?
|
26
|
+
header_field = request.headers["Authorization"]
|
27
|
+
|
28
|
+
if header_field =~ /Token token="(.*)"/
|
29
|
+
token = OauthToken.find_by_access_token($1)
|
30
|
+
token.user_id if token
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def looks_like_oauth_request?
|
35
|
+
header_field = request.headers["Authorization"]
|
36
|
+
header_field =~ /Token token="(.*)"/
|
37
|
+
end
|
38
|
+
|
39
|
+
def oauth_allowed?
|
40
|
+
if (oauth_options_proc && !oauth_options_proc.call(self))
|
41
|
+
false
|
42
|
+
else
|
43
|
+
return false if oauth_options.nil?
|
44
|
+
oauth_options.empty? ||
|
45
|
+
(oauth_options[:only] && oauth_options[:only].include?(action_name)) ||
|
46
|
+
(oauth_options[:except] && !oauth_options[:except].include?(action_name))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/tasks/gem.rake
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
|
4
|
+
desc 'Create a the oauth2_provider gem'
|
5
|
+
task :gem do
|
6
|
+
cd File.join(File.expand_path(File.dirname(__FILE__)), '..') do
|
7
|
+
|
8
|
+
cp "#{RAILS_ROOT}/../README.textile", '.'
|
9
|
+
cp "#{RAILS_ROOT}/../MIT-LICENSE.txt", '.'
|
10
|
+
|
11
|
+
spec = Gem::Specification.new do |s|
|
12
|
+
s.name = "oauth2_provider"
|
13
|
+
s.version = "0.0.1"
|
14
|
+
s.author = "ThoughtWorks, Inc."
|
15
|
+
s.email = "ketan@thoughtworks.com"
|
16
|
+
s.homepage = "http://github.com/ThoughtWorksStudios/oauth2_provider"
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.summary = "A Rails plugin to OAuth v2.0 enable your rails application"
|
19
|
+
s.description = "A Rails plugin to OAuth v2.0 enable your rails application"
|
20
|
+
s.files = Dir["**/*.*"]
|
21
|
+
s.has_rdoc = false
|
22
|
+
s.extra_rdoc_files = ["README.textile", "MIT-LICENSE.txt"]
|
23
|
+
end
|
24
|
+
File.open("oauth2_provider.gemspec", "w") { |f| f << spec.to_ruby }
|
25
|
+
rm_rf "#{RAILS_ROOT}/pkg"
|
26
|
+
sh "gem build #{spec.name}.gemspec"
|
27
|
+
mkdir "#{RAILS_ROOT}/pkg"
|
28
|
+
mv "#{spec.name}-#{spec.version}.gem", "#{RAILS_ROOT}/pkg"
|
29
|
+
|
30
|
+
rm "README.textile"
|
31
|
+
rm "MIT-LICENSE.txt"
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oauth2_provider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ThoughtWorks, Inc.
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-07-22 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A Rails plugin to OAuth v2.0 enable your rails application
|
17
|
+
email: ketan@thoughtworks.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.textile
|
24
|
+
- MIT-LICENSE.txt
|
25
|
+
files:
|
26
|
+
- app/controllers/oauth2/provider/oauth_authorize_controller.rb
|
27
|
+
- app/controllers/oauth2/provider/oauth_clients_controller.rb
|
28
|
+
- app/controllers/oauth2/provider/oauth_token_controller.rb
|
29
|
+
- app/controllers/oauth2/provider/oauth_user_tokens_controller.rb
|
30
|
+
- app/models/oauth2/provider/oauth_authorization.rb
|
31
|
+
- app/models/oauth2/provider/oauth_client.rb
|
32
|
+
- app/models/oauth2/provider/oauth_token.rb
|
33
|
+
- app/views/oauth2/provider/layouts/oauth_clients.html.erb
|
34
|
+
- app/views/oauth2/provider/oauth_authorize/index.html.erb
|
35
|
+
- app/views/oauth2/provider/oauth_clients/edit.html.erb
|
36
|
+
- app/views/oauth2/provider/oauth_clients/index.html.erb
|
37
|
+
- app/views/oauth2/provider/oauth_clients/new.html.erb
|
38
|
+
- app/views/oauth2/provider/oauth_clients/show.html.erb
|
39
|
+
- app/views/oauth2/provider/oauth_user_tokens/index.html.erb
|
40
|
+
- config/routes.rb
|
41
|
+
- generators/oauth2_provider/oauth2_provider_generator.rb
|
42
|
+
- generators/oauth2_provider/templates/config/initializers/oauth2_provider.rb
|
43
|
+
- generators/oauth2_provider/templates/db/migrate/create_oauth_authorizations.rb
|
44
|
+
- generators/oauth2_provider/templates/db/migrate/create_oauth_clients.rb
|
45
|
+
- generators/oauth2_provider/templates/db/migrate/create_oauth_tokens.rb
|
46
|
+
- init.rb
|
47
|
+
- lib/oauth2/provider/application_controller_methods.rb
|
48
|
+
- lib/oauth2/provider/clock.rb
|
49
|
+
- MIT-LICENSE.txt
|
50
|
+
- README.textile
|
51
|
+
- tasks/gem.rake
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/ThoughtWorksStudios/oauth2_provider
|
54
|
+
licenses: []
|
55
|
+
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
|
59
|
+
require_paths:
|
60
|
+
- lib
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: "0"
|
72
|
+
version:
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: A Rails plugin to OAuth v2.0 enable your rails application
|
80
|
+
test_files: []
|
81
|
+
|