doorkeeper-openid_connect 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +90 -0
  7. data/Rakefile +7 -0
  8. data/app/controllers/doorkeeper/openid_connect/userinfo_controller.rb +19 -0
  9. data/config/locales/en.yml +20 -0
  10. data/doorkeeper-openid_connect.gemspec +27 -0
  11. data/lib/doorkeeper/openid_connect.rb +65 -0
  12. data/lib/doorkeeper/openid_connect/claims_builder.rb +24 -0
  13. data/lib/doorkeeper/openid_connect/config.rb +125 -0
  14. data/lib/doorkeeper/openid_connect/engine.rb +9 -0
  15. data/lib/doorkeeper/openid_connect/models/claims/aggregated_claim.rb +11 -0
  16. data/lib/doorkeeper/openid_connect/models/claims/claim.rb +15 -0
  17. data/lib/doorkeeper/openid_connect/models/claims/distributed_claim.rb +11 -0
  18. data/lib/doorkeeper/openid_connect/models/claims/normal_claim.rb +28 -0
  19. data/lib/doorkeeper/openid_connect/models/id_token.rb +63 -0
  20. data/lib/doorkeeper/openid_connect/models/user_info.rb +39 -0
  21. data/lib/doorkeeper/openid_connect/rails/routes.rb +50 -0
  22. data/lib/doorkeeper/openid_connect/rails/routes/mapper.rb +30 -0
  23. data/lib/doorkeeper/openid_connect/rails/routes/mapping.rb +34 -0
  24. data/lib/doorkeeper/openid_connect/version.rb +5 -0
  25. data/spec/dummy/Rakefile +7 -0
  26. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  27. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +7 -0
  28. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  29. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  30. data/spec/dummy/app/controllers/metal_controller.rb +11 -0
  31. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  32. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  33. data/spec/dummy/app/models/user.rb +31 -0
  34. data/spec/dummy/app/views/home/index.html.erb +0 -0
  35. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  36. data/spec/dummy/config.ru +4 -0
  37. data/spec/dummy/config/application.rb +55 -0
  38. data/spec/dummy/config/boot.rb +6 -0
  39. data/spec/dummy/config/database.yml +15 -0
  40. data/spec/dummy/config/environment.rb +5 -0
  41. data/spec/dummy/config/environments/development.rb +29 -0
  42. data/spec/dummy/config/environments/production.rb +62 -0
  43. data/spec/dummy/config/environments/test.rb +56 -0
  44. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/dummy/config/initializers/doorkeeper.rb +59 -0
  46. data/spec/dummy/config/initializers/secret_token.rb +9 -0
  47. data/spec/dummy/config/initializers/session_store.rb +8 -0
  48. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  49. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  50. data/spec/dummy/config/mongo.yml +11 -0
  51. data/spec/dummy/config/mongoid2.yml +9 -0
  52. data/spec/dummy/config/mongoid3.yml +18 -0
  53. data/spec/dummy/config/mongoid4.yml +19 -0
  54. data/spec/dummy/config/routes.rb +52 -0
  55. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  56. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  57. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +41 -0
  58. data/spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb +7 -0
  59. data/spec/dummy/db/schema.rb +65 -0
  60. data/spec/dummy/log/test.log +16605 -0
  61. data/spec/dummy/public/404.html +26 -0
  62. data/spec/dummy/public/422.html +26 -0
  63. data/spec/dummy/public/500.html +26 -0
  64. data/spec/dummy/public/favicon.ico +0 -0
  65. data/spec/dummy/script/rails +6 -0
  66. data/spec/lib/doorkeeper/openid_connect/config_spec.rb +65 -0
  67. data/spec/spec_helper.rb +2 -0
  68. data/spec/spec_helper_integration.rb +48 -0
  69. metadata +239 -0
@@ -0,0 +1,9 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ class Engine < ::Rails::Engine
4
+ initializer 'doorkeeper.openid_connect.routes' do
5
+ Doorkeeper::OpenidConnect::Rails::Routes.install!
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Models
4
+ module Claims
5
+ class AggregatedClaim < Claim
6
+ attr_accessor :jwt
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Models
4
+ module Claims
5
+ class Claim
6
+ attr_accessor :name
7
+
8
+ def initialize(options = {})
9
+ @name = options[:name]
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Models
4
+ module Claims
5
+ class DistributedClaim < Claim
6
+ attr_accessor :endpoint, :access_token
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,28 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Models
4
+ module Claims
5
+ class NormalClaim < Claim
6
+ attr_reader :value
7
+
8
+ def initialize(options = {})
9
+ super(options)
10
+ @value = options[:value]
11
+ end
12
+
13
+ def type
14
+ :normal
15
+ end
16
+
17
+ def method_missing(method_sym, *arguments, &block)
18
+ @value
19
+ end
20
+
21
+ def response_to?(method_sym, *arguments, &block)
22
+ method_sym.to_s == @name
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,63 @@
1
+ require 'sandal'
2
+
3
+ module Doorkeeper
4
+ module OpenidConnect
5
+ module Models
6
+ class IdToken
7
+ include ActiveModel::Validations
8
+
9
+ def initialize(access_token)
10
+ @access_token = access_token
11
+ @resource_owner = access_token.instance_eval(&Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token)
12
+ @issued_at = Time.now
13
+ @signer = Sandal::Sig::RS256.new(Doorkeeper::OpenidConnect.configuration.jws_private_key)
14
+ @public_key = Doorkeeper::OpenidConnect.configuration.jws_public_key
15
+ end
16
+
17
+ def claims
18
+ {
19
+ iss: issuer,
20
+ sub: subject,
21
+ aud: audience,
22
+ exp: expiration,
23
+ iat: issued_at
24
+ }
25
+ end
26
+
27
+ def as_json(options = {})
28
+ claims
29
+ end
30
+
31
+ # TODO make signature strategy configurable with keys?
32
+ # TODO move this out of the model
33
+ def as_jws_token
34
+ Sandal.encode_token(claims, @signer, {
35
+ kid: @public_key
36
+ })
37
+ end
38
+
39
+ private
40
+
41
+ def issuer
42
+ Doorkeeper::OpenidConnect.configuration.issuer
43
+ end
44
+
45
+ def subject
46
+ @resource_owner.instance_eval(&Doorkeeper::OpenidConnect.configuration.subject).to_s
47
+ end
48
+
49
+ def audience
50
+ @access_token.application.uid
51
+ end
52
+
53
+ def expiration
54
+ (@issued_at.utc + Doorkeeper::OpenidConnect.configuration.expiration).to_i
55
+ end
56
+
57
+ def issued_at
58
+ @issued_at.utc.to_i
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,39 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Models
4
+ class UserInfo
5
+ include ActiveModel::Validations
6
+
7
+ def initialize(resource_owner)
8
+ @resource_owner = resource_owner
9
+ end
10
+
11
+ def claims
12
+ base_claims.merge resource_owner_claims
13
+ end
14
+
15
+ def as_json(options = {})
16
+ claims
17
+ end
18
+
19
+ private
20
+
21
+ def base_claims
22
+ {
23
+ sub: subject
24
+ }
25
+ end
26
+
27
+ def resource_owner_claims
28
+ Doorkeeper::OpenidConnect.configuration.claims.to_h.map do |claim_name, claim_value|
29
+ [claim_name, @resource_owner.instance_eval(&claim_value)]
30
+ end.to_h
31
+ end
32
+
33
+ def subject
34
+ @resource_owner.instance_eval(&Doorkeeper::OpenidConnect.configuration.subject).to_s
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ require 'doorkeeper/openid_connect/rails/routes/mapping'
2
+ require 'doorkeeper/openid_connect/rails/routes/mapper'
3
+
4
+ module Doorkeeper
5
+ module OpenidConnect
6
+ module Rails
7
+ class Routes
8
+ module Helper
9
+ def use_doorkeeper_openid_connect(options = {}, &block)
10
+ Doorkeeper::OpenidConnect::Rails::Routes.new(self, &block).generate_routes!(options)
11
+ end
12
+ end
13
+
14
+ def self.install!
15
+ ActionDispatch::Routing::Mapper.send :include, Doorkeeper::OpenidConnect::Rails::Routes::Helper
16
+ end
17
+
18
+ attr_accessor :routes
19
+
20
+ def initialize(routes, &block)
21
+ @routes, @block = routes, block
22
+ end
23
+
24
+ def generate_routes!(options)
25
+ @mapping = Mapper.new.map(&@block)
26
+ routes.scope options[:scope] || 'oauth', as: 'oauth' do
27
+ map_route(:userinfo, :userinfo_routes)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def map_route(name, method)
34
+ unless @mapping.skipped?(name)
35
+ send method, @mapping[name]
36
+ end
37
+ end
38
+
39
+ def userinfo_routes(mapping)
40
+ routes.resource(
41
+ :userinfo,
42
+ path: 'userinfo',
43
+ only: [:show], as: mapping[:as],
44
+ controller: mapping[:controllers]
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,30 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Rails
4
+ class Routes
5
+ class Mapper
6
+ def initialize(mapping = Mapping.new)
7
+ @mapping = mapping
8
+ end
9
+
10
+ def map(&block)
11
+ self.instance_eval(&block) if block
12
+ @mapping
13
+ end
14
+
15
+ def controllers(controller_names = {})
16
+ @mapping.controllers.merge!(controller_names)
17
+ end
18
+
19
+ def skip_controllers(*controller_names)
20
+ @mapping.skips = controller_names
21
+ end
22
+
23
+ def as(alias_names = {})
24
+ @mapping.as.merge!(alias_names)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ module Rails
4
+ class Routes
5
+ class Mapping
6
+ attr_accessor :controllers, :as, :skips
7
+
8
+ def initialize
9
+ @controllers = {
10
+ userinfo: 'doorkeeper/openid_connect/userinfo'
11
+ }
12
+
13
+ @as = {
14
+ userinfo: :userinfo
15
+ }
16
+
17
+ @skips = []
18
+ end
19
+
20
+ def [](routes)
21
+ {
22
+ controllers: @controllers[routes],
23
+ as: @as[routes]
24
+ }
25
+ end
26
+
27
+ def skipped?(controller)
28
+ @skips.include?(controller)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ module Doorkeeper
2
+ module OpenidConnect
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,7 @@
1
+ class CustomAuthorizationsController < ::ApplicationController
2
+ %w(index show new create edit update destroy).each do |action|
3
+ define_method action do
4
+ render nothing: true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class FullProtectedResourcesController < ApplicationController
2
+ # doorkeeper_for :index
3
+ # doorkeeper_for :show, scopes: [:admin]
4
+
5
+ def index
6
+ render text: 'index'
7
+ end
8
+
9
+ def show
10
+ render text: 'show'
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ class HomeController < ApplicationController
2
+ def index
3
+ end
4
+
5
+ def sign_in
6
+ session[:user_id] = if Rails.env.development?
7
+ User.first || User.create!(name: 'Joe', password: 'sekret')
8
+ else
9
+ User.first
10
+ end
11
+ redirect_to '/'
12
+ end
13
+
14
+ def callback
15
+ render text: 'ok'
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class MetalController < ActionController::Metal
2
+ include AbstractController::Callbacks
3
+ include ActionController::Head
4
+ # include Doorkeeper::Helpers::Filter
5
+
6
+ # doorkeeper_for :all
7
+
8
+ def index
9
+ self.response_body = { ok: true }.to_json
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class SemiProtectedResourcesController < ApplicationController
2
+ # doorkeeper_for :index
3
+
4
+ def index
5
+ render text: 'protected index'
6
+ end
7
+
8
+ def show
9
+ render text: 'protected show'
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module ApplicationHelper
2
+ def current_user
3
+ @current_user ||= User.find_by_id(session[:user_id])
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ # case DOORKEEPER_ORM
2
+ # when :active_record
3
+ # class User < ActiveRecord::Base
4
+ # end
5
+ # when :mongoid2, :mongoid3, :mongoid4
6
+ # class User
7
+ # include Mongoid::Document
8
+ # include Mongoid::Timestamps
9
+ #
10
+ # field :name, type: String
11
+ # field :password, type: String
12
+ # end
13
+ # when :mongo_mapper
14
+ # class User
15
+ # include MongoMapper::Document
16
+ # timestamps!
17
+ #
18
+ # key :name, String
19
+ # key :password, String
20
+ # end
21
+ # end
22
+ #
23
+ # class User
24
+ # if ::Rails.version.to_i < 4
25
+ # attr_accessible :name, :password
26
+ # end
27
+ #
28
+ # def self.authenticate!(name, password)
29
+ # User.where(name: name, password: password).first
30
+ # end
31
+ # end
File without changes
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= csrf_meta_tags %>
6
+ </head>
7
+ <body>
8
+
9
+ <%= link_to "Sign in", '/sign_in' %>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>