doorkeeper-openid_connect 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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>