Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation Ebay OAuth2 Strategy for OmniAuth #1

Closed
wants to merge 13 commits into from

Conversation

paderinandrey
Copy link

Hi, please review this implementation and let me know if there is some bugs

Copy link
Member

@Envek Envek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution!

Some things that should be fixed for use in real apps:

  1. info hash layout. While it's backward compatible with omniauth-ebay gem (which is a good thing, it is somewhat uncommon for omniauth strategies in general).

  2. In real apps, it is important to know when refresh_token will expire to send a reminder to the user, asking to log in again (before token really expires and our app will stop to work). Also, it allows distinguishing between token expiration and token revocation by the user.

    Please add refresh_token_expires_at field into credentials hash.

  3. OAuth scopes. Public scope provided by default is awesome! But it should be documented better IMHO in README.

    Also, an example should be added (should user concatenate the list of scopes with space or can we do it for them?)

I like that you've used omniauth-oauth2 gem, as it solves some problems for free. Your implementation works.

However, code is a bit messy. Try to clean and refactor it with rubocop, for example.

spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
else
raise "RubyGems 2.0 or newer is required to protect against " \
"public gem pushes."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this as it is open source.


spec.add_runtime_dependency 'omniauth', '~> 1.0'
spec.add_runtime_dependency 'omniauth-oauth2', '~> 1.0'
spec.add_runtime_dependency 'oauth2', '~> 1.3'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need explicit requirement on oauth2 for some reason? omniauth-oauth2 already depends on ~> 1.0 of it.

Gemfile Outdated
gem 'rack-test'
gem 'rspec', '~> 3.6.0'
gem 'simplecov', require: false
gem 'webmock'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably better to move them it into the gemspec's add_development_dependency.


info do
{
ebay_id: raw_info['UserID'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to keep it in nickname field of info hash as per https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later

lib/ebay_api.rb Outdated
<ErrorLanguage>en_US</ErrorLanguage>
<WarningLevel>High</WarningLevel>
</GetUserRequest>
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to be moved to constant and freezed. Or even to a file.

lib/ebay_api.rb Outdated
<ErrorLanguage>en_US</ErrorLanguage>
<WarningLevel>High</WarningLevel>
</GetUserRequest>
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you should add DetailLevel tag to get user's full name, phone, etc.

<DetailLevel>ReturnAll</DetailLevel>

lib/ebay_api.rb Outdated
headers = ebay_request_headers(call_name, request.length.to_s)
url = URI.parse(api_url)
req = Net::HTTP::Post.new(url.path, headers)
http = Net::HTTP.new(url.host, url.port)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to extract http client configuration out. Rubocop already complaints about this method.


def raw_info
@user_info ||= get_user_info
@user_info
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is useless ✂️

end

def raw_info
@user_info ||= get_user_info
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming is weird. Both for instance variable (it is astonishing that it doesn't match method name) and for get_user_info method.

Copy link
Member

@Envek Envek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EbayAPI module is confusing me. It is a module but it can only be included in the classes that are inherited from OmniAuth::Strategies::OAuth2 class. This is makes tests somewhat easier to write, but blows mind away when someone tries to understand what is what in code. Many people have said “prefer composition over inheritance” mantra many times and it's probably worth to make EbayAPI standalone class with clear dependencies that we must to have to instantiate it and with clear API. So we can explicitly use it. I believe this will make things better.

But anyway these are just complaints about style, mostly. Your PR is working well.


credentials do
{
:refresh_token_expires_in => access_token['refresh_token_expires_in'].to_i
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oauth2 gem actually converts access token lifetime duration from expires_in field to unix timestamp and exposes it in expires_at field (see OAuth2::AccessToken#initialize) and omniauth-oauth2 uses only this field. I think it is better to do the same with refresh token for the sake of consistency.

Please change it to refresh_token_expires_at (returning Unix timestamp of token expiration).

README.md Outdated

```ruby
Rails.application.config.middleware.use OmniAuth::Builder do
provider :ebay, ENV['EBAY_KEY'], ENV['EBAY_SECRET'], ENV['EBAY_RUNAME'], scope: "sell.marketing, sell.account.readonly"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just allow to specify an array of scopes?


extra do
{
:raw_info => raw_info
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have changed to old hash syntax?

@paderinandrey
Copy link
Author

I fixed notes. My first gem turned out really cool. Thanks)

lib/ebay_api.rb Outdated
attr_accessor :request, :response
module OmniAuth
module Strategies
class EbayAPI
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OmniAuth::Strategies is not appropriate namespace, actually. Because this is not strategy itself and OmniAuth should not try to load it. It is better to keep it somewhere in gem namespace. Something like OmniAuth::Ebay::EbayAPI (scary, I know!)

@Envek
Copy link
Member

Envek commented Nov 9, 2017

Gem namespace is weird. All stuff (except OmniAuth strategy) should be placed somewhere inside OmniAuth::Ebay::OAuth module or something like it. To avoid screwing up with constants from omniauth-ebay gem (not sure if anyone will need to use them simultaneously), or from ebay_api gem (and we are absolutely sure that we will use them together) in one app.

Except that everything is fine. Thank you for patience — resolving reviews is hard.

@Envek
Copy link
Member

Envek commented Nov 13, 2017

I'm closing this PR in favor of #2. I'm very grateful for your work and patience in resolving issues.

This wasn't an easy decision as all three submitted pull requests were fully functional solutions, differing in some subjective things.

This project is now alive and if you notice that it lacks some useful features, have bugs or needs polishing — pull requests are always welcome!

I learned something about OAuth while reviewing this PR (even after working with this protocol before) and hope that you have learned a lot too.

@Envek Envek closed this Nov 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants