oa2c 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Anton Dieterle
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,22 @@
1
+ # Oa2c - OAuth2 Container
2
+
3
+ Rails OAuth2 provider engine to support embedded iframe applications from different sites. Just like games on Facebook.
4
+
5
+ Heavily depends on [rack-oauth2](https://github.com/nov/rack-oauth2) gem.
6
+
7
+ It's mostly extract from [rack-oauth2-sample](https://github.com/nov/rack-oauth2-sample).
8
+
9
+ Right now it supports only Mongoid 3 as ORM.
10
+
11
+ # TODO
12
+
13
+ * Write specs
14
+ * Support for ActiveRecord
15
+
16
+ # License
17
+
18
+ See MIT-LICENSE
19
+
20
+ # Contribute
21
+
22
+ Pull requests are more than welcome!
data/Rakefile ADDED
@@ -0,0 +1,29 @@
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 = 'Oauth2Container'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+ Bundler::GemHelper.install_tasks
25
+
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new
28
+
29
+ task :default => :spec
@@ -0,0 +1,87 @@
1
+ module Oa2c
2
+ class AuthorizationsController < ActionController::Base
3
+ before_filter :authorize, except: :token
4
+
5
+ rescue_from Rack::OAuth2::Server::Authorize::BadRequest do |e|
6
+ @error = e
7
+ render :error, status: e.status
8
+ end
9
+
10
+ def new
11
+ respond *authorize_endpoint.call(request.env)
12
+ end
13
+
14
+ def create
15
+ respond *authorize_endpoint(true).call(request.env)
16
+ end
17
+
18
+ def token
19
+ token_endpoint.call(request.env)
20
+ end
21
+
22
+ private
23
+
24
+ def respond(status, header, response)
25
+ ["WWW-Authenticate"].each do |key|
26
+ headers[key] = header[key] if header[key].present?
27
+ end
28
+ if response.redirect?
29
+ redirect_to header['Location']
30
+ else
31
+ render :new
32
+ end
33
+ end
34
+
35
+ def authorize_endpoint(allow_approval = false)
36
+ Rack::OAuth2::Server::Authorize.new do |req, res|
37
+ @client = Auth::Client.where(identifier: req.client_id).first || req.bad_request!
38
+ res.redirect_uri = @redirect_uri = req.verify_redirect_uri!(@client.redirect_uri)
39
+ if allow_approval
40
+ if params[:approve]
41
+ case req.response_type
42
+ when :code
43
+ authorization_code = current_user.authorization_codes.create(client_id: @client.id, redirect_uri: res.redirect_uri)
44
+ res.code = authorization_code.token
45
+ when :token
46
+ res.access_token = current_user.access_tokens.create(client_id: @client.id).to_bearer_token
47
+ end
48
+ res.approve!
49
+ else
50
+ req.access_denied!
51
+ end
52
+ else
53
+ @response_type = req.response_type
54
+ end
55
+ end
56
+ end
57
+
58
+ def token_endpoint
59
+ Rack::OAuth2::Server::Token.new do |req, res|
60
+ client = Auth::Client.where(identifier: req.client_id).first || req.invalid_client!
61
+ client.secret == req.client_secret || req.invalid_client!
62
+ case req.grant_type
63
+ when :authorization_code
64
+ code = Auth::AuthorizationCode.valid.where(token: req.code).first
65
+ req.invalid_grant! if code.blank? || code.redirect_uri != req.redirect_uri
66
+ res.access_token = code.access_token.to_bearer_token(:with_refresh_token)
67
+ when :password
68
+ # NOTE: password is not hashed in this sample app. Don't do the same on your app.
69
+ # FIXME
70
+ account = Account.find_by_username_and_password(req.username, req.password) || req.invalid_grant!
71
+ res.access_token = account.access_tokens.create(:client => client).to_bearer_token(:with_refresh_token)
72
+ when :client_credentials
73
+ # NOTE: client is already authenticated here.
74
+ res.access_token = client.access_tokens.create.to_bearer_token
75
+ when :refresh_token
76
+ refresh_token = client.refresh_tokens.valid.wehre(token: req.refresh_token).first
77
+ req.invalid_grant! unless refresh_token
78
+ res.access_token = refresh_token.access_tokens.create.to_bearer_token
79
+ else
80
+ # NOTE: extended assertion grant_types are not supported yet.
81
+ req.unsupported_grant_type!
82
+ end
83
+ end
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,29 @@
1
+ require 'oa2c/oauth2_token'
2
+ module Oa2c
3
+ class AccessToken
4
+ include Mongoid::Document
5
+ include OAuth2Token
6
+
7
+ belongs_to :refresh_token
8
+
9
+ def to_bearer_token(with_refresh_token = false)
10
+ Rack::OAuth2::AccessToken::Bearer.new(access_token: token, expires_in: expires_in).tap do |bearer_token|
11
+ if with_refresh_token
12
+ bearer_token.refresh_token = create_refresh_token(user: user, client: client).token
13
+ end
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def setup
20
+ super
21
+ if refresh_token
22
+ self.user = refresh_token.user
23
+ self.client = refresh_token.client
24
+ self.expires_at = [expires_at, refresh_token.expires_at].min
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,10 @@
1
+ module Oa2c
2
+ class AuthorizationCode
3
+ include Mongoid::Document
4
+ include OAuth2Token
5
+
6
+ def access_token
7
+ @access_token ||= expire! && user.access_tokens.create(client: client)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,32 @@
1
+ module Oa2c
2
+ class Client
3
+ include Mongoid::Document
4
+
5
+ field :identifier
6
+ field :secret
7
+ field :redirect_uri
8
+
9
+ has_many :access_tokens
10
+ has_many :refresh_tokens
11
+
12
+ before_validation :setup, on: :create
13
+ validates :secret, presence: true
14
+ validates :identifier, presence: true, uniqueness: true
15
+
16
+ private
17
+
18
+ def setup
19
+ self.identifier = SecureRandom.hex(16)
20
+ generate_secret
21
+ end
22
+
23
+ def generate_secret
24
+ self.secret = SecureRandom.hex(32)
25
+ end
26
+
27
+ def generate_secret!
28
+ generate_secret
29
+ save!
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ module Oa2c
2
+ module OAuth2Token
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ cattr_accessor :default_lifetime
7
+ self.default_lifetime = 15.minutes
8
+
9
+ field :token
10
+ field :expires_at, type: Time
11
+
12
+ belongs_to :user
13
+ belongs_to :client
14
+
15
+ before_validation :setup, on: :create
16
+ validates :client, :expires_at, presence: true
17
+ validates :token, presence: true, uniqueness: true
18
+
19
+ scope :valid, proc { where(:expires_at.gte => Time.now) }
20
+ end
21
+
22
+ def expires_in
23
+ (expires_at - Time.now).to_i
24
+ end
25
+
26
+ def expire!
27
+ update_attributes! expires_at: Time.now
28
+ end
29
+
30
+ private
31
+
32
+ def setup
33
+ self.token = SecureRandom.hex(32)
34
+ self.expires_at ||= default_lifetime.from_now
35
+ end
36
+ end
37
+ end
38
+
39
+
@@ -0,0 +1,10 @@
1
+ module Oa2c
2
+ class RefreshToken
3
+ include Mongoid::Document
4
+ include OAuth2Token
5
+
6
+ self.default_lifetime = 1.month
7
+ has_many :access_tokens
8
+ end
9
+ end
10
+
@@ -0,0 +1,7 @@
1
+ <%= form_tag authorizations_path, :class => action do %>
2
+ <%= hidden_field_tag :client_id, client.identifier %>
3
+ <%= hidden_field_tag :response_type, response_type %>
4
+ <%= hidden_field_tag :redirect_uri, redirect_uri %>
5
+ <%= submit_tag action.to_s.capitalize %>
6
+ <%= hiden_field_tag action, true %>
7
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <h2>Invalid Authorization Request</h2>
2
+ <h3><%= @error.error %></h3>
3
+ <p><%= @error.description %></p>
@@ -0,0 +1,5 @@
1
+ <h2><%= @client.name %> is requiring your resource access</h2>
2
+
3
+ <%= render 'form', client: @client, response_type: @response_type, redirect_uri: @redirect_uri, action: :deny %>
4
+ <%= render 'form', client: @client, response_type: @response_type, redirect_uri: @redirect_uri, action: :approve %>
5
+
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Oa2c::Engine.routes.draw do
2
+ post 'authorizations/create'
3
+ match 'authorize', to: 'authorizations#new'
4
+ match 'token', to: proc {|env| Auth::AuthorizationsController.new.send(:token_endpoint).call(env) }
5
+ end
data/lib/oa2c.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rack/oauth2'
2
+ require 'mongoid'
3
+ require 'oa2c/engine'
4
+
5
+ module Oa2c
6
+ end
@@ -0,0 +1,29 @@
1
+ module Oa2c
2
+ module Authentication
3
+ def current_token
4
+ @current_token
5
+ end
6
+
7
+ def current_client
8
+ @current_client
9
+ end
10
+
11
+ def require_oauth_token
12
+ @current_token = Auth::AccessToken.where(token: request.env[Rack::OAuth2::Server::Resource::ACCESS_TOKEN].token).first # FIXME Right now an AccessToken object is store here, need to store only token
13
+ raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized unless @current_token
14
+ end
15
+
16
+ def require_oauth_user_token
17
+ require_oauth_token
18
+ raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(:invalid_token, 'User token is required') unless @current_token.user
19
+ authenticate @current_token.user
20
+ end
21
+
22
+ def require_oauth_client_token
23
+ require_oauth_token
24
+ raise Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(:invalid_token, 'Client token is required') if @current_token.user
25
+ @current_client = @current_token.client
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,6 @@
1
+ module Oa2c
2
+ class Engine < Rails::Engine
3
+ isolate_namespace Oa2c
4
+ config.orm = :mongoid
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Oa2c
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :oa2c do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oa2c
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Anton Dieterle
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rack-oauth2
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.14.9
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.14.9
46
+ - !ruby/object:Gem::Dependency
47
+ name: mongoid
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec-rails
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: sqlite3
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ description: Rails engine to provide OAuth2 authorization for embedded iframe applications.
95
+ email:
96
+ - antondie@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - app/models/oa2c/oauth2_token.rb
102
+ - app/models/oa2c/client.rb
103
+ - app/models/oa2c/refresh_token.rb
104
+ - app/models/oa2c/authorization_code.rb
105
+ - app/models/oa2c/access_token.rb
106
+ - app/views/oa2c/_form.html.erb
107
+ - app/views/oa2c/error.html.erb
108
+ - app/views/oa2c/new.html.erb
109
+ - app/controllers/oa2c/authorizations_controller.rb
110
+ - config/routes.rb
111
+ - lib/tasks/oa2c_tasks.rake
112
+ - lib/oa2c.rb
113
+ - lib/oa2c/version.rb
114
+ - lib/oa2c/authentication.rb
115
+ - lib/oa2c/engine.rb
116
+ - MIT-LICENSE
117
+ - Rakefile
118
+ - README.md
119
+ homepage: https://github.com/adie/oa2c
120
+ licenses: []
121
+ post_install_message:
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ segments:
132
+ - 0
133
+ hash: -181462029
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ segments:
141
+ - 0
142
+ hash: -181462029
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 1.8.24
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: OAuth2 authorization for embedded iframe applications.
149
+ test_files: []