authinator 0.0.3 → 0.1.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
  SHA1:
3
- metadata.gz: b3d82624397aabd4fc7fb6b6b851dd6537779d39
4
- data.tar.gz: ff45303cba2e2fc51ccc166bc9ad4fb694d3a7d3
3
+ metadata.gz: 5bab186640c9c1e8c020d88808cea1d05389e743
4
+ data.tar.gz: fd3636d7972b4bda346d1c9b641d633f2e655053
5
5
  SHA512:
6
- metadata.gz: cf8e1d9e08b9eb1b3e3532b3366975f3f070111cc5de18b30cc61ee45e4bbb5c351a540c5ab9b560376519647b4abb1e207588d4c8bef0b57e3ad11141a117bf
7
- data.tar.gz: 4bca86ce9fa8a423bf222e7759f7e56b62a0a5800497e24a261e9795124f3067e62f0a24aa900170408a7856a289ab01a59918c59727e4b76e95335ee53c7fbd
6
+ metadata.gz: 84848419144e543347fac7faa7fe32e13b10da1ea8e282a9c32f0977dfad44e161313c310dd3114b85c65667d5764bf9c569fd843448074c67cf7635c1d55cb5
7
+ data.tar.gz: db8e6561e4032b1b6f7f71648d1f48219ff2b94d260a55fae5f0f237997a7d746904fe5a27e95de0ed9f5846ac60b37444d5763ff3f2d85b1baace23c608826d
data/Gemfile CHANGED
@@ -16,3 +16,6 @@ group :test do
16
16
  gem 'simplecov', '>= 0.9'
17
17
  gem 'webmock'
18
18
  end
19
+
20
+ # gem 'abstract_google_client', path: '/Users/abradner/foogi/google_client', require: 'google_client'
21
+ gem 'abstract_google_client', github: 'abradner/google_client', require: 'google_client'
data/lib/authinator.rb CHANGED
@@ -1,8 +1,10 @@
1
+ require 'active_support/all'
1
2
  require 'authinator/version'
3
+ require 'authinator/provider'
4
+ require 'authinator/configuration'
2
5
  require 'authinator/auth_code_exchanger'
3
6
  require 'authinator/end_point_listener'
4
7
  require 'authinator/client_token_issuer'
5
8
 
6
9
  module Authinator
7
- # Your code goes here...
8
10
  end
@@ -1,10 +1,7 @@
1
- # require 'omniauth/strategies/google_oauth2'
2
- # require 'omniauth-oauth2'
3
1
  require 'oauth2'
4
2
 
5
3
  module Authinator
6
4
  class AuthCodeExchanger
7
- VALID_PROVIDERS = [:stub, :google]
8
5
  STUB_SAMPLE_TOKEN = {
9
6
  token: 'ya29.token',
10
7
  refresh_token: '1/refresh',
@@ -12,46 +9,25 @@ module Authinator
12
9
  }
13
10
 
14
11
  attr_reader :provider
12
+ # attr_reader :client
15
13
 
16
14
  def self.valid_providers
17
- VALID_PROVIDERS
15
+ Authinator.configuration.providers
18
16
  end
19
17
 
20
- PROVIDER_HASHES = {
21
- google: {
22
- client_id: 'cl_id',
23
- client_secret: 'cl_sec',
24
- site: 'https://accounts.google.com',
25
- token_url: '/o/oauth2/token',
26
- },
27
- stub: {
28
- client_id: 'cl_id',
29
- client_secret: 'cl_sec',
30
- site: 'https://example.org',
31
- token_url: '/extoken',
32
- },
33
- }
34
-
35
- def initialize(provider, client_options = {})
36
- unless VALID_PROVIDERS.include? provider
37
- fail ArgumentError,
38
- "Provider #{provider} not in supported parameter list:\n" <<
39
- VALID_PROVIDERS.inspect
40
- end
41
-
18
+ def initialize(provider, _client_options = {})
42
19
  @provider = provider
43
- build_provider_hash(client_options)
44
20
  end
45
21
 
46
22
  def site_token_url
47
- @provider_hash[:site] + @provider_hash[:token_url]
23
+ @provider.site + @provider.token_url
48
24
  end
49
25
 
50
26
  def exchange(auth_code)
51
27
  # auth_code = params[:code]
52
28
  return if auth_code.nil? || auth_code.empty?
53
29
 
54
- case @provider.to_sym
30
+ case @provider.name
55
31
  when :google
56
32
  exchange_with_google(auth_code)
57
33
  when :stub
@@ -61,20 +37,16 @@ module Authinator
61
37
 
62
38
  private
63
39
 
64
- def build_provider_hash(client_options)
65
- @provider_hash = PROVIDER_HASHES[@provider.to_sym]
66
- @provider_hash[:client_id] = client_options.delete(:client_id) if client_options[:client_id]
67
- @provider_hash[:client_secret] = client_options.delete(:client_secret) if client_options[:client_secret]
68
- end
40
+ # def build_provider_hash(client_options)
41
+ # @provider_hash = Authinator.configuration.provider_for[@provider.to_sym]
42
+ # @provider_hash[:client_id] = client_options.delete(:client_id) if client_options[:client_id]
43
+ # @provider_hash[:client_secret] = client_options.delete(:client_secret) if client_options[:client_secret]
44
+ # end
69
45
 
70
46
  def exchange_with_google(code)
71
- provider_hash = @provider_hash.dup
72
-
73
- client_id = provider_hash.delete(:client_id)
74
- client_secret = provider_hash.delete(:client_secret)
75
- @client = OAuth2::Client.new(client_id, client_secret, provider_hash)
47
+ @client = OAuth2::Client.new(@provider.client_id, @provider.client_secret, @provider.to_hash)
76
48
 
77
- token = @client.auth_code.get_token(code)
49
+ token = @client.auth_code.get_token(code, redirect_uri: 'http://localhost:4200')
78
50
 
79
51
  # response = token.get('/api/resource', :params => { 'query_foo' => 'bar' })
80
52
  # response.class.name
@@ -85,8 +57,8 @@ module Authinator
85
57
 
86
58
  def exchange_with_stub(_code)
87
59
  @client = OAuth2::Client.new(
88
- @provider_hash[:client_id],
89
- @provider_hash[:client_secret],
60
+ @provider.client_id,
61
+ @provider.client_secret,
90
62
  )
91
63
 
92
64
  OAuth2::AccessToken.new(
@@ -1,4 +1,226 @@
1
1
  module Authinator
2
+ class EmailNotVerifiedError < ArgumentError
3
+ end
4
+
2
5
  class ClientTokenIssuer
6
+ TEMP_RAW_INFO = {
7
+ email_verified: true,
8
+ email: 'a@b.c',
9
+ given_name: 'first',
10
+ family_name: 'last',
11
+ profile: 'xyz',
12
+ }.with_indifferent_access
13
+
14
+ # Options can
15
+ def initialize(params, options = {})
16
+ @params = params.with_indifferent_access
17
+ provider_name = (options.delete :provider if options[:provider]) || (@params[:provider].present? ? @params[:provider].to_sym : nil)
18
+ unless Authinator.configuration.providers.include? provider_name
19
+ fail ArgumentError,
20
+ "Provider #{provider_name} not in supported parameter list:\n" <<
21
+ Authinator.configuration.providers.inspect
22
+ end
23
+
24
+ @provider = Authinator.configuration.provider_for(provider_name)
25
+
26
+ @auth_code = (options.delete :auth_code if options[:auth_code]) || @params['code']
27
+ @app_name = (options.delete :app_name if options[:app_name]) || application_name
28
+ @valid_applications = (options.delete :valid_applications if options[:valid_applications]) || Authinator.configuration.valid_applications
29
+ end
30
+
31
+ def authorize!(options = {})
32
+ return { error: "Invalid Application #{@app_name}" }, :bad_request unless @valid_applications.include? @app_name
33
+
34
+ handler = EndPointListener.new(auth_code: @auth_code, provider: @provider)
35
+
36
+ if handler.valid?
37
+ return handle(options)
38
+
39
+ else
40
+ # Doorkeeper's defaut behaviour when the user signs in with login/password.
41
+ # TODO: kill this block
42
+ begin
43
+ response = strategy.authorize
44
+ headers.merge! response.headers
45
+ self.response_body = response.body.merge(user_id: (response.token.resource_owner_id && response.token.resource_owner_id.to_s)).to_json
46
+ self.status = response.status
47
+ rescue Doorkeeper::Errors::DoorkeeperError => e
48
+ handle_token_exception e
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ def handle(options = {})
55
+ application = Doorkeeper::Application.where(name: @app_name)
56
+ token_issuer = AuthCodeExchanger.new @provider
57
+ provider_access_token = token_issuer.exchange @auth_code
58
+
59
+ begin
60
+ info = load_info(provider_access_token)
61
+ rescue EmailNotVerifiedError => _e
62
+ return { error: 'Cannot create a Foogi account with an unverified email address' }, :bad_request
63
+ end
64
+
65
+ acc = find_or_create_account_from_info(info)
66
+ user = acc.user
67
+ expires_in = options.delete(:expires_in) || 2.hours
68
+ store_provider_credentials!(acc, provider_access_token)
69
+
70
+ client_access_token = Doorkeeper::AccessToken.create!(
71
+ application_id: application,
72
+ resource_owner_id: user.id,
73
+ expires_in: expires_in,
74
+ use_refresh_token: true,
75
+ )
76
+
77
+ token_data = {
78
+ access_token: client_access_token.token,
79
+ refresh_token: client_access_token.refresh_token,
80
+ token_type: 'bearer',
81
+ expires_in: client_access_token.expires_in,
82
+ user_id: user.id, # TODO: remove
83
+ provider_access_token: provider_access_token.token,
84
+ provider_expires_in: provider_access_token.expires_in,
85
+ # provider_id_token: provider_access_token.id_token,
86
+ }
87
+
88
+ [token_data.to_json, :ok]
89
+ end
90
+
91
+ def load_info(access_token)
92
+ # raw_info = provider_access_token.get('https://www.googleapis.com/plus/v1/people/me/openIdConnect').parsed
93
+
94
+ raw_info = case @provider.name
95
+ when :google
96
+ retrieve_user_from_google access_token
97
+ when :stub
98
+ TEMP_RAW_INFO
99
+ end
100
+ # raw_info = TEMP_RAW_INFO
101
+
102
+ verified_email = raw_info[:email_verified] ? raw_info[:email] : nil
103
+ fail EmailNotVerifiedError, 'Email not verified' unless verified_email.present?
104
+
105
+ # verified_email = raw_info['email']
106
+ # prune!(
107
+ # # email_verified: hash['emails'].first['type'].eql?('account'),
108
+ # email_verified: false,
109
+ # email: raw_info['emails'].first['value'],
110
+ # display_name: raw_info['displayName'],
111
+ # name: raw_info['name'],
112
+ # picture_url: raw_info['image']['url'],
113
+ # uid: raw_info['id'],
114
+ # language: raw_info['language'],
115
+ # )
116
+ # prune!(
117
+ # name: raw_info['name'],
118
+ # email: verified_email,
119
+ # first_name: raw_info['given_name'],
120
+ # last_name: raw_info['family_name'],
121
+ # image: raw_info['image_url'],
122
+ # uid: raw_info['sub'] || verified_email,
123
+ # urls: {
124
+ # @provider.name => raw_info['profile'],
125
+ # },
126
+ # )
127
+ raw_info
128
+ end
129
+
130
+ private
131
+
132
+ def find_or_create_account_from_info(info)
133
+ acc = Account.find_by email: info[:email], provider: @provider.name.to_s
134
+ if acc.blank?
135
+ user = User.find_by(primary_email: info[:email]) || User.create!(
136
+ primary_email: info[:email], display_name: info[:display_name],
137
+ name: info[:name], picture_url: info[:picture_url],
138
+ )
139
+ acc = user.create_account!(
140
+ email: info[:email],
141
+ provider: @provider.name.to_s,
142
+ provider_uid: info[:uid],
143
+ )
144
+ end
145
+ acc
146
+ end
147
+
148
+ def store_provider_credentials!(acc, access_token)
149
+ acc.credential.destroy unless acc.credential.blank?
150
+
151
+ acc.create_credential!(
152
+ access_token: access_token.token,
153
+ refresh_token: access_token.refresh_token,
154
+ expires_at: (Time.now.utc + access_token.expires_in),
155
+ expires: access_token.expires_in.present? ? true : false,
156
+ )
157
+ end
158
+
159
+ def application_name
160
+ @params['application_name'].present? ? @params['application_name'].to_sym : nil
161
+ end
162
+
163
+ def prune!(hash)
164
+ hash.delete_if do |_, v|
165
+ prune!(v) if v.is_a?(Hash)
166
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
167
+ end
168
+ end
169
+
170
+ def retrieve_user_from_google(access_token)
171
+ client = GoogleClient::Builder.new('plus', 'v1', 1)
172
+ result = client.execute access_token, client.service.people.get, userId: 'me'
173
+ process_google_info JSON.parse(result.body)
174
+ end
175
+
176
+ def process_google_info(hash)
177
+ {
178
+ email_verified: hash['emails'].first['type'].eql?('account'),
179
+ email: hash['emails'].first['value'],
180
+ display_name: hash['displayName'],
181
+ name: hash['name'],
182
+ picture_url: hash['image']['url'],
183
+ uid: hash['id'],
184
+ language: hash['language'],
185
+ }.with_indifferent_access
186
+
187
+ # {
188
+ # "kind" => "plus#person",
189
+ # "etag" => "\"xyz-something/abc\"",
190
+ # "gender" => "female",
191
+ # "emails" => [
192
+ # {
193
+ # "value" => "info@foogi.me",
194
+ # "type" => "account"
195
+ # }
196
+ # ],
197
+ # "objectType" => "person",
198
+ # "id" => "12345",
199
+ # "displayName" => "Leading Foogster",
200
+ # "name" => {
201
+ # "familyName" => "Foogster",
202
+ # "givenName" => "Leading"
203
+ # },
204
+ # "url" => "https://plus.google.com/+FoogiMe",
205
+ # "image" => {
206
+ # "url" => "https://someurl/photo.jpg?sz=50",
207
+ # "isDefault" => false
208
+ # },
209
+ # "placesLived" => [
210
+ # {
211
+ # "value" => "Sydney, Australia",
212
+ # "primary" => true
213
+ # },
214
+ # {
215
+ # "value" => "San Francisco, USA"
216
+ # }
217
+ # ],
218
+ # "isPlusUser" => true,
219
+ # "language" => "en_GB",
220
+ # "circledByCount" => 11225,
221
+ # "verified" => false,
222
+ # "domain" => "foogi.me"
223
+ # }
224
+ end
3
225
  end
4
226
  end
@@ -0,0 +1,71 @@
1
+ module Authinator
2
+ # Exception to handle a missing initializer
3
+ # class MissingConfiguration < StandardError
4
+ # def initialize
5
+ # super('Configuration for authinator missing. Do you have an Authinator initializer?')
6
+ # end
7
+ # end
8
+
9
+ # Module level methods
10
+ class << self
11
+ attr_accessor :configuration
12
+ end
13
+
14
+ def self.configure
15
+ self.configuration ||= Configuration.new
16
+ yield(configuration)
17
+ end
18
+
19
+ # def self.configuration
20
+ # @config || (fail MissingConfiguration.new)
21
+ # end
22
+
23
+ # Configuration class
24
+ class Configuration
25
+ attr_reader :providers
26
+ attr_accessor :valid_applications
27
+
28
+ def initialize
29
+ @providers = {}
30
+ add_provider(
31
+ :stub,
32
+ client_id: 'cl_id',
33
+ client_secret: 'cl_sec',
34
+ site: 'https://example.org',
35
+ token_url: '/extoken',
36
+ api_key: 'api_key',
37
+ user_info_url: 'http://example.org/info',
38
+ )
39
+ add_provider(
40
+ :google,
41
+ site: 'https://accounts.google.com',
42
+ token_url: '/o/oauth2/token',
43
+ user_info_url: 'https://www.googleapis.com/plus/v1/people/me/openIdConnect',
44
+ )
45
+ end
46
+
47
+ def providers
48
+ @providers.keys
49
+ end
50
+
51
+ def add_provider(provider_name, options = {})
52
+ @providers[provider_name] = Provider.new(provider_name, options)
53
+ end
54
+
55
+ def add_secrets(provider_name, options = {})
56
+ fail(
57
+ ArgumentError,
58
+ "#{provider_name} is not a configured provider.\n" \
59
+ "Valid Providers:\n" <<
60
+ providers.to_s,
61
+ ) if @providers[provider_name].blank?
62
+
63
+ @providers[provider_name].add_secrets(options)
64
+ end
65
+
66
+ # A more abstracted way of accessing the providers
67
+ def provider_for(provider_name)
68
+ @providers[provider_name]
69
+ end
70
+ end
71
+ end
@@ -1,9 +1,8 @@
1
1
  module Authinator
2
2
  class EndPointListener
3
- attr_reader :email, :provider, :auth_code, :options, :errors
3
+ attr_reader :provider, :auth_code, :options, :errors
4
4
 
5
5
  def initialize(hash = {})
6
- @email = hash.delete :email
7
6
  @provider = hash.delete :provider
8
7
  @auth_code = hash.delete :auth_code
9
8
  @options = hash
@@ -12,36 +11,24 @@ module Authinator
12
11
 
13
12
  def valid?
14
13
  validator_presence? &&
15
- validator_valid_email? &&
16
14
  validator_valid_provider?
17
15
  end
18
16
 
19
17
  private
20
18
 
21
19
  def validator_presence?
22
- email_present = present? @email
23
20
  provider_present = present? @provider
24
21
  auth_code_present = present? @auth_code
25
22
 
26
- return true if email_present && provider_present && auth_code_present
23
+ return true if provider_present && auth_code_present
27
24
  errors << 'A required param is missing'
28
- errors << '"email" field missing' unless email_present
29
25
  errors << '"provider" field missing' unless provider_present
30
26
  errors << '"auth_code" field missing' unless auth_code_present
31
27
  false
32
28
  end
33
29
 
34
- # Regexp lovingly borrowed from https://github.com/balexand/email_validator
35
- def validator_valid_email?
36
- name_validation = @options[:strict_mode] ? '-a-z0-9+._' : '^@\\s'
37
- regexp = /\A\s*([#{name_validation}]{1,64})@((?:[-a-z0-9]+\.)+[a-z]{2,})\s*\z/i
38
- return true if @email =~ regexp
39
- errors << "Email '#{@email}' is invalid"
40
- false
41
- end
42
-
43
30
  def validator_valid_provider?
44
- return true if Authinator::AuthCodeExchanger.valid_providers.include? @provider.to_sym
31
+ return true if Authinator.configuration.providers.include? @provider.name
45
32
  errors << "Provider '#{@provider}' is invalid"
46
33
  false
47
34
  end
@@ -0,0 +1,54 @@
1
+ module Authinator
2
+ class Provider
3
+ attr_reader :name
4
+ attr_accessor :client_id,
5
+ :client_secret,
6
+ :site,
7
+ :token_url,
8
+ :api_key,
9
+ :user_info_url
10
+
11
+ def initialize(name, options = {})
12
+ @name = name
13
+ @client_id = options.delete :client_id
14
+ @client_secret = options.delete :client_secret
15
+ @site = options.delete :site
16
+ @token_url = options.delete :token_url
17
+ @api_key = options.delete :api_key
18
+ @user_info_url = options.delete :user_info_url
19
+ end
20
+
21
+ def add_secrets(options = {})
22
+ @client_id = options.delete :client_id if options[:client_id]
23
+ @client_secret = options.delete :client_secret if options[:client_secret]
24
+ @api_key = options.delete :api_key if options[:api_key]
25
+ end
26
+
27
+ def secrets
28
+ sec = {}
29
+ sec[:client_id] = @client_id if @client_id
30
+ sec[:client_secret] = @client_secret if @client_secret
31
+ sec[:api_key] = @api_key if @api_key
32
+
33
+ sec
34
+ end
35
+
36
+ def to_hash
37
+ {
38
+ name: @name,
39
+ client_id: @client_id,
40
+ client_secret: @client_secret,
41
+ site: @site,
42
+ token_url: @token_url,
43
+ api_key: @api_key,
44
+ user_info_url: @user_info_url,
45
+ }
46
+ end
47
+
48
+ def empty?
49
+ to_hash.empty?
50
+ end
51
+
52
+ alias_method :inspect, :to_hash
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Authinator
2
- VERSION = '0.0.3'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -3,6 +3,11 @@ require 'json'
3
3
 
4
4
  describe Authinator::AuthCodeExchanger do
5
5
  before :all do
6
+ Authinator.configure do |config|
7
+ config.add_secrets :google,
8
+ client_id: 'cl_id',
9
+ client_secret: 'cl_sec'
10
+ end
6
11
  @token_hash = {
7
12
  access_token: 'ya29.token',
8
13
  refresh_token: '1/refresh',
@@ -27,9 +32,29 @@ describe Authinator::AuthCodeExchanger do
27
32
  body: @token_hash.to_json,
28
33
  headers: { content_type: 'application/json' },
29
34
  }
35
+
36
+ @stub_provider = Authinator::Provider.new(
37
+ :stub,
38
+ client_id: 'cl_id',
39
+ client_secret: 'cl_sec',
40
+ site: 'https://example.org',
41
+ token_url: '/extoken',
42
+ api_key: 'api_key',
43
+ user_info_url: 'http://example.org/info',
44
+ )
45
+ @google_provider = Authinator::Provider.new(
46
+ :stub,
47
+ client_id: 'cl_id',
48
+ client_secret: 'cl_sec',
49
+ site: 'https://example.org',
50
+ token_url: '/extoken',
51
+ api_key: 'api_key',
52
+ user_info_url: 'http://example.org/info',
53
+ )
30
54
  end
55
+
31
56
  it 'should correctly process a generic (stub) token' do
32
- ace = Authinator::AuthCodeExchanger.new(:stub)
57
+ ace = Authinator::AuthCodeExchanger.new(@stub_provider)
33
58
  stub_request(:post, ace.site_token_url).
34
59
  with(body: @test_env,
35
60
  headers: @req_headers).
@@ -45,7 +70,8 @@ describe Authinator::AuthCodeExchanger do
45
70
  it 'should return an AccessToken for each provider' do
46
71
  klass = OAuth2::AccessToken
47
72
 
48
- Authinator::AuthCodeExchanger.valid_providers.each do |provider|
73
+ Authinator::AuthCodeExchanger.valid_providers.each do |provider_name|
74
+ provider = Authinator.configuration.provider_for provider_name
49
75
  ace = Authinator::AuthCodeExchanger.new(provider)
50
76
  stub_request(:post, ace.site_token_url).
51
77
  with(body: @test_env,
@@ -57,7 +83,7 @@ describe Authinator::AuthCodeExchanger do
57
83
  end
58
84
 
59
85
  it 'should correctly process a google token' do
60
- ace = Authinator::AuthCodeExchanger.new(:google)
86
+ ace = Authinator::AuthCodeExchanger.new(@google_provider)
61
87
  stub_request(:post, ace.site_token_url).
62
88
  with(body: @test_env,
63
89
  headers: @req_headers).
@@ -69,19 +95,4 @@ describe Authinator::AuthCodeExchanger do
69
95
  expect(result.refresh_token).to eq @token_hash[:refresh_token]
70
96
  expect(result.expires_in).to eq @token_hash[:expires_in]
71
97
  end
72
-
73
- it 'should gracefully not allow unsupported providers' do
74
- expect do
75
- Authinator::AuthCodeExchanger.new(:some_fake_provider)
76
- end.to raise_error(ArgumentError)
77
- end
78
-
79
- it 'should correctly handle client information provided as a parameter' do
80
- ace = Authinator::AuthCodeExchanger.new(:google, client_id: 'new_id', client_secret: 'new_secret')
81
-
82
- stub_request(:post, ace.site_token_url).
83
- with(body: @test_env.merge(client_id: 'new_id', client_secret: 'new_secret'),
84
- headers: @req_headers).
85
- to_return(@req_response)
86
- end
87
98
  end
@@ -5,4 +5,21 @@ describe Authinator::ClientTokenIssuer do
5
5
  it 'should generate our own set of tokens for the client if the provided ones exchanged successfully'
6
6
 
7
7
  it 'should all integrate to follow a standard flow to auth the api client'
8
+
9
+ it 'should gracefully not allow unsupported providers' do
10
+ pending
11
+ expect do
12
+ Authinator::AuthCodeExchanger.new(:some_fake_provider)
13
+ end.to raise_error(ArgumentError)
14
+ end
15
+
16
+ it 'should correctly handle client information provided as a parameter' do
17
+ pending
18
+ ace = Authinator::AuthCodeExchanger.new(:google, client_id: 'new_id', client_secret: 'new_secret')
19
+
20
+ stub_request(:post, ace.site_token_url).
21
+ with(body: @test_env.merge(client_id: 'new_id', client_secret: 'new_secret'),
22
+ headers: @req_headers).
23
+ to_return(@req_response)
24
+ end
8
25
  end
@@ -2,10 +2,18 @@ require 'spec_helper'
2
2
 
3
3
  describe Authinator::EndPointListener do
4
4
  before :each do
5
+ @stub_provider = Authinator::Provider.new(
6
+ :stub,
7
+ client_id: 'cl_id',
8
+ client_secret: 'cl_sec',
9
+ site: 'https://example.org',
10
+ token_url: '/extoken',
11
+ api_key: 'api_key',
12
+ user_info_url: 'http://example.org/info',
13
+ )
5
14
  @creds_hash = {
6
- email: 'test@foogi.me',
7
15
  auth_code: '4/auth_code',
8
- provider: 'google',
16
+ provider: @stub_provider,
9
17
  }
10
18
  end
11
19
  it 'should accept valid-looking credentials from the client' do
@@ -25,31 +33,30 @@ describe Authinator::EndPointListener do
25
33
  expect(listener.valid?).to be_falsey
26
34
  end
27
35
  it 'should return an error unless all three fields are provided' do
28
- listener1 = Authinator::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:email) }) # remove email
29
36
  listener2 = Authinator::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:auth_code) }) # remove ac
30
37
  listener3 = Authinator::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:provider) }) # remove prov
31
38
 
32
- expect(listener1.valid?).to be_falsey
33
39
  expect(listener2.valid?).to be_falsey
34
40
  expect(listener3.valid?).to be_falsey
35
41
  end
36
- it 'should reject invalid emails' do
37
- bad_email_hash1 = @creds_hash.merge(email: 'abc')
38
- bad_email_hash2 = @creds_hash.merge(email: '')
39
- bad_email_hash3 = @creds_hash.merge(email: 'a@')
40
42
 
41
- listener1 = Authinator::EndPointListener.new(bad_email_hash1)
42
- listener2 = Authinator::EndPointListener.new(bad_email_hash2)
43
- listener3 = Authinator::EndPointListener.new(bad_email_hash3)
43
+ it 'should reject invalid providers' do
44
+ bad_provider_1 = Authinator::Provider.new(
45
+ :bad1,
46
+ client_id: 'cl_id',
47
+ client_secret: 'cl_sec',
48
+ site: 'https://example.org',
49
+ token_url: '/extoken',
50
+ api_key: 'api_key',
51
+ user_info_url: 'http://example.org/info',
52
+ )
44
53
 
45
- expect(listener1.valid?).to be_falsey
46
- expect(listener2.valid?).to be_falsey
47
- expect(listener3.valid?).to be_falsey
48
- end
54
+ bad_provider_2 = Authinator::Provider.new(
55
+ :bad2,
56
+ )
49
57
 
50
- it 'should reject invalid providers' do
51
- bad_provider_hash1 = @creds_hash.merge(provider: 'some_fake_provider')
52
- bad_provider_hash2 = @creds_hash.merge(provider: '')
58
+ bad_provider_hash1 = @creds_hash.merge(provider: bad_provider_1)
59
+ bad_provider_hash2 = @creds_hash.merge(provider: bad_provider_2)
53
60
 
54
61
  listener1 = Authinator::EndPointListener.new(bad_provider_hash1)
55
62
  listener2 = Authinator::EndPointListener.new(bad_provider_hash2)
@@ -63,7 +70,6 @@ describe Authinator::EndPointListener do
63
70
  listener.valid?
64
71
  expect(listener.errors).to eq [
65
72
  'A required param is missing',
66
- '"email" field missing',
67
73
  '"provider" field missing',
68
74
  '"auth_code" field missing',
69
75
  ]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authinator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Bradner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-23 00:00:00.000000000 Z
11
+ date: 2015-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -115,7 +115,9 @@ files:
115
115
  - lib/authinator.rb
116
116
  - lib/authinator/auth_code_exchanger.rb
117
117
  - lib/authinator/client_token_issuer.rb
118
+ - lib/authinator/configuration.rb
118
119
  - lib/authinator/end_point_listener.rb
120
+ - lib/authinator/provider.rb
119
121
  - lib/authinator/version.rb
120
122
  - spec/authinator/auth_code_exchanger_spec.rb
121
123
  - spec/authinator/client_token_issuer_spec.rb