oidc_provider 0.3.10 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da21094ceda40451619c72e143399acf170b98f031eae7e0db2ec7e0e7dd97a6
4
- data.tar.gz: 41be8a950f2a1c96afae1c8db4e2ea8f3ac1629419ef206c4123580426f5a125
3
+ metadata.gz: 29ccfbd4c57f22b63424ddbd7998bde94566c24e06721b43bfa5b07df0852ef6
4
+ data.tar.gz: fdeaa21ebbc146987ed9547988d4f7d59449a8dae6609477e72f1f78b47e7f91
5
5
  SHA512:
6
- metadata.gz: 76a5ece3b674d0ab2e72af183c3333dcbe3fbb347f0503ce1aafc09b0cfbd1ba7e66ebe3f0ad2393953a5686875cc2f5f22e5dc557e6bc37de204c2b7ec2cd41
7
- data.tar.gz: eb859617ee41d779fc5e34ac2af239ab2d87b48634c5639080496930aff58cab487292660c520a3f336d451f40ea87f1fb32ec0cfb5beb4c14d9ffb636331ad2
6
+ metadata.gz: 82cd93fa057ecf8522d3ae4754360e202da2e102a9ee4b8ac8d52cbfa2df6da8a86532de765cf52ddea63080b182f9605c37c87db8097066ac019b6091e70812
7
+ data.tar.gz: 5a8cd740d69fb544665b7262ccb8124d4ce51791ca052495b12369b01a5d8b40d4eabf6d0efc2a0b469086a8123d52ad898821083838d6d80e862be475262409
data/README.md CHANGED
@@ -41,14 +41,19 @@ $ rails db:migrate
41
41
 
42
42
  ### Private Key
43
43
 
44
- You will need to generate a unique private key per application.
44
+ This gem signs the generated [JWT (JSON Web Tokens)](https://jwt.io/) using a
45
+ private key that should exist at the path `lib/oidc_provider_key.pem` in your
46
+ Rails application.
47
+
48
+ You can pass its passphrase using the `OIDC_PROVIDER_KEY_PASSPHRASE` environment
49
+ variable.
50
+
51
+ This gem provide a convenient way of generating one if you need it by running :
45
52
 
46
53
  ```bash
47
- $ ssh-keygen
54
+ $ rails oidc_provider:generate_key
48
55
  ```
49
56
 
50
- Due to Docker Composes' lack of support for multiline `.env` variables, put a passphrase on it. Then add the key to your application at `lib/oidc_provider_key.pem` and add the passphrase as an environment variables in your application: `ENV["OIDC_PROVIDER_KEY_PASSPHRASE"]`.
51
-
52
57
  # Testing
53
58
 
54
59
  Visit: https://demo.c2id.com/oidc-client/
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OIDCProvider
2
4
  class AuthorizationsController < ApplicationController
3
5
  include Concerns::ConnectEndpoint
@@ -5,16 +7,13 @@ module OIDCProvider
5
7
  before_action :require_oauth_request
6
8
  before_action :require_response_type_code
7
9
  before_action :require_client
10
+ before_action :reset_login_if_necessary
8
11
  before_action :require_authentication
9
12
 
10
13
  def create
11
- puts "scopes: #{requested_scopes}"
12
- authorization = Authorization.create(
13
- client_id: @client.identifier,
14
- nonce: oauth_request.nonce,
15
- scopes: requested_scopes,
16
- account: oidc_current_account
17
- )
14
+ Rails.logger.info "scopes: #{requested_scopes}"
15
+
16
+ authorization = build_authorization_with(requested_scopes)
18
17
 
19
18
  oauth_response.code = authorization.code
20
19
  oauth_response.redirect_uri = @redirect_uri
@@ -27,21 +26,39 @@ module OIDCProvider
27
26
 
28
27
  private
29
28
 
29
+ def build_authorization_with(scopes)
30
+ Authorization.create(
31
+ client_id: @client.identifier,
32
+ nonce: oauth_request.nonce,
33
+ scopes: scopes,
34
+ account: oidc_current_account
35
+ )
36
+ end
37
+
30
38
  def require_client
31
39
  @client = ClientStore.new.find_by(identifier: oauth_request.client_id) or oauth_request.invalid_request! 'not a valid client'
32
- @redirect_uri = oauth_request.verify_redirect_uri! [oauth_request.redirect_uri, @client.redirect_uri]
40
+ @redirect_uri = oauth_request.verify_redirect_uri! @client.redirect_uri
33
41
  end
34
42
 
35
43
  def requested_scopes
36
- @requested_scopes ||= (["openid"] + OIDCProvider.supported_scopes.map(&:name)) & oauth_request.scope
44
+ @requested_scopes ||= (['openid'] + OIDCProvider.supported_scopes.map(&:name)) & oauth_request.scope
37
45
  end
38
46
  helper_method :requested_scopes
39
47
 
40
48
  def require_response_type_code
41
- unless oauth_request.response_type == :code
42
- oauth_request.unsupported_response_type!
49
+ return if oauth_request.response_type == :code
50
+
51
+ oauth_request.unsupported_response_type!
52
+ end
53
+
54
+ def reset_login_if_necessary
55
+ if params[:prompt] == "login"
56
+ # A `prompt=login` param means that we must prompt the user for sign in.
57
+ # So we will forcibly sign out the user here and then redirect them so they
58
+ # don't get redirected back to the url that contains `prompt=login`
59
+ unauthenticate!
60
+ redirect_to url_for(request.query_parameters.except(:prompt))
43
61
  end
44
62
  end
45
63
  end
46
-
47
- end
64
+ end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OIDCProvider
2
4
  class IdToken < ApplicationRecord
5
+ PASSPHRASE_ENV_VAR = 'OIDC_PROVIDER_KEY_PASSPHRASE'
6
+
3
7
  belongs_to :authorization
4
8
 
5
9
  attribute :expires_at, :datetime, default: -> { 1.hour.from_now }
@@ -24,8 +28,19 @@ module OIDCProvider
24
28
  private
25
29
 
26
30
  class << self
31
+ def config
32
+ {
33
+ issuer: OIDCProvider.issuer,
34
+ jwk_set: JSON::JWK::Set.new(public_jwk)
35
+ }
36
+ end
37
+
38
+ def oidc_provider_key_path
39
+ Rails.root.join("lib/oidc_provider_key.pem")
40
+ end
41
+
27
42
  def key_pair
28
- @key_pair ||= OpenSSL::PKey::RSA.new(File.read(Rails.root.join("lib/oidc_provider_key.pem")), ENV["OIDC_PROVIDER_KEY_PASSPHRASE"])
43
+ @key_pair ||= OpenSSL::PKey::RSA.new(File.read(oidc_provider_key_path), ENV[PASSPHRASE_ENV_VAR])
29
44
  end
30
45
 
31
46
  def private_jwk
@@ -35,13 +50,6 @@ module OIDCProvider
35
50
  def public_jwk
36
51
  JSON::JWK.new key_pair.public_key
37
52
  end
38
-
39
- def config
40
- {
41
- issuer: OIDCProvider.issuer,
42
- jwk_set: JSON::JWK::Set.new(public_jwk)
43
- }
44
- end
45
53
  end
46
54
  end
47
55
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OIDCProvider
2
4
  class Client
3
5
  attr_accessor :identifier, :secret, :redirect_uri, :name
@@ -5,10 +7,10 @@ module OIDCProvider
5
7
  def initialize(options = {})
6
8
  @identifier = options[:identifier]
7
9
  @secret = options[:secret]
8
- @redirect_uri = options[:redirect_uri]
10
+ @redirect_uri = Array(options[:redirect_uri])
9
11
  @name = options[:name]
10
12
  end
11
13
  end
12
14
  end
13
15
 
14
- require 'oidc_provider/client/builder'
16
+ require 'oidc_provider/client/builder'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/oauth2'
2
4
 
3
5
  module OIDCProvider
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OIDCProvider
2
4
  class TokenEndpoint
3
5
  attr_accessor :app
6
+
4
7
  delegate :call, to: :app
5
8
 
6
9
  def initialize
@@ -8,26 +11,36 @@ module OIDCProvider
8
11
  Rails.logger.info "Client ID: #{req.client_id}"
9
12
  Rails.logger.info "Client secret: #{req.client_secret}"
10
13
  Rails.logger.info "Redirect URI: #{req.redirect_uri}"
11
- client = ClientStore.new.find_by(
12
- identifier: req.client_id,
13
- secret: req.client_secret,
14
- redirect_uri: req.redirect_uri
15
- ) || req.invalid_client!
16
-
17
- Rails.logger.info "Found a client!"
14
+
15
+ client = find_valid_client_from(req) || req.invalid_client!
16
+
17
+ Rails.logger.info 'Found a client!'
18
18
 
19
19
  case req.grant_type
20
20
  when :authorization_code
21
- Rails.logger.info "Grant type was an authorization code. Correct!"
21
+ Rails.logger.info 'Grant type was an authorization code. Correct!'
22
22
  authorization = Authorization.valid.where(client_id: client.identifier, code: req.code).first || req.invalid_grant!
23
- Rails.logger.info "We found an authorization matching this code!"
23
+ Rails.logger.info 'We found an authorization matching this code!'
24
24
  res.access_token = authorization.access_token.to_bearer_token
25
- res.id_token = authorization.id_token.to_jwt if authorization.scopes.include?("openid")
25
+ res.id_token = authorization.id_token.to_jwt if authorization.scopes.include?('openid')
26
26
  else
27
- Rails.logger.info "Unsupported grant type"
27
+ Rails.logger.info "Unsupported grant type: #{req.grant_type.inspect}"
28
28
  req.unsupported_grant_type!
29
29
  end
30
30
  end
31
31
  end
32
+
33
+ private
34
+
35
+ def find_valid_client_from(req)
36
+ client = ClientStore.new.find_by(
37
+ identifier: req.client_id,
38
+ secret: req.client_secret
39
+ )
40
+
41
+ return nil unless client
42
+
43
+ client.redirect_uri.include?(req.redirect_uri) ? client : nil
44
+ end
32
45
  end
33
- end
46
+ end
@@ -1,3 +1,3 @@
1
1
  module OIDCProvider
2
- VERSION = '0.3.10'
2
+ VERSION = '0.4.0'
3
3
  end
data/lib/oidc_provider.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "openid_connect"
2
4
  require "oidc_provider/engine"
3
5
 
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :oidc_provider do
4
+ desc 'Generate the lib/oidc_provider_key.pem key file'
5
+ task generate_key: :environment do
6
+ key_filepath = OIDCProvider::IdToken.oidc_provider_key_path
7
+
8
+ File.exist?(key_filepath) && raise("ERROR: A key file already exists at #{key_filepath}.")
9
+
10
+ passphrase_env_var = OIDCProvider::IdToken::PASSPHRASE_ENV_VAR
11
+
12
+ pass_phrase = ENV.fetch(passphrase_env_var, '')
13
+
14
+ if pass_phrase == ''
15
+ puts "\033[33mWARNING: You haven't defined a passphrase to be used to " \
16
+ 'generate the new key which is concidered as insecured. You can ' \
17
+ "do it by setting the #{passphrase_env_var} environment variable " \
18
+ "and re-run this task.\033[0m"
19
+
20
+ raise
21
+ end
22
+
23
+ key_file_content = OpenSSL::PKey::RSA.new(2048).export(
24
+ OpenSSL::Cipher.new('AES-128-CBC'),
25
+ pass_phrase
26
+ )
27
+
28
+ File.write(key_filepath, key_file_content)
29
+ FileUtils.chmod(0_600, key_filepath)
30
+
31
+ puts "SUCCESS: A new key file has been created at #{key_filepath}."
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oidc_provider
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.10
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Carey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-03 00:00:00.000000000 Z
11
+ date: 2023-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -73,7 +73,7 @@ files:
73
73
  - lib/oidc_provider/token_endpoint.rb
74
74
  - lib/oidc_provider/user_info_builder.rb
75
75
  - lib/oidc_provider/version.rb
76
- - lib/tasks/openid/connect/provider_tasks.rake
76
+ - lib/tasks/oidc_provider.rake
77
77
  homepage: https://github.com/brandnewbox/oidc_provider
78
78
  licenses:
79
79
  - MIT
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :openid_connect_provider do
3
- # # Task goes here
4
- # end