authinator 0.0.1 → 0.0.2

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: d74ae2cc632fa497d66db160895f23b467ecf229
4
- data.tar.gz: b94bb79f1f6a8a2bf4590f3bda38c67cee7cdf1c
3
+ metadata.gz: b3b66719b8c7bb8dd6f60aa7e7ed026b661672f3
4
+ data.tar.gz: f9d3351fe755049be4cf3ed7b2c1cf3ab8dd6876
5
5
  SHA512:
6
- metadata.gz: cb6b27be793d25bee657b48791648ffe740a0efa52f0e07d7a704ffb4b51e0b6c4c775f36888c1cd130acb364eb14f2ebcc5ceb673e8d34f8fb85eedd4d452bb
7
- data.tar.gz: a536e204bae88a4a8daf8492d83fd1fa22b1013d8812e0716e29e4a4a47603d019bbe5db6c0d6127cd9e44c0255fccaa7c958f74f6c4d4f3bcbd5f52a9aedc98
6
+ metadata.gz: 8d3cdbe4ffd69f2fcfab7931eefc43ebbadc7214f02207bf42ad822d5330a62dbe2f6a46fc3a1c16239da4c6a33e180d7f021378252112c87b1bb40a2508cef3
7
+ data.tar.gz: cc7c802bae55aaf6e44a4c3ef220bdbfa4ab8ae6014a2236e841d27c4235dd53e98938f49f729560121988bd4edbf19cf0f1cb7450006d841297bde4b899e99c
data/.gitignore CHANGED
@@ -11,4 +11,5 @@
11
11
  *.so
12
12
  *.o
13
13
  *.a
14
+ *.gem
14
15
  mkmf.log
data/.rubocop.yml CHANGED
@@ -47,3 +47,7 @@ Style/Lambda:
47
47
 
48
48
  Style/TrailingComma:
49
49
  EnforcedStyleForMultiline: 'comma'
50
+
51
+ # Avoid complex methods.
52
+ Metrics/CyclomaticComplexity:
53
+ Max: 7
data/.travis.yml CHANGED
@@ -4,12 +4,12 @@ env:
4
4
  - JRUBY_OPTS="$JRUBY_OPTS --debug"
5
5
  language: ruby
6
6
  rvm:
7
+ - rbx-2
8
+ - jruby-19mode
7
9
  - 1.9.3
8
10
  - 2.0.0
9
11
  - 2.1
10
- - jruby-19mode
11
12
  - jruby-head
12
- - rbx-2
13
13
  - ruby-head
14
14
  matrix:
15
15
  allow_failures:
data/lib/authinator.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'authinator/version'
2
2
  require 'authinator/auth_code_exchanger'
3
+ require 'authinator/end_point_listener'
4
+ require 'authinator/client_token_issuer'
3
5
 
4
6
  module Authinator
5
7
  # Your code goes here...
@@ -2,99 +2,99 @@
2
2
  # require 'omniauth-oauth2'
3
3
  require 'oauth2'
4
4
 
5
- # module Authinator
6
- class AuthCodeExchanger
7
- VALID_PROVIDERS = [:stub, :google]
8
- STUB_SAMPLE_TOKEN = {
9
- token: 'ya29.token',
10
- refresh_token: '1/refresh',
11
- expires_in: 3600,
12
- }
13
-
14
- attr_reader :provider
15
-
16
- def self.valid_providers
17
- VALID_PROVIDERS
18
- end
19
-
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
5
+ module Authinator
6
+ class AuthCodeExchanger
7
+ VALID_PROVIDERS = [:stub, :google]
8
+ STUB_SAMPLE_TOKEN = {
9
+ token: 'ya29.token',
10
+ refresh_token: '1/refresh',
11
+ expires_in: 3600,
12
+ }
13
+
14
+ attr_reader :provider
15
+
16
+ def self.valid_providers
17
+ VALID_PROVIDERS
40
18
  end
41
19
 
42
- @provider = provider
43
- build_provider_hash(client_options)
44
- end
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
+
42
+ @provider = provider
43
+ build_provider_hash(client_options)
44
+ end
45
45
 
46
- def site_token_url
47
- @provider_hash[:site] + @provider_hash[:token_url]
48
- end
46
+ def site_token_url
47
+ @provider_hash[:site] + @provider_hash[:token_url]
48
+ end
49
49
 
50
- def exchange(auth_code)
51
- # auth_code = params[:code]
52
- return if auth_code.nil? || auth_code.empty?
50
+ def exchange(auth_code)
51
+ # auth_code = params[:code]
52
+ return if auth_code.nil? || auth_code.empty?
53
53
 
54
- case @provider.to_sym
55
- when :google
56
- exchange_with_google(auth_code)
57
- when :stub
58
- exchange_with_stub(auth_code)
54
+ case @provider.to_sym
55
+ when :google
56
+ exchange_with_google(auth_code)
57
+ when :stub
58
+ exchange_with_stub(auth_code)
59
+ end
59
60
  end
60
- end
61
61
 
62
- private
62
+ private
63
63
 
64
- def build_provider_hash(client_options)
65
- @provider_hash = PROVIDER_HASHES[provider]
66
- @provider_hash = client_options.delete(:client_id) if client_options[:client_id]
67
- @provider_hash = client_options.delete(:client_secret) if client_options[:client_secret]
68
- end
64
+ def build_provider_hash(client_options)
65
+ @provider_hash = PROVIDER_HASHES[provider]
66
+ @provider_hash = client_options.delete(:client_id) if client_options[:client_id]
67
+ @provider_hash = client_options.delete(:client_secret) if client_options[:client_secret]
68
+ end
69
69
 
70
- def exchange_with_google(code)
71
- provider_hash = @provider_hash.dup
70
+ def exchange_with_google(code)
71
+ provider_hash = @provider_hash.dup
72
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)
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)
76
76
 
77
- token = @client.auth_code.get_token(code)
77
+ token = @client.auth_code.get_token(code)
78
78
 
79
- # response = token.get('/api/resource', :params => { 'query_foo' => 'bar' })
80
- # response.class.name
81
- # => OAuth2::Response
79
+ # response = token.get('/api/resource', :params => { 'query_foo' => 'bar' })
80
+ # response.class.name
81
+ # => OAuth2::Response
82
82
 
83
- token
84
- end
83
+ token
84
+ end
85
85
 
86
- def exchange_with_stub(_code)
87
- @client = OAuth2::Client.new(
88
- @provider_hash[:client_id],
89
- @provider_hash[:client_secret],
90
- )
91
-
92
- OAuth2::AccessToken.new(
93
- @client,
94
- STUB_SAMPLE_TOKEN[:token],
95
- refresh_token: STUB_SAMPLE_TOKEN[:refresh_token],
96
- expires_in: STUB_SAMPLE_TOKEN[:expires_in],
97
- )
86
+ def exchange_with_stub(_code)
87
+ @client = OAuth2::Client.new(
88
+ @provider_hash[:client_id],
89
+ @provider_hash[:client_secret],
90
+ )
91
+
92
+ OAuth2::AccessToken.new(
93
+ @client,
94
+ STUB_SAMPLE_TOKEN[:token],
95
+ refresh_token: STUB_SAMPLE_TOKEN[:refresh_token],
96
+ expires_in: STUB_SAMPLE_TOKEN[:expires_in],
97
+ )
98
+ end
98
99
  end
99
100
  end
100
- # end
@@ -0,0 +1,4 @@
1
+ module Authinator
2
+ class ClientTokenIssuer
3
+ end
4
+ end
@@ -0,0 +1,58 @@
1
+ module Authinator
2
+ class EndPointListener
3
+ attr_reader :email, :provider, :auth_code, :options, :errors
4
+
5
+ def initialize(hash = {})
6
+ @email = hash.delete :email
7
+ @provider = hash.delete :provider
8
+ @auth_code = hash.delete :auth_code
9
+ @options = hash
10
+ @errors = []
11
+ end
12
+
13
+ def valid?
14
+ validator_presence? &&
15
+ validator_valid_email? &&
16
+ validator_valid_provider?
17
+ end
18
+
19
+ private
20
+
21
+ def validator_presence?
22
+ email_present = present? @email
23
+ provider_present = present? @provider
24
+ auth_code_present = present? @auth_code
25
+
26
+ return true if email_present && provider_present && auth_code_present
27
+ errors << 'A required param is missing'
28
+ errors << '"email" field missing' unless email_present
29
+ errors << '"provider" field missing' unless provider_present
30
+ errors << '"auth_code" field missing' unless auth_code_present
31
+ false
32
+ end
33
+
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
+ def validator_valid_provider?
44
+ return true if Authinator::AuthCodeExchanger.valid_providers.include? @provider.to_sym
45
+ errors << "Provider '#{@provider}' is invalid"
46
+ false
47
+ end
48
+
49
+ # recreate rails method
50
+ def present?(el)
51
+ !blank?(el)
52
+ end
53
+
54
+ def blank?(el)
55
+ el.nil? || el.empty?
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Authinator
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'json'
3
3
 
4
- describe AuthCodeExchanger do
4
+ describe Authinator::AuthCodeExchanger do
5
5
  before :all do
6
6
  @token_hash = {
7
7
  access_token: 'ya29.token',
@@ -29,7 +29,7 @@ describe AuthCodeExchanger do
29
29
  }
30
30
  end
31
31
  it 'should correctly process a generic (stub) token' do
32
- ace = AuthCodeExchanger.new(:stub)
32
+ ace = Authinator::AuthCodeExchanger.new(:stub)
33
33
  stub_request(:post, ace.site_token_url).
34
34
  with(body: @test_env,
35
35
  headers: @req_headers).
@@ -45,8 +45,8 @@ describe AuthCodeExchanger do
45
45
  it 'should return an AccessToken for each provider' do
46
46
  klass = OAuth2::AccessToken
47
47
 
48
- AuthCodeExchanger.valid_providers.each do |provider|
49
- ace = AuthCodeExchanger.new(provider)
48
+ Authinator::AuthCodeExchanger.valid_providers.each do |provider|
49
+ ace = Authinator::AuthCodeExchanger.new(provider)
50
50
  stub_request(:post, ace.site_token_url).
51
51
  with(body: @test_env,
52
52
  headers: @req_headers).
@@ -57,7 +57,7 @@ describe AuthCodeExchanger do
57
57
  end
58
58
 
59
59
  it 'should correctly process a google token' do
60
- ace = AuthCodeExchanger.new(:google)
60
+ ace = Authinator::AuthCodeExchanger.new(:google)
61
61
  stub_request(:post, ace.site_token_url).
62
62
  with(body: @test_env,
63
63
  headers: @req_headers).
@@ -72,18 +72,7 @@ describe AuthCodeExchanger do
72
72
 
73
73
  it 'should gracefully not allow unsupported providers' do
74
74
  expect do
75
- AuthCodeExchanger.new(:some_fake_provider)
75
+ Authinator::AuthCodeExchanger.new(:some_fake_provider)
76
76
  end.to raise_error(ArgumentError)
77
77
  end
78
78
  end
79
-
80
- describe 'ClientTokenIssuer' do
81
- pending
82
- it 'should accept valid-looking credentials from the client'
83
- it 'should exchange client-provided credentials for auth codes'
84
- it 'should return an error to the client if the credentials were invalid'
85
- it 'should verify that the tokens belong to the provided email before returning them'
86
- it 'should generate our own set of tokens for the client if the provided ones exchanged successfully'
87
-
88
- it 'should all integrate to follow a standard flow to auth the api client'
89
- end
@@ -0,0 +1,8 @@
1
+ describe Authinator::ClientTokenIssuer do
2
+ it 'should exchange client-provided credentials for auth codes'
3
+ it 'should gracefully handle and return error condition if client-provided credentials are invalid'
4
+ it 'should verify that the tokens belong to the provided email before returning them'
5
+ it 'should generate our own set of tokens for the client if the provided ones exchanged successfully'
6
+
7
+ it 'should all integrate to follow a standard flow to auth the api client'
8
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Authinator::EndPointListener do
4
+ before :each do
5
+ @creds_hash = {
6
+ email: 'test@foogi.me',
7
+ auth_code: '4/auth_code',
8
+ provider: 'google',
9
+ }
10
+ end
11
+ it 'should accept valid-looking credentials from the client' do
12
+ listener = Authinator::EndPointListener.new(@creds_hash)
13
+ expect(listener.valid?).to be_truthy
14
+ end
15
+
16
+ # These tests extend on the test above.
17
+ # Given the test above handles the happy path, everything below are sad path tests
18
+
19
+ it 'should return an error to the client if the credentials were invalid' do
20
+ bad_creds_hash = {
21
+ a: 'b',
22
+ c: 'd',
23
+ }
24
+ listener = Authinator::EndPointListener.new(bad_creds_hash)
25
+ expect(listener.valid?).to be_falsey
26
+ end
27
+ 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
+ listener2 = Authinator::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:auth_code) }) # remove ac
30
+ listener3 = Authinator::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:provider) }) # remove prov
31
+
32
+ expect(listener1.valid?).to be_falsey
33
+ expect(listener2.valid?).to be_falsey
34
+ expect(listener3.valid?).to be_falsey
35
+ 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
+
41
+ listener1 = Authinator::EndPointListener.new(bad_email_hash1)
42
+ listener2 = Authinator::EndPointListener.new(bad_email_hash2)
43
+ listener3 = Authinator::EndPointListener.new(bad_email_hash3)
44
+
45
+ expect(listener1.valid?).to be_falsey
46
+ expect(listener2.valid?).to be_falsey
47
+ expect(listener3.valid?).to be_falsey
48
+ end
49
+
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: '')
53
+
54
+ listener1 = Authinator::EndPointListener.new(bad_provider_hash1)
55
+ listener2 = Authinator::EndPointListener.new(bad_provider_hash2)
56
+
57
+ expect(listener1.valid?).to be_falsey
58
+ expect(listener2.valid?).to be_falsey
59
+ end
60
+
61
+ it 'should return a human-readable list of errors if there are any' do
62
+ listener = Authinator::EndPointListener.new({})
63
+ listener.valid?
64
+ expect(listener.errors).to eq [
65
+ 'A required param is missing',
66
+ '"email" field missing',
67
+ '"provider" field missing',
68
+ '"auth_code" field missing',
69
+ ]
70
+ end
71
+ end
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.1
4
+ version: 0.0.2
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-21 00:00:00.000000000 Z
11
+ date: 2014-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -114,8 +114,12 @@ files:
114
114
  - authinator.gemspec
115
115
  - lib/authinator.rb
116
116
  - lib/authinator/auth_code_exchanger.rb
117
+ - lib/authinator/client_token_issuer.rb
118
+ - lib/authinator/end_point_listener.rb
117
119
  - lib/authinator/version.rb
118
- - spec/authinator/authinator_spec.rb
120
+ - spec/authinator/auth_code_exchanger_spec.rb
121
+ - spec/authinator/client_token_issuer_spec.rb
122
+ - spec/authinator/end_point_listener_spec.rb
119
123
  - spec/spec_helper.rb
120
124
  homepage: https://github.com/abradner/authinator
121
125
  licenses:
@@ -142,5 +146,7 @@ signing_key:
142
146
  specification_version: 4
143
147
  summary: Single-Sign-On for the front and rails backend of a Single-Page-App
144
148
  test_files:
145
- - spec/authinator/authinator_spec.rb
149
+ - spec/authinator/auth_code_exchanger_spec.rb
150
+ - spec/authinator/client_token_issuer_spec.rb
151
+ - spec/authinator/end_point_listener_spec.rb
146
152
  - spec/spec_helper.rb