grape_oauth2 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +18 -0
- data/.travis.yml +42 -0
- data/Gemfile +23 -0
- data/README.md +820 -0
- data/Rakefile +11 -0
- data/gemfiles/active_record.rb +25 -0
- data/gemfiles/mongoid.rb +14 -0
- data/gemfiles/sequel.rb +24 -0
- data/grape_oauth2.gemspec +27 -0
- data/grape_oauth2.png +0 -0
- data/lib/grape_oauth2.rb +129 -0
- data/lib/grape_oauth2/configuration.rb +143 -0
- data/lib/grape_oauth2/configuration/class_accessors.rb +36 -0
- data/lib/grape_oauth2/configuration/validation.rb +71 -0
- data/lib/grape_oauth2/endpoints/authorize.rb +34 -0
- data/lib/grape_oauth2/endpoints/token.rb +72 -0
- data/lib/grape_oauth2/gem_version.rb +24 -0
- data/lib/grape_oauth2/generators/authorization.rb +44 -0
- data/lib/grape_oauth2/generators/base.rb +26 -0
- data/lib/grape_oauth2/generators/token.rb +62 -0
- data/lib/grape_oauth2/helpers/access_token_helpers.rb +54 -0
- data/lib/grape_oauth2/helpers/oauth_params.rb +41 -0
- data/lib/grape_oauth2/mixins/active_record/access_grant.rb +47 -0
- data/lib/grape_oauth2/mixins/active_record/access_token.rb +75 -0
- data/lib/grape_oauth2/mixins/active_record/client.rb +35 -0
- data/lib/grape_oauth2/mixins/mongoid/access_grant.rb +58 -0
- data/lib/grape_oauth2/mixins/mongoid/access_token.rb +88 -0
- data/lib/grape_oauth2/mixins/mongoid/client.rb +41 -0
- data/lib/grape_oauth2/mixins/sequel/access_grant.rb +68 -0
- data/lib/grape_oauth2/mixins/sequel/access_token.rb +86 -0
- data/lib/grape_oauth2/mixins/sequel/client.rb +46 -0
- data/lib/grape_oauth2/responses/authorization.rb +10 -0
- data/lib/grape_oauth2/responses/base.rb +56 -0
- data/lib/grape_oauth2/responses/token.rb +10 -0
- data/lib/grape_oauth2/scopes.rb +74 -0
- data/lib/grape_oauth2/strategies/authorization_code.rb +38 -0
- data/lib/grape_oauth2/strategies/base.rb +47 -0
- data/lib/grape_oauth2/strategies/client_credentials.rb +20 -0
- data/lib/grape_oauth2/strategies/password.rb +22 -0
- data/lib/grape_oauth2/strategies/refresh_token.rb +47 -0
- data/lib/grape_oauth2/unique_token.rb +20 -0
- data/lib/grape_oauth2/version.rb +14 -0
- data/spec/configuration/config_spec.rb +231 -0
- data/spec/configuration/version_spec.rb +12 -0
- data/spec/dummy/endpoints/custom_authorization.rb +25 -0
- data/spec/dummy/endpoints/custom_token.rb +35 -0
- data/spec/dummy/endpoints/status.rb +25 -0
- data/spec/dummy/grape_oauth2_config.rb +11 -0
- data/spec/dummy/orm/active_record/app/config/db.rb +7 -0
- data/spec/dummy/orm/active_record/app/models/access_code.rb +3 -0
- data/spec/dummy/orm/active_record/app/models/access_token.rb +3 -0
- data/spec/dummy/orm/active_record/app/models/application.rb +3 -0
- data/spec/dummy/orm/active_record/app/models/application_record.rb +3 -0
- data/spec/dummy/orm/active_record/app/models/user.rb +10 -0
- data/spec/dummy/orm/active_record/app/twitter.rb +36 -0
- data/spec/dummy/orm/active_record/config.ru +7 -0
- data/spec/dummy/orm/active_record/db/schema.rb +53 -0
- data/spec/dummy/orm/mongoid/app/config/db.rb +6 -0
- data/spec/dummy/orm/mongoid/app/config/mongoid.yml +21 -0
- data/spec/dummy/orm/mongoid/app/models/access_code.rb +3 -0
- data/spec/dummy/orm/mongoid/app/models/access_token.rb +3 -0
- data/spec/dummy/orm/mongoid/app/models/application.rb +3 -0
- data/spec/dummy/orm/mongoid/app/models/user.rb +11 -0
- data/spec/dummy/orm/mongoid/app/twitter.rb +34 -0
- data/spec/dummy/orm/mongoid/config.ru +5 -0
- data/spec/dummy/orm/sequel/app/config/db.rb +1 -0
- data/spec/dummy/orm/sequel/app/models/access_code.rb +4 -0
- data/spec/dummy/orm/sequel/app/models/access_token.rb +4 -0
- data/spec/dummy/orm/sequel/app/models/application.rb +4 -0
- data/spec/dummy/orm/sequel/app/models/application_record.rb +2 -0
- data/spec/dummy/orm/sequel/app/models/user.rb +11 -0
- data/spec/dummy/orm/sequel/app/twitter.rb +47 -0
- data/spec/dummy/orm/sequel/config.ru +5 -0
- data/spec/dummy/orm/sequel/db/schema.rb +50 -0
- data/spec/lib/scopes_spec.rb +50 -0
- data/spec/mixins/active_record/access_token_spec.rb +185 -0
- data/spec/mixins/active_record/client_spec.rb +95 -0
- data/spec/mixins/mongoid/access_token_spec.rb +185 -0
- data/spec/mixins/mongoid/client_spec.rb +95 -0
- data/spec/mixins/sequel/access_token_spec.rb +185 -0
- data/spec/mixins/sequel/client_spec.rb +96 -0
- data/spec/requests/flows/authorization_code_spec.rb +67 -0
- data/spec/requests/flows/client_credentials_spec.rb +101 -0
- data/spec/requests/flows/password_spec.rb +210 -0
- data/spec/requests/flows/refresh_token_spec.rb +222 -0
- data/spec/requests/flows/revoke_token_spec.rb +103 -0
- data/spec/requests/protected_resources_spec.rb +64 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/support/api_helper.rb +11 -0
- metadata +257 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Grape::OAuth2 Version' do
|
4
|
+
it 'has a version string' do
|
5
|
+
expect(Grape::OAuth2::VERSION::STRING).to be_present
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'returns version as an instance of Gem::Version' do
|
9
|
+
expect(Grape::OAuth2.gem_version).to be_an_instance_of(Gem::Version)
|
10
|
+
expect(Grape::OAuth2.version).to be_an_instance_of(Gem::Version)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Twitter
|
2
|
+
module Endpoints
|
3
|
+
class CustomAuthorization < ::Grape::API
|
4
|
+
helpers Grape::OAuth2::Helpers::OAuthParams
|
5
|
+
|
6
|
+
namespace :oauth do
|
7
|
+
params do
|
8
|
+
use :oauth_authorization_params
|
9
|
+
end
|
10
|
+
|
11
|
+
post :custom_authorize do
|
12
|
+
response = Grape::OAuth2::Generators::Authorization.generate_for(env) do |request, response|
|
13
|
+
request.unsupported_response_type!
|
14
|
+
end
|
15
|
+
|
16
|
+
# Status
|
17
|
+
status response.status
|
18
|
+
|
19
|
+
# Body
|
20
|
+
body response.body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Twitter
|
2
|
+
module Endpoints
|
3
|
+
class CustomToken < ::Grape::API
|
4
|
+
helpers Grape::OAuth2::Helpers::OAuthParams
|
5
|
+
|
6
|
+
namespace :oauth do
|
7
|
+
params do
|
8
|
+
use :oauth_token_params
|
9
|
+
end
|
10
|
+
|
11
|
+
post :custom_token do
|
12
|
+
token_response = Grape::OAuth2::Generators::Token.generate_for(env) do |request, response|
|
13
|
+
# Custom client authentication:
|
14
|
+
client = Grape::OAuth2::Strategies::Base.authenticate_client(request)
|
15
|
+
request.invalid_client! if client.nil? || client.name != 'Admin'
|
16
|
+
|
17
|
+
resource_owner = Grape::OAuth2::Strategies::Base.authenticate_resource_owner(client, request)
|
18
|
+
request.invalid_grant! if resource_owner.nil?
|
19
|
+
|
20
|
+
token = AccessToken.create_for(client, resource_owner, request.scope.join(' '))
|
21
|
+
response.access_token = Grape::OAuth2::Strategies::Base.expose_to_bearer_token(token)
|
22
|
+
end
|
23
|
+
|
24
|
+
status token_response.status
|
25
|
+
|
26
|
+
token_response.headers.each do |key, value|
|
27
|
+
header key, value
|
28
|
+
end
|
29
|
+
|
30
|
+
body token_response.body
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Twitter
|
2
|
+
module Endpoints
|
3
|
+
class Status < Grape::API
|
4
|
+
before do
|
5
|
+
access_token_required!
|
6
|
+
end
|
7
|
+
|
8
|
+
resources :status do
|
9
|
+
get do
|
10
|
+
{ value: 'Nice day!', current_user: current_resource_owner.username }
|
11
|
+
end
|
12
|
+
|
13
|
+
get :single_scope, scopes: [:read] do
|
14
|
+
{ value: 'Access granted' }
|
15
|
+
end
|
16
|
+
|
17
|
+
get :multiple_scopes, scopes: [:read, :write] do
|
18
|
+
access_token_required!
|
19
|
+
|
20
|
+
{ value: 'Access granted' }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Common config across all the ORMs
|
2
|
+
Grape::OAuth2.configure do |config|
|
3
|
+
config.client_class_name = 'Application'
|
4
|
+
config.access_token_class_name = 'AccessToken'
|
5
|
+
config.resource_owner_class_name = 'User'
|
6
|
+
config.access_grant_class_name = 'AccessCode'
|
7
|
+
|
8
|
+
config.realm = 'Custom Realm'
|
9
|
+
|
10
|
+
config.allowed_grant_types << 'refresh_token'
|
11
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
OTR::ActiveRecord.configure_from_hash!(adapter: 'sqlite3', database: ':memory:')
|
2
|
+
|
3
|
+
::ActiveRecord::Base.default_timezone = :utc
|
4
|
+
::ActiveRecord::Base.logger = ENV['RAILS_ENV'] == 'test' ? nil : Logger.new(STDOUT)
|
5
|
+
|
6
|
+
::ActiveRecord::Migration.verbose = false
|
7
|
+
load File.expand_path('../../../db/schema.rb', __FILE__)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'otr-activerecord'
|
2
|
+
require 'grape'
|
3
|
+
|
4
|
+
require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
|
5
|
+
|
6
|
+
# Database
|
7
|
+
load File.expand_path('../config/db.rb', __FILE__)
|
8
|
+
|
9
|
+
# Grape::OAuth2 config
|
10
|
+
load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
|
11
|
+
|
12
|
+
# Models
|
13
|
+
require_relative 'models/application_record'
|
14
|
+
require_relative 'models/access_token'
|
15
|
+
require_relative 'models/access_code'
|
16
|
+
require_relative 'models/application'
|
17
|
+
require_relative 'models/user'
|
18
|
+
|
19
|
+
# Twitter Endpoints
|
20
|
+
require_relative '../../../endpoints/custom_token'
|
21
|
+
require_relative '../../../endpoints/custom_authorization'
|
22
|
+
require_relative '../../../endpoints/status'
|
23
|
+
|
24
|
+
module Twitter
|
25
|
+
class API < Grape::API
|
26
|
+
version 'v1', using: :path
|
27
|
+
format :json
|
28
|
+
prefix :api
|
29
|
+
|
30
|
+
include Grape::OAuth2.api
|
31
|
+
|
32
|
+
mount Twitter::Endpoints::Status
|
33
|
+
mount Twitter::Endpoints::CustomToken
|
34
|
+
mount Twitter::Endpoints::CustomAuthorization
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
ActiveRecord::Schema.define(version: 3) do
|
2
|
+
create_table :users do |t|
|
3
|
+
t.string :name
|
4
|
+
t.string :username
|
5
|
+
t.string :password_digest
|
6
|
+
end
|
7
|
+
|
8
|
+
create_table :applications do |t|
|
9
|
+
t.string :name
|
10
|
+
t.string :key
|
11
|
+
t.string :secret
|
12
|
+
t.string :redirect_uri
|
13
|
+
|
14
|
+
t.timestamps null: false
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :applications, :key, unique: true
|
18
|
+
|
19
|
+
create_table :access_tokens do |t|
|
20
|
+
t.integer :resource_owner_id
|
21
|
+
t.integer :client_id
|
22
|
+
|
23
|
+
t.string :token, null: false
|
24
|
+
t.string :refresh_token
|
25
|
+
t.string :scopes
|
26
|
+
|
27
|
+
t.datetime :expires_at
|
28
|
+
t.datetime :revoked_at
|
29
|
+
t.datetime :created_at, null: false
|
30
|
+
end
|
31
|
+
|
32
|
+
create_table :access_codes do |t|
|
33
|
+
t.integer :resource_owner_id
|
34
|
+
t.integer :client_id
|
35
|
+
|
36
|
+
t.string :token, null: false
|
37
|
+
t.string :redirect_uri
|
38
|
+
t.string :scopes
|
39
|
+
|
40
|
+
t.datetime :expires_at
|
41
|
+
t.datetime :revoked_at
|
42
|
+
t.datetime :created_at, null: false
|
43
|
+
end
|
44
|
+
|
45
|
+
add_index :access_tokens, :token, unique: true
|
46
|
+
add_index :access_tokens, :resource_owner_id
|
47
|
+
add_index :access_tokens, :client_id
|
48
|
+
add_index :access_tokens, :refresh_token, unique: true
|
49
|
+
|
50
|
+
add_index :access_codes, :token, unique: true
|
51
|
+
add_index :access_codes, :resource_owner_id
|
52
|
+
add_index :access_codes, :client_id
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
development:
|
2
|
+
clients:
|
3
|
+
default:
|
4
|
+
database: mongoid-dev
|
5
|
+
hosts:
|
6
|
+
- localhost:27017
|
7
|
+
options:
|
8
|
+
raise_not_found_error: false
|
9
|
+
write:
|
10
|
+
w: 1
|
11
|
+
|
12
|
+
test:
|
13
|
+
clients:
|
14
|
+
default:
|
15
|
+
database: mongoid-test
|
16
|
+
hosts:
|
17
|
+
- localhost:27017
|
18
|
+
options:
|
19
|
+
raise_not_found_error: false
|
20
|
+
write:
|
21
|
+
w: 1
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class User
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps
|
4
|
+
|
5
|
+
field :username, type: String
|
6
|
+
field :password, type: String
|
7
|
+
|
8
|
+
def self.oauth_authenticate(_client, username, password)
|
9
|
+
find_by(username: username, password: password)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'grape'
|
2
|
+
|
3
|
+
require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
|
4
|
+
|
5
|
+
# Database
|
6
|
+
load File.expand_path('../config/db.rb', __FILE__)
|
7
|
+
|
8
|
+
# Grape::OAuth2 config
|
9
|
+
load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
|
10
|
+
|
11
|
+
# Models
|
12
|
+
require_relative 'models/access_token'
|
13
|
+
require_relative 'models/access_code'
|
14
|
+
require_relative 'models/application'
|
15
|
+
require_relative 'models/user'
|
16
|
+
|
17
|
+
# Twitter Endpoints
|
18
|
+
require_relative '../../../endpoints/custom_token'
|
19
|
+
require_relative '../../../endpoints/custom_authorization'
|
20
|
+
require_relative '../../../endpoints/status'
|
21
|
+
|
22
|
+
module Twitter
|
23
|
+
class API < Grape::API
|
24
|
+
version 'v1', using: :path
|
25
|
+
format :json
|
26
|
+
prefix :api
|
27
|
+
|
28
|
+
include Grape::OAuth2.api
|
29
|
+
|
30
|
+
mount Twitter::Endpoints::Status
|
31
|
+
mount Twitter::Endpoints::CustomToken
|
32
|
+
mount Twitter::Endpoints::CustomAuthorization
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
load File.expand_path('../../../db/schema.rb', __FILE__)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class User < ApplicationRecord
|
2
|
+
set_dataset :users
|
3
|
+
plugin :secure_password, include_validations: false
|
4
|
+
|
5
|
+
def self.oauth_authenticate(_client, username, password)
|
6
|
+
user = find(username: username)
|
7
|
+
return if user.nil?
|
8
|
+
|
9
|
+
user.authenticate(password)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'grape'
|
2
|
+
|
3
|
+
require File.expand_path('../../../../../../lib/grape_oauth2', __FILE__)
|
4
|
+
|
5
|
+
# SQLite memory database
|
6
|
+
DB = if defined?(JRUBY_VERSION)
|
7
|
+
Sequel.connect('jdbc:sqlite::memory:')
|
8
|
+
else
|
9
|
+
Sequel.sqlite
|
10
|
+
end
|
11
|
+
|
12
|
+
# Database
|
13
|
+
load File.expand_path('../config/db.rb', __FILE__)
|
14
|
+
|
15
|
+
# Grape::OAuth2 config
|
16
|
+
load File.expand_path('../../../../grape_oauth2_config.rb', __FILE__)
|
17
|
+
|
18
|
+
# Models
|
19
|
+
require_relative 'models/application_record'
|
20
|
+
require_relative 'models/access_token'
|
21
|
+
require_relative 'models/access_code'
|
22
|
+
require_relative 'models/application'
|
23
|
+
require_relative 'models/user'
|
24
|
+
|
25
|
+
# Twitter Endpoints
|
26
|
+
require_relative '../../../endpoints/custom_token'
|
27
|
+
require_relative '../../../endpoints/custom_authorization'
|
28
|
+
require_relative '../../../endpoints/status'
|
29
|
+
|
30
|
+
module Twitter
|
31
|
+
class API < Grape::API
|
32
|
+
version 'v1', using: :path
|
33
|
+
format :json
|
34
|
+
prefix :api
|
35
|
+
|
36
|
+
use *Grape::OAuth2.middleware
|
37
|
+
|
38
|
+
helpers Grape::OAuth2::Helpers::AccessTokenHelpers
|
39
|
+
|
40
|
+
mount Grape::OAuth2::Endpoints::Token
|
41
|
+
mount Grape::OAuth2::Endpoints::Authorize
|
42
|
+
|
43
|
+
mount Twitter::Endpoints::Status
|
44
|
+
mount Twitter::Endpoints::CustomToken
|
45
|
+
mount Twitter::Endpoints::CustomAuthorization
|
46
|
+
end
|
47
|
+
end
|