doorkeeper 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- data/MIT-LICENSE +20 -0
- data/README.md +106 -0
- data/Rakefile +42 -0
- data/app/assets/javascripts/doorkeeper/application.js +9 -0
- data/app/assets/stylesheets/doorkeeper/application.css +7 -0
- data/app/assets/stylesheets/doorkeeper/form.css +8 -0
- data/app/controllers/doorkeeper/application_controller.rb +27 -0
- data/app/controllers/doorkeeper/applications_controller.rb +35 -0
- data/app/controllers/doorkeeper/authorizations_controller.rb +26 -0
- data/app/controllers/doorkeeper/tokens_controller.rb +15 -0
- data/app/helpers/doorkeeper/application_helper.rb +4 -0
- data/app/models/access_grant.rb +29 -0
- data/app/models/access_token.rb +35 -0
- data/app/models/application.rb +20 -0
- data/app/views/doorkeeper/applications/_form.html.erb +27 -0
- data/app/views/doorkeeper/applications/edit.html.erb +13 -0
- data/app/views/doorkeeper/applications/index.html.erb +29 -0
- data/app/views/doorkeeper/applications/new.html.erb +13 -0
- data/app/views/doorkeeper/applications/show.html.erb +23 -0
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -0
- data/app/views/doorkeeper/authorizations/new.html.erb +18 -0
- data/app/views/layouts/doorkeeper/application.html.erb +25 -0
- data/config/initializers/form_errors.rb +14 -0
- data/config/routes.rb +8 -0
- data/lib/doorkeeper.rb +19 -0
- data/lib/doorkeeper/config.rb +42 -0
- data/lib/doorkeeper/doorkeeper_for.rb +42 -0
- data/lib/doorkeeper/engine.rb +9 -0
- data/lib/doorkeeper/oauth/access_token_request.rb +84 -0
- data/lib/doorkeeper/oauth/authorization_request.rb +95 -0
- data/lib/doorkeeper/oauth/random_string.rb +15 -0
- data/lib/doorkeeper/validations.rb +29 -0
- data/lib/doorkeeper/version.rb +3 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -0
- data/lib/generators/doorkeeper/templates/README +13 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +23 -0
- data/lib/generators/doorkeeper/templates/migration.rb +29 -0
- data/lib/tasks/doorkeeper_tasks.rake +4 -0
- metadata +162 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Applicake. http://applicake.com
|
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,106 @@
|
|
1
|
+
# Doorkeeper - awesome oauth provider for your Rails app.
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/applicake/doorkeeper.png)](http://travis-ci.org/applicake/doorkeeper)
|
4
|
+
|
5
|
+
Doorkeeper is a gem that makes it easy to introduce oauth2 provider
|
6
|
+
functionality to your application.
|
7
|
+
|
8
|
+
So far it supports only Authorization Code
|
9
|
+
flow, but we will gradually introduce other flows.
|
10
|
+
|
11
|
+
For more information about Oauth2 go to
|
12
|
+
[Oauth2 Specs (Draft)](http://tools.ietf.org/html/draft-ietf-oauth-v2-22)
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Put this in your Gemfile:
|
17
|
+
|
18
|
+
gem 'doorkeeper'
|
19
|
+
|
20
|
+
Run the installation generator with:
|
21
|
+
|
22
|
+
rails generate doorkeeper:install
|
23
|
+
|
24
|
+
This will generate the doorkeeper initializer and the oauth tables migration. Don't forget to run the migration in your application:
|
25
|
+
|
26
|
+
rake db:migrate
|
27
|
+
|
28
|
+
## Configuration
|
29
|
+
|
30
|
+
The installation will mount the Doorkeeper routes to your app like this:
|
31
|
+
|
32
|
+
Rails.application.routes.draw do
|
33
|
+
mount Doorkeeper::Engine => "/oauth"
|
34
|
+
# your routes
|
35
|
+
end
|
36
|
+
|
37
|
+
This will mount following routes:
|
38
|
+
|
39
|
+
GET /oauth/authorize
|
40
|
+
POST /oauth/authorize
|
41
|
+
DELETE /oauth/authorize
|
42
|
+
POST /oauth/token
|
43
|
+
resources /oauth/applications
|
44
|
+
|
45
|
+
You need to configure Doorkeeper in order to provide resource_owner model and authentication block `initializers/doorkeeper.rb`
|
46
|
+
|
47
|
+
Doorkeeper.configure do
|
48
|
+
resource_owner_authenticator do |routes|
|
49
|
+
current_user || redirect_to('/sign_in', :alert => "Needs sign in.") # returns nil if current_user is not logged in
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
If you use devise, you may want to use warden to authenticate the block:
|
54
|
+
|
55
|
+
resource_owner_authenticator do |routes|
|
56
|
+
current_user || warden.authenticate!(:scope => :user)
|
57
|
+
end
|
58
|
+
|
59
|
+
## Protecting resources (a.k.a your API endpoint)
|
60
|
+
|
61
|
+
In the controller add the before_filter to authorize the token
|
62
|
+
|
63
|
+
class ProtectedResourcesController < ApplicationController
|
64
|
+
doorkeeper_for :all # For all actions
|
65
|
+
doorkeeper_for :only => :index # Require token only for index action
|
66
|
+
doorkeeper_for :except => :show # Require token for all actions except show
|
67
|
+
end
|
68
|
+
|
69
|
+
## Creating and using client applications
|
70
|
+
|
71
|
+
To start using OAuth 2 as a client first fire up the server with `rails server`, go to `/oauth/applications` and create an application for your client.
|
72
|
+
|
73
|
+
Choose a name and a callback url for it. If you use oauth2 gem you can specify your just generated client as:
|
74
|
+
|
75
|
+
require 'oauth2'
|
76
|
+
client_id = '...' # your client's id
|
77
|
+
client_secret = '...' # your client's secret
|
78
|
+
redirect_uri = '...' # your client's redirect uri
|
79
|
+
client = OAuth2::Client.new(
|
80
|
+
client_id,
|
81
|
+
client_secret,
|
82
|
+
:site => "http://localhost:3000"
|
83
|
+
)
|
84
|
+
|
85
|
+
If you changed the default mount path `/oauth` in your `routes.rb` you need to specify it in the oauth client as `:authorize_url` and `:token_url`. For more information, check the oauth2 gem documentation.
|
86
|
+
|
87
|
+
After that you can try to request an authorization code with the oauth2 gem as follow:
|
88
|
+
|
89
|
+
client.auth_code.authorize_url(:redirect_uri => redirect_uri)
|
90
|
+
# => http://localhost:3000/oauth/authorize?response_type=code&client_id=...&redirect_uri=...
|
91
|
+
|
92
|
+
If you visit the returned url, you'll see a screen to authorize your app. Click on `authorize` and you'll be redirected to your client redirect url.
|
93
|
+
|
94
|
+
Grab the code from the redirect url and request a access token with the following:
|
95
|
+
|
96
|
+
token = client.auth_code.get_token(parms[:code], :redirect_uri => redirect_uri)
|
97
|
+
|
98
|
+
You now have an access token to access you protected resources.
|
99
|
+
|
100
|
+
## Contributing/Development
|
101
|
+
|
102
|
+
Check our [contributing guidelines page in the wiki](https://github.com/applicake/doorkeeper/wiki/Contributing)
|
103
|
+
|
104
|
+
## Supported ruby versions
|
105
|
+
|
106
|
+
All supported ruby versions are [listed here](https://github.com/applicake/doorkeeper/wiki/Supported-Ruby-versions)
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Doorkeeper'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rspec/core/rake_task'
|
24
|
+
|
25
|
+
desc 'Default: run specs.'
|
26
|
+
task :default => :spec
|
27
|
+
|
28
|
+
desc "Run all specs"
|
29
|
+
RSpec::Core::RakeTask.new(:spec => "app:test:prepare")
|
30
|
+
|
31
|
+
namespace :doorkeeper do
|
32
|
+
desc "Install doorkeeper in dummy app"
|
33
|
+
task :install do
|
34
|
+
cd 'spec/dummy'
|
35
|
+
system 'bundle exec rails g doorkeeper:install --force'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
40
|
+
load 'rails/tasks/engine.rake'
|
41
|
+
|
42
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
5
|
+
// the compiled file.
|
6
|
+
//
|
7
|
+
//= require jquery
|
8
|
+
//= require jquery_ujs
|
9
|
+
//= require_tree .
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require_tree .
|
7
|
+
*/
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
class ApplicationController < ActionController::Base
|
3
|
+
private
|
4
|
+
|
5
|
+
def authenticate_resource_owner!
|
6
|
+
current_resource_owner
|
7
|
+
end
|
8
|
+
|
9
|
+
def current_resource_owner
|
10
|
+
instance_exec(main_app, &Doorkeeper.authenticate_resource_owner)
|
11
|
+
end
|
12
|
+
|
13
|
+
def authenticate_admin!
|
14
|
+
if block = Doorkeeper.authenticate_admin
|
15
|
+
instance_exec(main_app, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(method, *args, &block)
|
20
|
+
if method =~ /_(url|path)$/
|
21
|
+
raise "Your path has not been found. Didn't you mean to call routes.#{method} in doorkeeper configuration blocks?"
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
class ApplicationsController < ApplicationController
|
3
|
+
respond_to :html
|
4
|
+
|
5
|
+
before_filter :authenticate_admin!
|
6
|
+
|
7
|
+
def index
|
8
|
+
@applications = Application.all
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
@application = Application.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
@application = Application.new(params[:application])
|
17
|
+
flash[:notice] = "Application created" if @application.save
|
18
|
+
respond_with @application
|
19
|
+
end
|
20
|
+
|
21
|
+
def show
|
22
|
+
@application = Application.find(params[:id])
|
23
|
+
end
|
24
|
+
|
25
|
+
def edit
|
26
|
+
@application = Application.find(params[:id])
|
27
|
+
end
|
28
|
+
|
29
|
+
def update
|
30
|
+
@application = Application.find(params[:id])
|
31
|
+
flash[:notice] = "Application updated" if @application.update_attributes(params[:application])
|
32
|
+
respond_with @application
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Doorkeeper::AuthorizationsController < Doorkeeper::ApplicationController
|
2
|
+
before_filter :authenticate_resource_owner!
|
3
|
+
|
4
|
+
def new
|
5
|
+
render :error unless authorization.valid?
|
6
|
+
end
|
7
|
+
|
8
|
+
def create
|
9
|
+
if authorization.authorize
|
10
|
+
redirect_to authorization.success_redirect_uri
|
11
|
+
else
|
12
|
+
render :error
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def destroy
|
17
|
+
authorization.deny
|
18
|
+
redirect_to authorization.invalid_redirect_uri
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def authorization
|
24
|
+
@authorization ||= Doorkeeper::OAuth::AuthorizationRequest.new(current_resource_owner, params)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Doorkeeper::TokensController < Doorkeeper::ApplicationController
|
2
|
+
def create
|
3
|
+
if token.authorize
|
4
|
+
render :json => token.authorization
|
5
|
+
else
|
6
|
+
render :json => token.error_response
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def token
|
13
|
+
@token ||= Doorkeeper::OAuth::AccessTokenRequest.new(params)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class AccessGrant < ActiveRecord::Base
|
2
|
+
include Doorkeeper::OAuth::RandomString
|
3
|
+
|
4
|
+
self.table_name = "oauth_access_grants"
|
5
|
+
|
6
|
+
belongs_to :application
|
7
|
+
|
8
|
+
validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, :presence => true
|
9
|
+
|
10
|
+
before_validation :generate_token, :on => :create
|
11
|
+
|
12
|
+
def expired?
|
13
|
+
expires_in.present? && Time.now > expired_time
|
14
|
+
end
|
15
|
+
|
16
|
+
def accessible?
|
17
|
+
!expired?
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def expired_time
|
23
|
+
self.created_at + expires_in.seconds
|
24
|
+
end
|
25
|
+
|
26
|
+
def generate_token
|
27
|
+
self.token = unique_random_string_for(:token)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class AccessToken < ActiveRecord::Base
|
2
|
+
include Doorkeeper::OAuth::RandomString
|
3
|
+
|
4
|
+
self.table_name = "oauth_access_tokens"
|
5
|
+
|
6
|
+
belongs_to :application
|
7
|
+
|
8
|
+
scope :accessible, where(:revoked_at => nil)
|
9
|
+
|
10
|
+
validates :application_id, :resource_owner_id, :token, :presence => true
|
11
|
+
|
12
|
+
before_validation :generate_token, :on => :create
|
13
|
+
|
14
|
+
def revoke!
|
15
|
+
update_attribute :revoked_at, DateTime.now
|
16
|
+
end
|
17
|
+
|
18
|
+
def revoked?
|
19
|
+
self.revoked_at.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
def expired?
|
23
|
+
self.expires_at.present? && DateTime.now > self.expires_at
|
24
|
+
end
|
25
|
+
|
26
|
+
def accessible?
|
27
|
+
!expired? && !revoked?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def generate_token
|
33
|
+
self.token = unique_random_string_for(:token)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Application < ActiveRecord::Base
|
2
|
+
include Doorkeeper::OAuth::RandomString
|
3
|
+
set_table_name 'oauth_applications'
|
4
|
+
|
5
|
+
has_many :access_grants
|
6
|
+
|
7
|
+
validates :name, :secret, :redirect_uri, :presence => true
|
8
|
+
validates :uid, :presence => true, :uniqueness => true
|
9
|
+
|
10
|
+
before_validation :generate_uid, :generate_secret, :on => :create
|
11
|
+
|
12
|
+
private
|
13
|
+
def generate_uid
|
14
|
+
self.uid = unique_random_string_for(:uid)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_secret
|
18
|
+
self.secret = random_string
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= form_for(application) do |f| %>
|
2
|
+
<fieldset>
|
3
|
+
<% if @application.errors.any? %>
|
4
|
+
<div class="alert-message error" data-alert><a class="close" href="#">×</a><p>Whoops! Check your form for possible errors</p></div>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<div class="clearfix">
|
8
|
+
<%= f.label :name %>
|
9
|
+
<div class="input">
|
10
|
+
<%= f.text_field :name %>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="clearfix">
|
15
|
+
<%= f.label :redirect_uri %>
|
16
|
+
<div class="input">
|
17
|
+
<%= f.text_field :redirect_uri %>
|
18
|
+
</div>
|
19
|
+
</div class="clearfix">
|
20
|
+
|
21
|
+
<div class="actions">
|
22
|
+
<%= f.submit :Submit, :class => "btn primary" %>
|
23
|
+
<%= link_to "Cancel", applications_path, :class => "btn" %>
|
24
|
+
</div>
|
25
|
+
</fieldset>
|
26
|
+
<% end %>
|
27
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="span16">
|
2
|
+
<header class="page-header"><h2>Edit application</h2></header>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="span10">
|
6
|
+
<%= render 'form', :application => @application %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="span6">
|
10
|
+
<h3>Actions</h3>
|
11
|
+
<p><%= link_to 'Back to application list', applications_path %></p>
|
12
|
+
</div>
|
13
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<div class="span16">
|
2
|
+
<header class="page-header">
|
3
|
+
<h2>Your applications</h2>
|
4
|
+
</header>
|
5
|
+
|
6
|
+
<p><%= link_to 'New Application', new_application_path %></p>
|
7
|
+
|
8
|
+
<table class="zebra-striped">
|
9
|
+
<thead>
|
10
|
+
<tr>
|
11
|
+
<th>Name</th>
|
12
|
+
<th>Callback url</th>
|
13
|
+
<th></th>
|
14
|
+
<th></th>
|
15
|
+
</tr>
|
16
|
+
</thead>
|
17
|
+
<tbody>
|
18
|
+
<% @applications.each do |application| %>
|
19
|
+
<tr>
|
20
|
+
<td><%= link_to application.name, application %></td>
|
21
|
+
<td><%= application.redirect_uri %></td>
|
22
|
+
<td><%= link_to 'Edit', edit_application_path(application) %></td>
|
23
|
+
<td><%= link_to 'Destroy', application, :confirm => 'Are you sure?', :method => :delete %></td>
|
24
|
+
</tr>
|
25
|
+
<% end %>
|
26
|
+
</tbody>
|
27
|
+
</table>
|
28
|
+
|
29
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div class="span16">
|
2
|
+
<header class="page-header"><h2>New application</h2></header>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="span10">
|
6
|
+
<%= render 'form', :application => @application %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<div class="span6">
|
10
|
+
<h3>Actions</h3>
|
11
|
+
<p><%= link_to 'Back to application list', applications_path %></p>
|
12
|
+
</div>
|
13
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<div class="span16">
|
2
|
+
<header class="page-header">
|
3
|
+
<h1>Application: <%= @application.name %></h1>
|
4
|
+
</header>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div class="span10">
|
8
|
+
<h4>Callback url:</h4>
|
9
|
+
<p><%= @application.redirect_uri %></p>
|
10
|
+
|
11
|
+
<h4>Application Id:</h4>
|
12
|
+
<p><code><%= @application.uid %></code></p>
|
13
|
+
|
14
|
+
<h4>Secret:</h4>
|
15
|
+
<p><code><%= @application.secret %></code></p>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="span6">
|
19
|
+
<h3>Actions</h3>
|
20
|
+
<p><%= link_to 'List all', applications_path %></p>
|
21
|
+
<p><%= link_to 'Edit', edit_application_path(@application) %></p>
|
22
|
+
<p><%= link_to 'Remove', @application, :method => :delete, :confirm => "Are you sure?" %></p>
|
23
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>An error has occurred</p>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<div class="span16">
|
2
|
+
<h2>Authorize <%= @authorization.client.name %> to use your account?</h2>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="span16">
|
6
|
+
<%= form_tag authorization_path do %>
|
7
|
+
<%= hidden_field_tag :client_id, @authorization.client_id %>
|
8
|
+
<%= hidden_field_tag :redirect_uri, @authorization.redirect_uri %>
|
9
|
+
<%= hidden_field_tag :response_type, @authorization.response_type %>
|
10
|
+
<%= submit_tag "Authorize", :class => "btn primary" %> or
|
11
|
+
<% end %>
|
12
|
+
<%= form_tag authorization_path, :method => :delete do %>
|
13
|
+
<%= hidden_field_tag :client_id, @authorization.client_id %>
|
14
|
+
<%= hidden_field_tag :redirect_uri, @authorization.redirect_uri %>
|
15
|
+
<%= hidden_field_tag :response_type, @authorization.response_type %>
|
16
|
+
<%= button_tag "Deny", :class => "btn" %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Doorkeeper</title>
|
5
|
+
<%= stylesheet_link_tag "http://twitter.github.com/bootstrap/1.4.0/bootstrap.min.css" %>
|
6
|
+
<%= stylesheet_link_tag "doorkeeper/application" %>
|
7
|
+
<%= javascript_include_tag "doorkeeper/application" %>
|
8
|
+
<%= csrf_meta_tags %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<section id="main" class="container">
|
12
|
+
<div class="content">
|
13
|
+
<div class="row">
|
14
|
+
<% flash.each do |key, message| %>
|
15
|
+
<div class="span16">
|
16
|
+
<div class="alert-message <%= key %>" data-alert><a class="close" href="#">×</a><p><%= message %></p></div>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= yield %>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</section>
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
|
2
|
+
if html_tag.match("input")
|
3
|
+
message = (error = instance.error_message).respond_to?(:join) ? error.join(",") : error
|
4
|
+
%(<span class="error">
|
5
|
+
#{html_tag}
|
6
|
+
<span class="help-inline">
|
7
|
+
#{message}
|
8
|
+
</span>
|
9
|
+
</span>
|
10
|
+
).html_safe
|
11
|
+
else
|
12
|
+
html_tag
|
13
|
+
end
|
14
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
Doorkeeper::Engine.routes.draw do
|
2
|
+
get 'authorize', :to => "authorizations#new", :as => :authorization
|
3
|
+
post 'authorize', :to => "authorizations#create", :as => :authorization
|
4
|
+
delete 'authorize', :to => "authorizations#destroy", :as => :authorization
|
5
|
+
post 'token', :to => "tokens#create", :as => :token
|
6
|
+
|
7
|
+
resources :applications
|
8
|
+
end
|
data/lib/doorkeeper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "doorkeeper/engine"
|
2
|
+
require "doorkeeper/config"
|
3
|
+
require "doorkeeper/doorkeeper_for"
|
4
|
+
|
5
|
+
module Doorkeeper
|
6
|
+
autoload :Validations, "doorkeeper/validations"
|
7
|
+
|
8
|
+
module OAuth
|
9
|
+
class MismatchRedirectURI < StandardError; end
|
10
|
+
|
11
|
+
autoload :RandomString, "doorkeeper/oauth/random_string"
|
12
|
+
autoload :AuthorizationRequest, "doorkeeper/oauth/authorization_request"
|
13
|
+
autoload :AccessTokenRequest, "doorkeeper/oauth/access_token_request"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.setup
|
17
|
+
yield self
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
def self.configure(&block)
|
3
|
+
@@config = Config.new(&block)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Config
|
7
|
+
module ConfigOptions
|
8
|
+
def register_config_option(name, attribute, receives_block = true)
|
9
|
+
define_method name do |*args, &block|
|
10
|
+
if receives_block
|
11
|
+
self.instance_variable_set(:"@#{attribute}", block)
|
12
|
+
else
|
13
|
+
self.instance_variable_set(:"@#{attribute}", args[0])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader attribute
|
18
|
+
public attribute
|
19
|
+
|
20
|
+
Doorkeeper.class_eval "
|
21
|
+
def self.#{attribute}
|
22
|
+
@@config.#{attribute}
|
23
|
+
end
|
24
|
+
"
|
25
|
+
end
|
26
|
+
|
27
|
+
def extended(base)
|
28
|
+
base.send(:private, :register_method)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
extend ConfigOptions
|
33
|
+
|
34
|
+
register_config_option :resource_owner_authenticator, :authenticate_resource_owner
|
35
|
+
register_config_option :admin_authenticator, :authenticate_admin
|
36
|
+
|
37
|
+
def initialize(&block)
|
38
|
+
instance_eval &block
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
module Controller
|
3
|
+
module ClassMethods
|
4
|
+
def doorkeeper_for(options)
|
5
|
+
raise "You have to specify some option for doorkeeper_for method" unless options.present?
|
6
|
+
options = nil if options == :all
|
7
|
+
if options
|
8
|
+
before_filter :doorkeeper_before_filter, options
|
9
|
+
else
|
10
|
+
before_filter :doorkeeper_before_filter
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.included(base)
|
16
|
+
base.extend ClassMethods
|
17
|
+
base.send(:private, :doorkeeper_before_filter, :doorkeeper_token, :doorkeeper_valid_token, :get_doorkeeper_token)
|
18
|
+
end
|
19
|
+
|
20
|
+
def doorkeeper_before_filter
|
21
|
+
head :unauthorized unless doorkeeper_valid_token
|
22
|
+
end
|
23
|
+
|
24
|
+
def doorkeeper_valid_token
|
25
|
+
doorkeeper_token and doorkeeper_token.accessible?
|
26
|
+
end
|
27
|
+
|
28
|
+
def doorkeeper_token
|
29
|
+
@token ||= get_doorkeeper_token
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_doorkeeper_token
|
33
|
+
token = params[:access_token] || params[:bearer_token] || request.env['HTTP_AUTHORIZATION']
|
34
|
+
if token
|
35
|
+
token.gsub!(/Bearer /, '')
|
36
|
+
end
|
37
|
+
AccessToken.find_by_token(token)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
ActionController::Base.send(:include, Doorkeeper::Controller)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Doorkeeper::OAuth
|
2
|
+
class AccessTokenRequest
|
3
|
+
include Doorkeeper::Validations
|
4
|
+
|
5
|
+
ATTRIBUTES = [
|
6
|
+
:client_id,
|
7
|
+
:client_secret,
|
8
|
+
:grant_type,
|
9
|
+
:code,
|
10
|
+
:redirect_uri,
|
11
|
+
]
|
12
|
+
|
13
|
+
validate :attributes, :error => :invalid_request
|
14
|
+
validate :client, :error => :invalid_client
|
15
|
+
validate :grant, :error => :invalid_grant
|
16
|
+
validate :grant_type, :error => :unsupported_grant_type
|
17
|
+
|
18
|
+
attr_accessor *ATTRIBUTES
|
19
|
+
|
20
|
+
def initialize(attributes = {})
|
21
|
+
ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", attributes[attr]) }
|
22
|
+
validate
|
23
|
+
end
|
24
|
+
|
25
|
+
def authorize
|
26
|
+
create_access_token if valid?
|
27
|
+
end
|
28
|
+
|
29
|
+
def authorization
|
30
|
+
{ 'access_token' => access_token,
|
31
|
+
'token_type' => token_type
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid?
|
36
|
+
self.error.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def access_token
|
40
|
+
@access_token.token
|
41
|
+
end
|
42
|
+
|
43
|
+
def token_type
|
44
|
+
"bearer"
|
45
|
+
end
|
46
|
+
|
47
|
+
def error_response
|
48
|
+
{ 'error' => error.to_s }
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def grant
|
54
|
+
@grant ||= AccessGrant.find_by_token(@code)
|
55
|
+
end
|
56
|
+
|
57
|
+
def client
|
58
|
+
@client ||= Application.find_by_uid_and_secret(@client_id, @client_secret)
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_access_token
|
62
|
+
@access_token = AccessToken.create!({
|
63
|
+
:application_id => client.uid,
|
64
|
+
:resource_owner_id => grant.resource_owner_id,
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_attributes
|
69
|
+
code.present? && grant_type.present? && redirect_uri.present?
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_client
|
73
|
+
!!client
|
74
|
+
end
|
75
|
+
|
76
|
+
def validate_grant
|
77
|
+
grant && grant.accessible? && grant.application_id == client.id && grant.redirect_uri == redirect_uri
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_grant_type
|
81
|
+
grant_type == "authorization_code"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Doorkeeper::OAuth
|
2
|
+
class AuthorizationRequest
|
3
|
+
include Doorkeeper::Validations
|
4
|
+
|
5
|
+
DEFAULT_EXPIRATION_TIME = 600
|
6
|
+
|
7
|
+
ATTRIBUTES = [
|
8
|
+
:response_type,
|
9
|
+
:client_id,
|
10
|
+
:redirect_uri,
|
11
|
+
:scope,
|
12
|
+
:state
|
13
|
+
]
|
14
|
+
|
15
|
+
validate :attributes, :error => :invalid_request
|
16
|
+
validate :client, :error => :invalid_client
|
17
|
+
validate :redirect_uri, :error => :invalid_redirect_uri
|
18
|
+
validate :response_type, :error => :unsupported_response_type
|
19
|
+
|
20
|
+
attr_accessor *ATTRIBUTES
|
21
|
+
attr_accessor :resource_owner, :error
|
22
|
+
|
23
|
+
def initialize(resource_owner, attributes)
|
24
|
+
ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", attributes[attr]) }
|
25
|
+
@resource_owner = resource_owner
|
26
|
+
@grant = nil
|
27
|
+
validate
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorize
|
31
|
+
create_authorization if valid?
|
32
|
+
end
|
33
|
+
|
34
|
+
def deny
|
35
|
+
self.error = :access_denied
|
36
|
+
end
|
37
|
+
|
38
|
+
def success_redirect_uri
|
39
|
+
build_uri do |uri|
|
40
|
+
query = "code=#{token}"
|
41
|
+
query << "&state=#{state}" if has_state?
|
42
|
+
uri.query = query
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def invalid_redirect_uri
|
47
|
+
build_uri { |uri| uri.query = "error=#{error}" }
|
48
|
+
end
|
49
|
+
|
50
|
+
def client
|
51
|
+
@client ||= Application.find_by_uid(client_id)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def create_authorization
|
57
|
+
@grant = AccessGrant.create!(
|
58
|
+
:application_id => client.id,
|
59
|
+
:resource_owner_id => resource_owner.id,
|
60
|
+
:expires_in => DEFAULT_EXPIRATION_TIME,
|
61
|
+
:redirect_uri => redirect_uri
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def has_state?
|
66
|
+
state.present?
|
67
|
+
end
|
68
|
+
|
69
|
+
def token
|
70
|
+
@grant.token
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_uri
|
74
|
+
uri = URI.parse(client.redirect_uri)
|
75
|
+
yield uri
|
76
|
+
uri.to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate_attributes
|
80
|
+
%w(response_type client_id redirect_uri).all? { |attr| send(attr).present? }
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_client
|
84
|
+
!!client
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_redirect_uri
|
88
|
+
client.redirect_uri == redirect_uri
|
89
|
+
end
|
90
|
+
|
91
|
+
def validate_response_type
|
92
|
+
response_type == "code"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Doorkeeper::OAuth
|
2
|
+
module RandomString
|
3
|
+
def random_string
|
4
|
+
SecureRandom.hex(32)
|
5
|
+
end
|
6
|
+
|
7
|
+
def unique_random_string_for(attribute)
|
8
|
+
loop do
|
9
|
+
token = random_string
|
10
|
+
break token unless self.class.send("find_by_#{attribute}", token)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
module Validations
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
attr_accessor :error
|
6
|
+
|
7
|
+
def validate
|
8
|
+
@error = nil
|
9
|
+
self.class.validations.each do |validation|
|
10
|
+
break if @error
|
11
|
+
@error = validation.last unless send("validate_#{validation.first}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
@error.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def validate(attribute, options = {})
|
21
|
+
validations << [attribute, options[:error]]
|
22
|
+
end
|
23
|
+
|
24
|
+
def validations
|
25
|
+
@validations ||= []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
class Doorkeeper::InstallGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
|
7
|
+
def install
|
8
|
+
migration_template 'migration.rb', 'db/migrate/create_doorkeeper_tables.rb'
|
9
|
+
template "initializer.rb", "config/initializers/doorkeeper.rb"
|
10
|
+
route "mount Doorkeeper::Engine => '/oauth'"
|
11
|
+
readme "README"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.next_migration_number(dirname)
|
15
|
+
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
===============================================================================
|
2
|
+
|
3
|
+
There is a setup that you need to do before you can use doorkeeper.
|
4
|
+
|
5
|
+
Step 1.
|
6
|
+
Go to config/initializers/doorkeeper.rb and configure
|
7
|
+
resource_owner_authenticator block.
|
8
|
+
|
9
|
+
Step 2.
|
10
|
+
That's it, that's all. Enjoy!
|
11
|
+
|
12
|
+
===============================================================================
|
13
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Doorkeeper.configure do
|
2
|
+
# This block will be called to check whether the
|
3
|
+
# resource owner is authenticated or not
|
4
|
+
resource_owner_authenticator do |routes|
|
5
|
+
raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
|
6
|
+
# Put your resource owner authentication logic here.
|
7
|
+
# If you want to use named routes from your app you need
|
8
|
+
# to call them on routes object eg.
|
9
|
+
# routes.new_user_session_path
|
10
|
+
# e.g. User.find_by_id(session[:user_id]) || redirect_to routes.new_user_seesion_path
|
11
|
+
end
|
12
|
+
|
13
|
+
# If you want to restrict the access to the web interface for
|
14
|
+
# adding oauth authorized applications you need to declare the
|
15
|
+
# block below
|
16
|
+
# admin_authenticator do |routes|
|
17
|
+
# # Put your admin authentication logic here.
|
18
|
+
# # If you want to use named routes from your app you need
|
19
|
+
# # to call them on routes object eg.
|
20
|
+
# # routes.new_admin_session_path
|
21
|
+
# Admin.find_by_id(session[:admin_id]) || redirect_to routes.new_admin_session_path
|
22
|
+
# end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class CreateDoorkeeperTables < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :oauth_applications do |t|
|
4
|
+
t.string :name, :null => false
|
5
|
+
t.string :uid, :null => false
|
6
|
+
t.string :secret, :null => false
|
7
|
+
t.string :redirect_uri, :null => false
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :oauth_access_grants do |t|
|
12
|
+
t.integer :resource_owner_id, :null => false
|
13
|
+
t.integer :application_id, :null => false
|
14
|
+
t.string :token, :null => false
|
15
|
+
t.integer :expires_in, :null => false
|
16
|
+
t.string :redirect_uri, :null => false
|
17
|
+
t.datetime :created_at, :null => false
|
18
|
+
end
|
19
|
+
|
20
|
+
create_table :oauth_access_tokens do |t|
|
21
|
+
t.integer :resource_owner_id, :null => false
|
22
|
+
t.integer :application_id, :null => false
|
23
|
+
t.string :token, :null => false
|
24
|
+
t.datetime :expires_at
|
25
|
+
t.datetime :revoked_at
|
26
|
+
t.datetime :created_at, :null => false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: doorkeeper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Felipe Elias Philipp
|
9
|
+
- Piotr Jakubowski
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-11-28 00:00:00.000000000Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rails
|
17
|
+
requirement: &70336834072240 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ~>
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.1.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *70336834072240
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: sqlite3
|
28
|
+
requirement: &70336834071600 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *70336834071600
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec-rails
|
39
|
+
requirement: &70336834070820 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70336834070820
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: capybara
|
50
|
+
requirement: &70336834070040 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70336834070040
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: generator_spec
|
61
|
+
requirement: &70336834069340 !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: *70336834069340
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: factory_girl_rails
|
72
|
+
requirement: &70336834068500 !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: *70336834068500
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: timecop
|
83
|
+
requirement: &70336834068020 !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: *70336834068020
|
92
|
+
description: Doorkeeper is an OAuth 2 provider for Rails.
|
93
|
+
email:
|
94
|
+
- felipe@applicake.com
|
95
|
+
- piotr.jakubowski@applicake.com
|
96
|
+
executables: []
|
97
|
+
extensions: []
|
98
|
+
extra_rdoc_files: []
|
99
|
+
files:
|
100
|
+
- app/assets/javascripts/doorkeeper/application.js
|
101
|
+
- app/assets/stylesheets/doorkeeper/application.css
|
102
|
+
- app/assets/stylesheets/doorkeeper/form.css
|
103
|
+
- app/controllers/doorkeeper/application_controller.rb
|
104
|
+
- app/controllers/doorkeeper/applications_controller.rb
|
105
|
+
- app/controllers/doorkeeper/authorizations_controller.rb
|
106
|
+
- app/controllers/doorkeeper/tokens_controller.rb
|
107
|
+
- app/helpers/doorkeeper/application_helper.rb
|
108
|
+
- app/models/access_grant.rb
|
109
|
+
- app/models/access_token.rb
|
110
|
+
- app/models/application.rb
|
111
|
+
- app/views/doorkeeper/applications/_form.html.erb
|
112
|
+
- app/views/doorkeeper/applications/edit.html.erb
|
113
|
+
- app/views/doorkeeper/applications/index.html.erb
|
114
|
+
- app/views/doorkeeper/applications/new.html.erb
|
115
|
+
- app/views/doorkeeper/applications/show.html.erb
|
116
|
+
- app/views/doorkeeper/authorizations/error.html.erb
|
117
|
+
- app/views/doorkeeper/authorizations/new.html.erb
|
118
|
+
- app/views/layouts/doorkeeper/application.html.erb
|
119
|
+
- config/initializers/form_errors.rb
|
120
|
+
- config/routes.rb
|
121
|
+
- lib/doorkeeper/config.rb
|
122
|
+
- lib/doorkeeper/doorkeeper_for.rb
|
123
|
+
- lib/doorkeeper/engine.rb
|
124
|
+
- lib/doorkeeper/oauth/access_token_request.rb
|
125
|
+
- lib/doorkeeper/oauth/authorization_request.rb
|
126
|
+
- lib/doorkeeper/oauth/random_string.rb
|
127
|
+
- lib/doorkeeper/validations.rb
|
128
|
+
- lib/doorkeeper/version.rb
|
129
|
+
- lib/doorkeeper.rb
|
130
|
+
- lib/generators/doorkeeper/install_generator.rb
|
131
|
+
- lib/generators/doorkeeper/templates/initializer.rb
|
132
|
+
- lib/generators/doorkeeper/templates/migration.rb
|
133
|
+
- lib/generators/doorkeeper/templates/README
|
134
|
+
- lib/tasks/doorkeeper_tasks.rake
|
135
|
+
- MIT-LICENSE
|
136
|
+
- Rakefile
|
137
|
+
- README.md
|
138
|
+
homepage: https://github.com/applicake/doorkeeper
|
139
|
+
licenses: []
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 1.8.10
|
159
|
+
signing_key:
|
160
|
+
specification_version: 3
|
161
|
+
summary: Doorkeeper is an OAuth 2 provider for Rails.
|
162
|
+
test_files: []
|