pax_global_header00006660000000000000000000000064133603311050014505gustar00rootroot0000000000000052 comment=04d762e9df511d81ba75dcc502d7697b2d25cafb oauth2-1.4.1/000077500000000000000000000000001336033110500127125ustar00rootroot00000000000000oauth2-1.4.1/.document000066400000000000000000000000741336033110500145320ustar00rootroot00000000000000README.rdoc lib/**/*.rb bin/* features/**/*.feature LICENSE oauth2-1.4.1/.gitignore000066400000000000000000000001401336033110500146750ustar00rootroot00000000000000*.gem *~ .bundle .rvmrc Gemfile.lock coverage/* log/* measurement/* pkg/* rdoc/* .rspec_status oauth2-1.4.1/.jrubyrc000066400000000000000000000000251336033110500143700ustar00rootroot00000000000000debug.fullTrace=true oauth2-1.4.1/.rspec000066400000000000000000000000271336033110500140260ustar00rootroot00000000000000--color --order random oauth2-1.4.1/.rubocop.yml000066400000000000000000000025021336033110500151630ustar00rootroot00000000000000require: rubocop-rspec inherit_from: - .rubocop_todo.yml - .rubocop_rspec.yml AllCops: DisplayCopNames: true # Display the name of the failing cops TargetRubyVersion: 2.1 Exclude: - 'gemfiles/vendor/**/*' - 'vendor/**/*' - '**/.irbrc' Gemspec/RequiredRubyVersion: Enabled: false Metrics/BlockLength: Enabled: false Metrics/BlockNesting: Max: 2 Metrics/LineLength: Enabled: false Metrics/MethodLength: Max: 15 Metrics/ParameterLists: Max: 4 Layout/AccessModifierIndentation: EnforcedStyle: outdent Layout/DotPosition: EnforcedStyle: trailing Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: no_space Lint/UnusedBlockArgument: Exclude: - 'spec/**/*.rb' - 'gemfiles/vendor/**/*' - 'vendor/**/*' - '**/.irbrc' RSpec/DescribeClass: Exclude: - 'spec/examples/*' RSpec/NestedGroups: Enabled: false Style/ClassVars: Enabled: false Style/CollectionMethods: PreferredMethods: map: 'collect' reduce: 'inject' find: 'detect' find_all: 'select' Style/Documentation: Enabled: false Style/DoubleNegation: Enabled: false Style/EmptyMethod: EnforcedStyle: expanded Style/Encoding: Enabled: false Style/TrailingCommaInArrayLiteral: EnforcedStyleForMultiline: comma Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma oauth2-1.4.1/.rubocop_rspec.yml000066400000000000000000000005431336033110500163620ustar00rootroot00000000000000RSpec/FilePath: Enabled: false RSpec/MultipleExpectations: Enabled: false RSpec/NamedSubject: Enabled: false RSpec/ExampleLength: Enabled: false RSpec/VerifiedDoubles: Enabled: false RSpec/MessageSpies: Enabled: false RSpec/InstanceVariable: Enabled: false RSpec/NestedGroups: Enabled: false RSpec/ExpectInHook: Enabled: false oauth2-1.4.1/.rubocop_todo.yml000066400000000000000000000004231336033110500162100ustar00rootroot00000000000000Style/HashSyntax: EnforcedStyle: hash_rockets Style/Lambda: Enabled: false Style/SymbolArray: Enabled: false Style/EachWithObject: Enabled: false # Once we drop Rubies that lack support for __dir__ we can turn this on. Style/ExpandPathArguments: Enabled: false oauth2-1.4.1/.travis.yml000066400000000000000000000025271336033110500150310ustar00rootroot00000000000000before_install: - gem update --system - gem install bundler bundler_args: --no-deployment --jobs 3 --retry 3 cache: bundler language: ruby matrix: allow_failures: - rvm: jruby-head - rvm: ruby-head - rvm: rbx-3 fast_finish: true include: - rvm: jruby-1.7.27 # targets MRI v1.9 gemfile: gemfiles/jruby_1.7.gemfile - rvm: 1.9.3-p551 gemfile: gemfiles/ruby_1.9.gemfile - rvm: 2.0.0-p648 gemfile: gemfiles/ruby_2.0.gemfile - rvm: 2.1.10 gemfile: gemfiles/ruby_2.1.gemfile - rvm: jruby-9.0.5.0 # targets MRI v2.0 gemfile: gemfiles/jruby_9.0.gemfile # DEPRECATION WARNING # oauth2 1.x series releases are the last to support Ruby versions above # oauth2 2.x series releases will support Ruby versions below, and not above - rvm: jruby-9.1.9.0 # targets MRI v2.3 gemfile: gemfiles/jruby_9.1.gemfile - rvm: 2.2.10 gemfile: gemfiles/ruby_2.2.gemfile - rvm: 2.3.7 gemfile: gemfiles/ruby_2.3.gemfile - rvm: 2.4.4 gemfile: gemfiles/ruby_2.4.gemfile - rvm: jruby-9.2.0.0 # targets MRI v2.5 gemfile: gemfiles/jruby_9.2.gemfile - rvm: 2.5.1 gemfile: gemfiles/ruby_2.5.gemfile - rvm: jruby-head gemfile: gemfiles/jruby_head.gemfile - rvm: ruby-head gemfile: gemfiles/ruby_head.gemfile - rvm: rbx-3 sudo: false oauth2-1.4.1/CHANGELOG.md000066400000000000000000000135021336033110500145240ustar00rootroot00000000000000# Change Log All notable changes to this project will be documented in this file. ## [unreleased] - no changes yet ## [1.4.1] - 2018-10-13 - [#417](oauth-xx/oauth2#417) - update jwt dependency (@thewoolleyman) - [#418](oauth-xx/oauth2#418) - remove rubocop dependency (temporary, added back in [#423](oauth-xx/oauth2#423)) (@pboling) - [#419](oauth-xx/oauth2#419) - update faraday dependency (@pboling) - [#420](oauth-xx/oauth2#420) - update [oauth2.gemspec](oauth2.gemspec) (@pboling) - [#421](oauth-xx/oauth2#421) - fix [CHANGELOG.md](CHANGELOG.md) for previous releases (@pboling) - [#422](oauth-xx/oauth2#422) - update [LICENSE](LICENSE) and [README.md](README.md) (@pboling) - [#423](oauth-xx/oauth2#423) - update [builds](https://travis-ci.org/oauth-xx/oauth2/builds), [Rakefile](Rakefile) (@pboling) - officially document supported Rubies * Ruby 1.9.3 * Ruby 2.0.0 * Ruby 2.1 * Ruby 2.2 * [JRuby 1.7][jruby-1.7] (targets MRI v1.9) * [JRuby 9.0][jruby-9.0] (targets MRI v2.0) * Ruby 2.3 * Ruby 2.4 * Ruby 2.5 * [JRuby 9.1][jruby-9.1] (targets MRI v2.3) * [JRuby 9.2][jruby-9.2] (targets MRI v2.5) [jruby-1.7]: https://www.jruby.org/2017/05/11/jruby-1-7-27.html [jruby-9.0]: https://www.jruby.org/2016/01/26/jruby-9-0-5-0.html [jruby-9.1]: https://www.jruby.org/2017/05/16/jruby-9-1-9-0.html [jruby-9.2]: https://www.jruby.org/2018/05/24/jruby-9-2-0-0.html ## [1.4.0] - 2017-06-09 - Drop Ruby 1.8.7 support (@sferik) - Fix some RuboCop offenses (@sferik) - _Dependency_: Remove Yardstick (@sferik) - _Dependency_: Upgrade Faraday to 0.12 (@sferik) ## [1.3.1] - 2017-03-03 - Add support for Ruby 2.4.0 (@pschambacher) - _Dependency_: Upgrade Faraday to Faraday 0.11 (@mcfiredrill, @rhymes, @pschambacher) ## [1.3.0] - 2016-12-28 - Add support for header-based authentication to the `Client` so it can be used across the library (@bjeanes) - Default to header-based authentication when getting a token from an authorisation code (@maletor) - **Breaking**: Allow an `auth_scheme` (`:basic_auth` or `:request_body`) to be set on the client, defaulting to `:request_body` to maintain backwards compatibility (@maletor, @bjeanes) - Handle `redirect_uri` according to the OAuth 2 spec, so it is passed on redirect and at the point of token exchange (@bjeanes) - Refactor handling of encoding of error responses (@urkle) - Avoid instantiating an `Error` if there is no error to raise (@urkle) - Add support for Faraday 0.10 (@rhymes) ## [1.2.0] - 2016-07-01 - Properly handle encoding of error responses (so we don't blow up, for example, when Google's response includes a ∞) (@Motoshi-Nishihira) - Make a copy of the options hash in `AccessToken#from_hash` to avoid accidental mutations (@Linuus) - Use `raise` rather than `fail` to throw exceptions (@sferik) ## [1.1.0] - 2016-01-30 - Various refactors (eliminating `Hash#merge!` usage in `AccessToken#refresh!`, use `yield` instead of `#call`, freezing mutable objects in constants, replacing constants with class variables) (@sferik) - Add support for Rack 2, and bump various other dependencies (@sferik) ## [1.0.0] - 2014-07-09 ### Added - Add an implementation of the MAC token spec. ### Fixed - Fix Base64.strict_encode64 incompatibility with Ruby 1.8.7. ## [0.5.0] - 2011-07-29 ### Changed - [breaking] `oauth_token` renamed to `oauth_bearer`. - [breaking] `authorize_path` Client option renamed to `authorize_url`. - [breaking] `access_token_path` Client option renamed to `token_url`. - [breaking] `access_token_method` Client option renamed to `token_method`. - [breaking] `web_server` renamed to `auth_code`. ## [0.4.1] - 2011-04-20 ## [0.4.0] - 2011-04-20 ## [0.3.0] - 2011-04-08 ## [0.2.0] - 2011-04-01 ## [0.1.1] - 2011-01-12 ## [0.1.0] - 2010-10-13 ## [0.0.13] + [0.0.12] + [0.0.11] - 2010-08-17 ## [0.0.10] - 2010-06-19 ## [0.0.9] - 2010-06-18 ## [0.0.8] + [0.0.7] - 2010-04-27 ## [0.0.6] - 2010-04-25 ## [0.0.5] - 2010-04-23 ## [0.0.4] + [0.0.3] + [0.0.2] + [0.0.1] - 2010-04-22 [0.0.1]: https://github.com/oauth-xx/oauth2/compare/311d9f4...v0.0.1 [0.0.2]: https://github.com/oauth-xx/oauth2/compare/v0.0.1...v0.0.2 [0.0.3]: https://github.com/oauth-xx/oauth2/compare/v0.0.2...v0.0.3 [0.0.4]: https://github.com/oauth-xx/oauth2/compare/v0.0.3...v0.0.4 [0.0.5]: https://github.com/oauth-xx/oauth2/compare/v0.0.4...v0.0.5 [0.0.6]: https://github.com/oauth-xx/oauth2/compare/v0.0.5...v0.0.6 [0.0.7]: https://github.com/oauth-xx/oauth2/compare/v0.0.6...v0.0.7 [0.0.8]: https://github.com/oauth-xx/oauth2/compare/v0.0.7...v0.0.8 [0.0.9]: https://github.com/oauth-xx/oauth2/compare/v0.0.8...v0.0.9 [0.0.10]: https://github.com/oauth-xx/oauth2/compare/v0.0.9...v0.0.10 [0.0.11]: https://github.com/oauth-xx/oauth2/compare/v0.0.10...v0.0.11 [0.0.12]: https://github.com/oauth-xx/oauth2/compare/v0.0.11...v0.0.12 [0.0.13]: https://github.com/oauth-xx/oauth2/compare/v0.0.12...v0.0.13 [0.1.0]: https://github.com/oauth-xx/oauth2/compare/v0.0.13...v0.1.0 [0.1.1]: https://github.com/oauth-xx/oauth2/compare/v0.1.0...v0.1.1 [0.2.0]: https://github.com/oauth-xx/oauth2/compare/v0.1.1...v0.2.0 [0.3.0]: https://github.com/oauth-xx/oauth2/compare/v0.2.0...v0.3.0 [0.4.0]: https://github.com/oauth-xx/oauth2/compare/v0.3.0...v0.4.0 [0.4.1]: https://github.com/oauth-xx/oauth2/compare/v0.4.0...v0.4.1 [0.5.0]: https://github.com/oauth-xx/oauth2/compare/v0.4.1...v0.5.0 [1.0.0]: https://github.com/oauth-xx/oauth2/compare/v0.9.4...v1.0.0 [1.1.0]: https://github.com/oauth-xx/oauth2/compare/v1.0.0...v1.1.0 [1.2.0]: https://github.com/oauth-xx/oauth2/compare/v1.1.0...v1.2.0 [1.3.0]: https://github.com/oauth-xx/oauth2/compare/v1.2.0...v1.3.0 [1.3.1]: https://github.com/oauth-xx/oauth2/compare/v1.3.0...v1.3.1 [1.4.0]: https://github.com/oauth-xx/oauth2/compare/v1.3.1...v1.4.0 [1.4.1]: https://github.com/oauth-xx/oauth2/compare/v1.4.0...v1.4.1 [unreleased]: https://github.com/oauth-xx/oauth2/compare/v1.4.0...1-4-stable oauth2-1.4.1/CODE_OF_CONDUCT.md000066400000000000000000000062361336033110500155200ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at peter.boling@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ oauth2-1.4.1/CONTRIBUTING.md000066400000000000000000000014541336033110500151470ustar00rootroot00000000000000## Submitting a Pull Request 1. [Fork the repository.][fork] 2. [Create a topic branch.][branch] 3. Add specs for your unimplemented feature or bug fix. 4. Run `bundle exec rake spec`. If your specs pass, return to step 3. 5. Implement your feature or bug fix. 6. Run `bundle exec rake`. If your specs fail, return to step 5. 7. Run `open coverage/index.html`. If your changes are not completely covered by your tests, return to step 3. 8. Add documentation for your feature or bug fix. 9. Run `bundle exec rake verify_measurements`. If your changes are not 100% documented, go back to step 8. 10. Commit and push your changes. 11. [Submit a pull request.][pr] [fork]: http://help.github.com/fork-a-repo/ [branch]: http://learn.github.com/p/branching.html [pr]: http://help.github.com/send-pull-requests/ oauth2-1.4.1/Gemfile000066400000000000000000000024511336033110500142070ustar00rootroot00000000000000source 'https://rubygems.org' git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } gem 'faraday', '~> 0.9.2', :platforms => [:jruby_18, :ruby_18] gem 'jwt', '< 1.5.2', :platforms => [:jruby_18, :ruby_18] gem 'rake', '< 11.0' gem 'rdoc', '~> 4.2.2' group :test do ruby_version = Gem::Version.new(RUBY_VERSION) if ruby_version >= Gem::Version.new('2.1') # TODO: Upgrade to >= 0.59 when we drop Rubies below 2.2 # Error: Unsupported Ruby version 2.1 found in `TargetRubyVersion` parameter (in .rubocop.yml). 2.1-compatible analysis was dropped after version 0.58. # Supported versions: 2.2, 2.3, 2.4, 2.5 gem 'rubocop', '~> 0.57.0' gem 'rubocop-rspec', '~> 1.27.0' # last version that can use rubocop < 0.58 end gem 'pry', '~> 0.11' if ruby_version >= Gem::Version.new('2.0') gem 'rspec-pending_for' gem 'addressable', '~> 2.3.8' gem 'backports' gem 'coveralls' gem 'rack', '~> 1.2', :platforms => [:jruby_18, :jruby_19, :ruby_18, :ruby_19, :ruby_20, :ruby_21] gem 'rspec', '>= 3' gem 'simplecov', '>= 0.9' platforms :jruby_18, :ruby_18 do gem 'mime-types', '~> 1.25' gem 'rest-client', '~> 1.6.0' end platforms :ruby_18, :ruby_19 do gem 'json', '< 2.0' gem 'term-ansicolor', '< 1.4.0' gem 'tins', '< 1.7' end end gemspec oauth2-1.4.1/LICENSE000066400000000000000000000022261336033110500137210ustar00rootroot00000000000000MIT License Copyright (c) 2011 - 2013 Michael Bleigh and Intridea, Inc. Copyright (c) 2017 - 2018 oauth-xx organization, https://github.com/oauth-xx Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. oauth2-1.4.1/README.md000066400000000000000000000217221336033110500141750ustar00rootroot00000000000000# OAuth2 [![Gem Version](http://img.shields.io/gem/v/oauth2.svg)][gem] [![Total Downloads](https://img.shields.io/gem/dt/oauth2.svg)][gem] [![Downloads Today](https://img.shields.io/gem/rt/oauth2.svg)][gem] [![Build Status](http://img.shields.io/travis/oauth-xx/oauth2.svg)][travis] [![Coverage Status](http://img.shields.io/coveralls/intridea/oauth2.svg)][coveralls] [![Maintainability](https://api.codeclimate.com/v1/badges/688c612528ff90a46955/maintainability)][codeclimate-maintainability] [![Depfu](https://badges.depfu.com/badges/6d34dc1ba682bbdf9ae2a97848241743/count.svg)][depfu] [![Open Source Helpers](https://www.codetriage.com/oauth-xx/oauth2/badges/users.svg)][code-triage] [![Chat](https://img.shields.io/gitter/room/oauth-xx/oauth2.svg)](https://gitter.im/oauth-xx/oauth2) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)][source-license] [![Documentation](http://inch-ci.org/github/oauth-xx/oauth2.png)][inch-ci] [gem]: https://rubygems.org/gems/oauth2 [travis]: http://travis-ci.org/oauth-xx/oauth2 [coveralls]: https://coveralls.io/r/oauth-xx/oauth2 [codeclimate-maintainability]: https://codeclimate.com/github/oauth-xx/oauth2/maintainability [depfu]: https://depfu.com/github/oauth-xx/oauth2 [source-license]: https://opensource.org/licenses/MIT [inch-ci]: http://inch-ci.org/github/oauth-xx/oauth2 [code-triage]: https://www.codetriage.com/oauth-xx/oauth2 A Ruby wrapper for the [OAuth 2.0 specification][oauth2-spec]. [oauth2-spec]: https://oauth.net/2/ ## Installation Add this line to your application's Gemfile: ```ruby gem 'oauth2' ``` And then execute: $ bundle Or install it yourself as: $ gem install oauth2 ## Resources * [View Source on GitHub][code] * [Report Issues on GitHub][issues] * [Read More at the Wiki][wiki] [code]: https://github.com/oauth-xx/oauth2 [issues]: https://github.com/oauth-xx/oauth2/issues [wiki]: https://github.com/oauth-xx/oauth2/wiki ## Usage Examples ```ruby require 'oauth2' client = OAuth2::Client.new('client_id', 'client_secret', :site => 'https://example.org') client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth2/callback') # => "https://example.org/oauth/authorization?response_type=code&client_id=client_id&redirect_uri=http://localhost:8080/oauth2/callback" token = client.auth_code.get_token('authorization_code_value', :redirect_uri => 'http://localhost:8080/oauth2/callback', :headers => {'Authorization' => 'Basic some_password'}) response = token.get('/api/resource', :params => { 'query_foo' => 'bar' }) response.class.name # => OAuth2::Response ``` ## OAuth2::Response The AccessToken methods #get, #post, #put and #delete and the generic #request will return an instance of the #OAuth2::Response class. This instance contains a #parsed method that will parse the response body and return a Hash if the Content-Type is application/x-www-form-urlencoded or if the body is a JSON object. It will return an Array if the body is a JSON array. Otherwise, it will return the original body string. The original response body, headers, and status can be accessed via their respective methods. ## OAuth2::AccessToken If you have an existing Access Token for a user, you can initialize an instance using various class methods including the standard new, from_hash (if you have a hash of the values), or from_kvform (if you have an application/x-www-form-urlencoded encoded string of the values). ## OAuth2::Error On 400+ status code responses, an OAuth2::Error will be raised. If it is a standard OAuth2 error response, the body will be parsed and #code and #description will contain the values provided from the error and error_description parameters. The #response property of OAuth2::Error will always contain the OAuth2::Response instance. If you do not want an error to be raised, you may use :raise_errors => false option on initialization of the client. In this case the OAuth2::Response instance will be returned as usual and on 400+ status code responses, the Response instance will contain the OAuth2::Error instance. ## Authorization Grants Currently the Authorization Code, Implicit, Resource Owner Password Credentials, Client Credentials, and Assertion authentication grant types have helper strategy classes that simplify client use. They are available via the #auth_code, #implicit, #password, #client_credentials, and #assertion methods respectively. ```ruby auth_url = client.auth_code.authorize_url(:redirect_uri => 'http://localhost:8080/oauth/callback') token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback') auth_url = client.implicit.authorize_url(:redirect_uri => 'http://localhost:8080/oauth/callback') # get the token params in the callback and token = OAuth2::AccessToken.from_kvform(client, query_string) token = client.password.get_token('username', 'password') token = client.client_credentials.get_token token = client.assertion.get_token(assertion_params) ``` If you want to specify additional headers to be sent out with the request, add a 'headers' hash under 'params': ```ruby token = client.auth_code.get_token('code_value', :redirect_uri => 'http://localhost:8080/oauth/callback', :headers => {'Some' => 'Header'}) ``` You can always use the #request method on the OAuth2::Client instance to make requests for tokens for any Authentication grant type. ## Supported Ruby Versions This library aims to support and is [tested against][travis] the following Ruby implementations: ### Rubies with support ending at Oauth2 2.x * Ruby 1.9.3 * Ruby 2.0.0 * Ruby 2.1 * Ruby 2.2 * [JRuby 1.7][jruby-1.7] (targets MRI v1.9) * [JRuby 9.0][jruby-9.0] (targets MRI v2.0) --- ### Rubies with continued support past Oauth2 2.x * Ruby 2.3 - Support through version 3.x series * Ruby 2.4 * Ruby 2.5 * [JRuby 9.1][jruby-9.1] (targets MRI v2.3) * [JRuby 9.2][jruby-9.2] (targets MRI v2.5) [jruby-1.7]: https://www.jruby.org/2017/05/11/jruby-1-7-27.html [jruby-9.0]: https://www.jruby.org/2016/01/26/jruby-9-0-5-0.html [jruby-9.1]: https://www.jruby.org/2017/05/16/jruby-9-1-9-0.html [jruby-9.2]: https://www.jruby.org/2018/05/24/jruby-9-2-0-0.html If something doesn't work on one of these interpreters, it's a bug. This library may inadvertently work (or seem to work) on other Ruby implementations, however support will only be provided for the versions listed above. If you would like this library to support another Ruby version, you may volunteer to be a maintainer. Being a maintainer entails making sure all tests run and pass on that implementation. When something breaks on your implementation, you will be responsible for providing patches in a timely fashion. If critical issues for a particular implementation exist at the time of a major release, support for that Ruby version may be dropped. ## Versioning This library aims to adhere to [Semantic Versioning 2.0.0][semver]. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions. As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint][pvc] with two digits of precision. For example: ```ruby spec.add_dependency 'oauth2', '~> 1.4' ``` [semver]: http://semver.org/ [pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint ## License [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)][source-license] - Copyright (c) 2011-2013 Michael Bleigh and Intridea, Inc. - Copyright (c) 2017-2018 [oauth-xx organization][oauth-xx] - See [LICENSE][license] for details. [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2.svg?type=large)][fossa2] [license]: LICENSE [oauth-xx]: https://github.com/oauth-xx [fossa2]: https://app.fossa.io/projects/git%2Bgithub.com%2Foauth-xx%2Foauth2?ref=badge_large ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/oauth-xx/oauth2. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. ## Code of Conduct Everyone interacting in the OAuth2 project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/oauth-xx/oauth2/blob/master/CODE_OF_CONDUCT.md). oauth2-1.4.1/Rakefile000066400000000000000000000015611336033110500143620ustar00rootroot00000000000000# encoding: utf-8 # !/usr/bin/env rake require 'bundler/gem_tasks' begin require 'wwtd/tasks' rescue LoadError puts 'failed to load wwtd' end begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) rescue LoadError task :spec do warn 'rspec is disabled' end end task :test => :spec begin require 'rubocop/rake_task' RuboCop::RakeTask.new do |task| task.options = ['-D'] # Display the name of the failing cops end rescue LoadError task :rubocop do warn 'RuboCop is disabled' end end namespace :doc do require 'rdoc/task' require File.expand_path('../lib/oauth2/version', __FILE__) RDoc::Task.new do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = "oauth2 #{OAuth2::Version}" rdoc.main = 'README.md' rdoc.rdoc_files.include('README.md', 'LICENSE.md', 'lib/**/*.rb') end end task :default => [:test, :rubocop] oauth2-1.4.1/gemfiles/000077500000000000000000000000001336033110500145055ustar00rootroot00000000000000oauth2-1.4.1/gemfiles/jruby_1.7.gemfile000066400000000000000000000002271336033110500175600ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' end gemspec :path => '../' oauth2-1.4.1/gemfiles/jruby_1.7.gemfile.lock000066400000000000000000000032071336033110500205100ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.4.0) backports (3.11.4) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0-java) jwt (1.5.6) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) rack (1.6.10) rake (12.2.1) rdoc (5.1.0) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.3.2) tins (~> 1.0) thor (0.19.4) tins (1.6.0) wwtd (1.3.0) PLATFORMS java DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! rake rdoc (>= 5.0, < 7) rspec rspec-pending_for wwtd BUNDLED WITH 1.16.6 oauth2-1.4.1/gemfiles/jruby_9.0.gemfile000066400000000000000000000003271336033110500175620ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/jruby_9.1.gemfile000066400000000000000000000003761336033110500175670ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/jruby_9.1.gemfile.lock000066400000000000000000000045751336033110500205230ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) ffi (1.9.25-java) json (2.1.0-java) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3-java) coderay (~> 1.1.0) method_source (~> 0.9.0) spoon (~> 0.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) spoon (0.0.6) ffi term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS java DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.4 oauth2-1.4.1/gemfiles/jruby_9.2.gemfile000066400000000000000000000003761336033110500175700ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/jruby_9.2.gemfile.lock000066400000000000000000000045751336033110500205240ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) ffi (1.9.25-java) json (2.1.0-java) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3-java) coderay (~> 1.1.0) method_source (~> 0.9.0) spoon (~> 0.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) spoon (0.0.6) ffi term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS java DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.4 oauth2-1.4.1/gemfiles/jruby_head.gemfile000066400000000000000000000003761336033110500201610ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_1.9.gemfile000066400000000000000000000003651336033110500174130ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' gem 'json', '< 2.0' gem 'rack', '~> 1.2' gem 'term-ansicolor', '< 1.4.0' gem 'tins', '< 1.7' group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_1.9.gemfile.lock000066400000000000000000000033131336033110500203360ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.4.0) backports (3.11.4) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (1.8.6) jwt (1.5.6) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) rack (1.6.10) rake (12.2.1) rdoc (5.1.0) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.3.2) tins (~> 1.0) thor (0.19.4) tins (1.6.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) json (< 2.0) oauth2! rack (~> 1.2) rake rdoc (>= 5.0, < 7) rspec rspec-pending_for term-ansicolor (< 1.4.0) tins (< 1.7) wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.0.gemfile000066400000000000000000000003241336033110500173760ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' gem 'rack', '~> 1.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.0.gemfile.lock000066400000000000000000000035201336033110500203260ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (1.5.6) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (2.0.5) rack (1.6.10) rake (12.3.1) rdoc (5.1.0) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rack (~> 1.2) rake rdoc (>= 5.0, < 7) rspec rspec-pending_for wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.1.gemfile000066400000000000000000000004241336033110500174000ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' gem 'rack', '~> 1.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.1.gemfile.lock000066400000000000000000000044751336033110500203410ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (1.6.10) rainbow (3.0.0) rake (12.3.1) rdoc (5.1.0) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rack (~> 1.2) rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.2.gemfile000066400000000000000000000003761336033110500174070ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.2.gemfile.lock000066400000000000000000000044541336033110500203370ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.3.gemfile000066400000000000000000000003761336033110500174100ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.3.gemfile.lock000066400000000000000000000044541336033110500203400ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.4.gemfile000066400000000000000000000003761336033110500174110ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.4.gemfile.lock000066400000000000000000000044541336033110500203410ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.2 oauth2-1.4.1/gemfiles/ruby_2.5.gemfile000066400000000000000000000003761336033110500174120ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_2.5.gemfile.lock000066400000000000000000000044541336033110500203420ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.5 oauth2-1.4.1/gemfiles/ruby_head.gemfile000066400000000000000000000003761336033110500200070ustar00rootroot00000000000000source 'https://rubygems.org' gem 'faraday', '0.9.2' group :development do gem 'pry' end group :test do gem 'rake' gem 'rspec' gem 'rspec-pending_for' gem 'rubocop', '~> 0.53.0' gem 'rubocop-rspec', '~> 1.24.0' end gemspec :path => '../' oauth2-1.4.1/gemfiles/ruby_head.gemfile.lock000066400000000000000000000044541336033110500207370ustar00rootroot00000000000000PATH remote: .. specs: oauth2 (1.4.0) faraday (>= 0.8, < 0.16.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) GEM remote: https://rubygems.org/ specs: addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) ast (2.4.0) backports (3.11.4) coderay (1.1.2) coveralls (0.8.22) json (>= 1.8, < 3) simplecov (~> 0.16.1) term-ansicolor (~> 1.3) thor (~> 0.19.4) tins (~> 1.6) diff-lcs (1.3) docile (1.3.1) faraday (0.9.2) multipart-post (>= 1.2, < 3) json (2.1.0) jwt (2.1.0) method_source (0.9.0) multi_json (1.13.1) multi_xml (0.6.0) multipart-post (2.0.0) parallel (1.12.1) parser (2.5.1.2) ast (~> 2.4.0) powerpack (0.1.2) pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) public_suffix (3.0.3) rack (2.0.5) rainbow (3.0.0) rake (12.3.1) rdoc (6.0.4) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-pending_for (0.1.13) rspec-core ruby_engine (~> 1.0) ruby_version (~> 1.0) rspec-support (3.8.0) rubocop (0.53.0) parallel (~> 1.10) parser (>= 2.5) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) rubocop-rspec (1.24.0) rubocop (>= 0.53.0) ruby-progressbar (1.10.0) ruby_engine (1.0.1) ruby_version (1.0.1) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) term-ansicolor (1.6.0) tins (~> 1.0) thor (0.19.4) tins (1.16.3) unicode-display_width (1.4.0) wwtd (1.3.0) PLATFORMS ruby DEPENDENCIES addressable (~> 2.3) backports (~> 3.11) bundler (~> 1.16) coveralls (~> 0.8) faraday (= 0.9.2) oauth2! pry rake rdoc (>= 5.0, < 7) rspec rspec-pending_for rubocop (~> 0.53.0) rubocop-rspec (~> 1.24.0) wwtd BUNDLED WITH 1.16.4 oauth2-1.4.1/lib/000077500000000000000000000000001336033110500134605ustar00rootroot00000000000000oauth2-1.4.1/lib/oauth2.rb000066400000000000000000000005731336033110500152140ustar00rootroot00000000000000require 'oauth2/error' require 'oauth2/authenticator' require 'oauth2/client' require 'oauth2/strategy/base' require 'oauth2/strategy/auth_code' require 'oauth2/strategy/implicit' require 'oauth2/strategy/password' require 'oauth2/strategy/client_credentials' require 'oauth2/strategy/assertion' require 'oauth2/access_token' require 'oauth2/mac_token' require 'oauth2/response' oauth2-1.4.1/lib/oauth2/000077500000000000000000000000001336033110500146625ustar00rootroot00000000000000oauth2-1.4.1/lib/oauth2/access_token.rb000066400000000000000000000135041336033110500176530ustar00rootroot00000000000000module OAuth2 class AccessToken attr_reader :client, :token, :expires_in, :expires_at, :params attr_accessor :options, :refresh_token class << self # Initializes an AccessToken from a Hash # # @param [Client] the OAuth2::Client instance # @param [Hash] a hash of AccessToken property values # @return [AccessToken] the initalized AccessToken def from_hash(client, hash) hash = hash.dup new(client, hash.delete('access_token') || hash.delete(:access_token), hash) end # Initializes an AccessToken from a key/value application/x-www-form-urlencoded string # # @param [Client] client the OAuth2::Client instance # @param [String] kvform the application/x-www-form-urlencoded string # @return [AccessToken] the initalized AccessToken def from_kvform(client, kvform) from_hash(client, Rack::Utils.parse_query(kvform)) end end # Initalize an AccessToken # # @param [Client] client the OAuth2::Client instance # @param [String] token the Access Token value # @param [Hash] opts the options to create the Access Token with # @option opts [String] :refresh_token (nil) the refresh_token value # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire # @option opts [Symbol] :mode (:header) the transmission mode of the Access Token parameter value # one of :header, :body or :query # @option opts [String] :header_format ('Bearer %s') the string format to use for the Authorization header # @option opts [String] :param_name ('access_token') the parameter name to use for transmission of the # Access Token value in :body or :query transmission mode def initialize(client, token, opts = {}) # rubocop:disable Metrics/AbcSize @client = client @token = token.to_s opts = opts.dup [:refresh_token, :expires_in, :expires_at].each do |arg| instance_variable_set("@#{arg}", opts.delete(arg) || opts.delete(arg.to_s)) end @expires_in ||= opts.delete('expires') @expires_in &&= @expires_in.to_i @expires_at &&= @expires_at.to_i @expires_at ||= Time.now.to_i + @expires_in if @expires_in @options = {:mode => opts.delete(:mode) || :header, :header_format => opts.delete(:header_format) || 'Bearer %s', :param_name => opts.delete(:param_name) || 'access_token'} @params = opts end # Indexer to additional params present in token response # # @param [String] key entry key to Hash def [](key) @params[key] end # Whether or not the token expires # # @return [Boolean] def expires? !!@expires_at end # Whether or not the token is expired # # @return [Boolean] def expired? expires? && (expires_at < Time.now.to_i) end # Refreshes the current Access Token # # @return [AccessToken] a new AccessToken # @note options should be carried over to the new AccessToken def refresh!(params = {}) raise('A refresh_token is not available') unless refresh_token params[:grant_type] = 'refresh_token' params[:refresh_token] = refresh_token new_token = @client.get_token(params) new_token.options = options new_token.refresh_token = refresh_token unless new_token.refresh_token new_token end # Convert AccessToken to a hash which can be used to rebuild itself with AccessToken.from_hash # # @return [Hash] a hash of AccessToken property values def to_hash params.merge(:access_token => token, :refresh_token => refresh_token, :expires_at => expires_at) end # Make a request with the Access Token # # @param [Symbol] verb the HTTP request method # @param [String] path the HTTP URL path of the request # @param [Hash] opts the options to make the request with # @see Client#request def request(verb, path, opts = {}, &block) configure_authentication!(opts) @client.request(verb, path, opts, &block) end # Make a GET request with the Access Token # # @see AccessToken#request def get(path, opts = {}, &block) request(:get, path, opts, &block) end # Make a POST request with the Access Token # # @see AccessToken#request def post(path, opts = {}, &block) request(:post, path, opts, &block) end # Make a PUT request with the Access Token # # @see AccessToken#request def put(path, opts = {}, &block) request(:put, path, opts, &block) end # Make a PATCH request with the Access Token # # @see AccessToken#request def patch(path, opts = {}, &block) request(:patch, path, opts, &block) end # Make a DELETE request with the Access Token # # @see AccessToken#request def delete(path, opts = {}, &block) request(:delete, path, opts, &block) end # Get the headers hash (includes Authorization token) def headers {'Authorization' => options[:header_format] % token} end private def configure_authentication!(opts) # rubocop:disable MethodLength, Metrics/AbcSize case options[:mode] when :header opts[:headers] ||= {} opts[:headers].merge!(headers) when :query opts[:params] ||= {} opts[:params][options[:param_name]] = token when :body opts[:body] ||= {} if opts[:body].is_a?(Hash) opts[:body][options[:param_name]] = token else opts[:body] << "&#{options[:param_name]}=#{token}" end # @todo support for multi-part (file uploads) else raise("invalid :mode option of #{options[:mode]}") end end end end oauth2-1.4.1/lib/oauth2/authenticator.rb000066400000000000000000000031331336033110500200610ustar00rootroot00000000000000require 'base64' module OAuth2 class Authenticator attr_reader :mode, :id, :secret def initialize(id, secret, mode) @id = id @secret = secret @mode = mode end # Apply the request credentials used to authenticate to the Authorization Server # # Depending on configuration, this might be as request params or as an # Authorization header. # # User-provided params and header take precedence. # # @param [Hash] params a Hash of params for the token endpoint # @return [Hash] params amended with appropriate authentication details def apply(params) case mode.to_sym when :basic_auth apply_basic_auth(params) when :request_body apply_params_auth(params) else raise NotImplementedError end end def self.encode_basic_auth(user, password) 'Basic ' + Base64.encode64(user + ':' + password).delete("\n") end private # Adds client_id and client_secret request parameters if they are not # already set. def apply_params_auth(params) {'client_id' => id, 'client_secret' => secret}.merge(params) end # Adds an `Authorization` header with Basic Auth credentials if and only if # it is not already set in the params. def apply_basic_auth(params) headers = params.fetch(:headers, {}) headers = basic_auth_header.merge(headers) params.merge(:headers => headers) end # @see https://tools.ietf.org/html/rfc2617#section-2 def basic_auth_header {'Authorization' => self.class.encode_basic_auth(id, secret)} end end end oauth2-1.4.1/lib/oauth2/client.rb000066400000000000000000000201351336033110500164660ustar00rootroot00000000000000require 'faraday' require 'logger' module OAuth2 # The OAuth2::Client class class Client # rubocop:disable Metrics/ClassLength attr_reader :id, :secret, :site attr_accessor :options attr_writer :connection # Instantiate a new OAuth 2.0 client using the # Client ID and Client Secret registered to your # application. # # @param [String] client_id the client_id value # @param [String] client_secret the client_secret value # @param [Hash] opts the options to create the client with # @option opts [String] :site the OAuth2 provider site host # @option opts [String] :redirect_uri the absolute URI to the Redirection Endpoint for use in authorization grants and token exchange # @option opts [String] :authorize_url ('/oauth/authorize') absolute or relative URL path to the Authorization endpoint # @option opts [String] :token_url ('/oauth/token') absolute or relative URL path to the Token endpoint # @option opts [Symbol] :token_method (:post) HTTP method to use to request token (:get or :post) # @option opts [Symbol] :auth_scheme (:basic_auth) HTTP method to use to authorize request (:basic_auth or :request_body) # @option opts [Hash] :connection_opts ({}) Hash of connection options to pass to initialize Faraday with # @option opts [FixNum] :max_redirects (5) maximum number of redirects to follow # @option opts [Boolean] :raise_errors (true) whether or not to raise an OAuth2::Error # on responses with 400+ status codes # @yield [builder] The Faraday connection builder def initialize(client_id, client_secret, options = {}, &block) opts = options.dup @id = client_id @secret = client_secret @site = opts.delete(:site) ssl = opts.delete(:ssl) @options = {:authorize_url => '/oauth/authorize', :token_url => '/oauth/token', :token_method => :post, :auth_scheme => :request_body, :connection_opts => {}, :connection_build => block, :max_redirects => 5, :raise_errors => true}.merge(opts) @options[:connection_opts][:ssl] = ssl if ssl end # Set the site host # # @param [String] the OAuth2 provider site host def site=(value) @connection = nil @site = value end # The Faraday connection object def connection @connection ||= begin conn = Faraday.new(site, options[:connection_opts]) if options[:connection_build] conn.build do |b| options[:connection_build].call(b) end end conn end end # The authorize endpoint URL of the OAuth2 provider # # @param [Hash] params additional query parameters def authorize_url(params = {}) params = (params || {}).merge(redirection_params) connection.build_url(options[:authorize_url], params).to_s end # The token endpoint URL of the OAuth2 provider # # @param [Hash] params additional query parameters def token_url(params = nil) connection.build_url(options[:token_url], params).to_s end # Makes a request relative to the specified site root. # # @param [Symbol] verb one of :get, :post, :put, :delete # @param [String] url URL path of request # @param [Hash] opts the options to make the request with # @option opts [Hash] :params additional query parameters for the URL of the request # @option opts [Hash, String] :body the body of the request # @option opts [Hash] :headers http request headers # @option opts [Boolean] :raise_errors whether or not to raise an OAuth2::Error on 400+ status # code response for this request. Will default to client option # @option opts [Symbol] :parse @see Response::initialize # @yield [req] The Faraday request def request(verb, url, opts = {}) # rubocop:disable CyclomaticComplexity, MethodLength, Metrics/AbcSize connection.response :logger, ::Logger.new($stdout) if ENV['OAUTH_DEBUG'] == 'true' url = connection.build_url(url, opts[:params]).to_s response = connection.run_request(verb, url, opts[:body], opts[:headers]) do |req| yield(req) if block_given? end response = Response.new(response, :parse => opts[:parse]) case response.status when 301, 302, 303, 307 opts[:redirect_count] ||= 0 opts[:redirect_count] += 1 return response if opts[:redirect_count] > options[:max_redirects] if response.status == 303 verb = :get opts.delete(:body) end request(verb, response.headers['location'], opts) when 200..299, 300..399 # on non-redirecting 3xx statuses, just return the response response when 400..599 error = Error.new(response) raise(error) if opts.fetch(:raise_errors, options[:raise_errors]) response.error = error response else error = Error.new(response) raise(error, "Unhandled status code value of #{response.status}") end end # Initializes an AccessToken by making a request to the token endpoint # # @param [Hash] params a Hash of params for the token endpoint # @param [Hash] access token options, to pass to the AccessToken object # @param [Class] class of access token for easier subclassing OAuth2::AccessToken # @return [AccessToken] the initalized AccessToken def get_token(params, access_token_opts = {}, access_token_class = AccessToken) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength params = Authenticator.new(id, secret, options[:auth_scheme]).apply(params) opts = {:raise_errors => options[:raise_errors], :parse => params.delete(:parse)} headers = params.delete(:headers) || {} if options[:token_method] == :post opts[:body] = params opts[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'} else opts[:params] = params opts[:headers] = {} end opts[:headers].merge!(headers) response = request(options[:token_method], token_url, opts) if options[:raise_errors] && !(response.parsed.is_a?(Hash) && response.parsed['access_token']) error = Error.new(response) raise(error) end access_token_class.from_hash(self, response.parsed.merge(access_token_opts)) end # The Authorization Code strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1 def auth_code @auth_code ||= OAuth2::Strategy::AuthCode.new(self) end # The Implicit strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2 def implicit @implicit ||= OAuth2::Strategy::Implicit.new(self) end # The Resource Owner Password Credentials strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3 def password @password ||= OAuth2::Strategy::Password.new(self) end # The Client Credentials strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4 def client_credentials @client_credentials ||= OAuth2::Strategy::ClientCredentials.new(self) end def assertion @assertion ||= OAuth2::Strategy::Assertion.new(self) end # The redirect_uri parameters, if configured # # The redirect_uri query parameter is OPTIONAL (though encouraged) when # requesting authorization. If it is provided at authorization time it MUST # also be provided with the token exchange request. # # Providing the :redirect_uri to the OAuth2::Client instantiation will take # care of managing this. # # @api semipublic # # @see https://tools.ietf.org/html/rfc6749#section-4.1 # @see https://tools.ietf.org/html/rfc6749#section-4.1.3 # @see https://tools.ietf.org/html/rfc6749#section-4.2.1 # @see https://tools.ietf.org/html/rfc6749#section-10.6 # @return [Hash] the params to add to a request or URL def redirection_params if options[:redirect_uri] {'redirect_uri' => options[:redirect_uri]} else {} end end end end oauth2-1.4.1/lib/oauth2/error.rb000066400000000000000000000025471336033110500163500ustar00rootroot00000000000000module OAuth2 class Error < StandardError attr_reader :response, :code, :description # standard error values include: # :invalid_request, :invalid_client, :invalid_token, :invalid_grant, :unsupported_grant_type, :invalid_scope def initialize(response) response.error = self @response = response if response.parsed.is_a?(Hash) @code = response.parsed['error'] @description = response.parsed['error_description'] error_description = "#{@code}: #{@description}" end super(error_message(response.body, :error_description => error_description)) end # Makes a error message # @param [String] response_body response body of request # @param [String] opts :error_description error description to show first line def error_message(response_body, opts = {}) message = [] opts[:error_description] && message << opts[:error_description] error_message = if opts[:error_description] && opts[:error_description].respond_to?(:encoding) script_encoding = opts[:error_description].encoding response_body.encode(script_encoding, :invalid => :replace, :undef => :replace) else response_body end message << error_message message.join("\n") end end end oauth2-1.4.1/lib/oauth2/mac_token.rb000066400000000000000000000076651336033110500171650ustar00rootroot00000000000000require 'base64' require 'digest' require 'openssl' require 'securerandom' module OAuth2 class MACToken < AccessToken # Generates a MACToken from an AccessToken and secret # # @param [AccessToken] token the OAuth2::Token instance # @option [String] secret the secret key value # @param [Hash] opts the options to create the Access Token with # @see MACToken#initialize def self.from_access_token(token, secret, options = {}) new(token.client, token.token, secret, token.params.merge(:refresh_token => token.refresh_token, :expires_in => token.expires_in, :expires_at => token.expires_at).merge(options)) end attr_reader :secret, :algorithm # Initalize a MACToken # # @param [Client] client the OAuth2::Client instance # @param [String] token the Access Token value # @option [String] secret the secret key value # @param [Hash] opts the options to create the Access Token with # @option opts [String] :refresh_token (nil) the refresh_token value # @option opts [FixNum, String] :expires_in (nil) the number of seconds in which the AccessToken will expire # @option opts [FixNum, String] :expires_at (nil) the epoch time in seconds in which AccessToken will expire # @option opts [FixNum, String] :algorithm (hmac-sha-256) the algorithm to use for the HMAC digest (one of 'hmac-sha-256', 'hmac-sha-1') def initialize(client, token, secret, opts = {}) @secret = secret self.algorithm = opts.delete(:algorithm) || 'hmac-sha-256' super(client, token, opts) end # Make a request with the MAC Token # # @param [Symbol] verb the HTTP request method # @param [String] path the HTTP URL path of the request # @param [Hash] opts the options to make the request with # @see Client#request def request(verb, path, opts = {}, &block) url = client.connection.build_url(path, opts[:params]).to_s opts[:headers] ||= {} opts[:headers]['Authorization'] = header(verb, url) @client.request(verb, path, opts, &block) end # Get the headers hash (always an empty hash) def headers {} end # Generate the MAC header # # @param [Symbol] verb the HTTP request method # @param [String] url the HTTP URL path of the request def header(verb, url) timestamp = Time.now.utc.to_i nonce = Digest::MD5.hexdigest([timestamp, SecureRandom.hex].join(':')) uri = URI.parse(url) raise(ArgumentError, "could not parse \"#{url}\" into URI") unless uri.is_a?(URI::HTTP) mac = signature(timestamp, nonce, verb, uri) "MAC id=\"#{token}\", ts=\"#{timestamp}\", nonce=\"#{nonce}\", mac=\"#{mac}\"" end # Generate the Base64-encoded HMAC digest signature # # @param [Fixnum] timestamp the timestamp of the request in seconds since epoch # @param [String] nonce the MAC header nonce # @param [Symbol] verb the HTTP request method # @param [String] url the HTTP URL path of the request def signature(timestamp, nonce, verb, uri) signature = [ timestamp, nonce, verb.to_s.upcase, uri.request_uri, uri.host, uri.port, '', nil ].join("\n") strict_encode64(OpenSSL::HMAC.digest(@algorithm, secret, signature)) end # Set the HMAC algorithm # # @param [String] alg the algorithm to use (one of 'hmac-sha-1', 'hmac-sha-256') def algorithm=(alg) @algorithm = begin case alg.to_s when 'hmac-sha-1' OpenSSL::Digest::SHA1.new when 'hmac-sha-256' OpenSSL::Digest::SHA256.new else raise(ArgumentError, 'Unsupported algorithm') end end end private # No-op since we need the verb and path # and the MAC always goes in a header def token=(_noop) end # Base64.strict_encode64 is not available on Ruby 1.8.7 def strict_encode64(str) Base64.encode64(str).delete("\n") end end end oauth2-1.4.1/lib/oauth2/response.rb000066400000000000000000000055121336033110500170500ustar00rootroot00000000000000require 'multi_json' require 'multi_xml' require 'rack' module OAuth2 # OAuth2::Response class class Response attr_reader :response attr_accessor :error, :options # Procs that, when called, will parse a response body according # to the specified format. @@parsers = { :json => lambda { |body| MultiJson.load(body) rescue body }, # rubocop:disable RescueModifier :query => lambda { |body| Rack::Utils.parse_query(body) }, :text => lambda { |body| body }, } # Content type assignments for various potential HTTP content types. @@content_types = { 'application/json' => :json, 'text/javascript' => :json, 'application/x-www-form-urlencoded' => :query, 'text/plain' => :text, } # Adds a new content type parser. # # @param [Symbol] key A descriptive symbol key such as :json or :query. # @param [Array] mime_types One or more mime types to which this parser applies. # @yield [String] A block returning parsed content. def self.register_parser(key, mime_types, &block) key = key.to_sym @@parsers[key] = block Array(mime_types).each do |mime_type| @@content_types[mime_type] = key end end # Initializes a Response instance # # @param [Faraday::Response] response The Faraday response instance # @param [Hash] opts options in which to initialize the instance # @option opts [Symbol] :parse (:automatic) how to parse the response body. one of :query (for x-www-form-urlencoded), # :json, or :automatic (determined by Content-Type response header) def initialize(response, opts = {}) @response = response @options = {:parse => :automatic}.merge(opts) end # The HTTP response headers def headers response.headers end # The HTTP response status code def status response.status end # The HTTP response body def body response.body || '' end # The parsed response body. # Will attempt to parse application/x-www-form-urlencoded and # application/json Content-Type response bodies def parsed return nil unless @@parsers.key?(parser) @parsed ||= @@parsers[parser].call(body) end # Attempts to determine the content type of the response. def content_type ((response.headers.values_at('content-type', 'Content-Type').compact.first || '').split(';').first || '').strip end # Determines the parser that will be used to supply the content of #parsed def parser return options[:parse].to_sym if @@parsers.key?(options[:parse]) @@content_types[content_type] end end end OAuth2::Response.register_parser(:xml, ['text/xml', 'application/rss+xml', 'application/rdf+xml', 'application/atom+xml']) do |body| MultiXml.parse(body) rescue body # rubocop:disable RescueModifier end oauth2-1.4.1/lib/oauth2/strategy/000077500000000000000000000000001336033110500165245ustar00rootroot00000000000000oauth2-1.4.1/lib/oauth2/strategy/assertion.rb000066400000000000000000000046231336033110500210650ustar00rootroot00000000000000require 'jwt' module OAuth2 module Strategy # The Client Assertion Strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.3 # # Sample usage: # client = OAuth2::Client.new(client_id, client_secret, # :site => 'http://localhost:8080') # # params = {:hmac_secret => "some secret", # # or :private_key => "private key string", # :iss => "http://localhost:3001", # :prn => "me@here.com", # :exp => Time.now.utc.to_i + 3600} # # access = client.assertion.get_token(params) # access.token # actual access_token string # access.get("/api/stuff") # making api calls with access token in header # class Assertion < Base # Not used for this strategy # # @raise [NotImplementedError] def authorize_url raise(NotImplementedError, 'The authorization endpoint is not used in this strategy') end # Retrieve an access token given the specified client. # # @param [Hash] params assertion params # pass either :hmac_secret or :private_key, but not both. # # params :hmac_secret, secret string. # params :private_key, private key string. # # params :iss, issuer # params :aud, audience, optional # params :prn, principal, current user # params :exp, expired at, in seconds, like Time.now.utc.to_i + 3600 # # @param [Hash] opts options def get_token(params = {}, opts = {}) hash = build_request(params) @client.get_token(hash, opts.merge('refresh_token' => nil)) end def build_request(params) assertion = build_assertion(params) { :grant_type => 'assertion', :assertion_type => 'urn:ietf:params:oauth:grant-type:jwt-bearer', :assertion => assertion, :scope => params[:scope], } end def build_assertion(params) claims = { :iss => params[:iss], :aud => params[:aud], :prn => params[:prn], :exp => params[:exp], } if params[:hmac_secret] JWT.encode(claims, params[:hmac_secret], 'HS256') elsif params[:private_key] JWT.encode(claims, params[:private_key], 'RS256') end end end end end oauth2-1.4.1/lib/oauth2/strategy/auth_code.rb000066400000000000000000000022741336033110500210110ustar00rootroot00000000000000module OAuth2 module Strategy # The Authorization Code Strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.1 class AuthCode < Base # The required query parameters for the authorize URL # # @param [Hash] params additional query parameters def authorize_params(params = {}) params.merge('response_type' => 'code', 'client_id' => @client.id) end # The authorization URL endpoint of the provider # # @param [Hash] params additional query parameters for the URL def authorize_url(params = {}) @client.authorize_url(authorize_params.merge(params)) end # Retrieve an access token given the specified validation code. # # @param [String] code The Authorization Code value # @param [Hash] params additional params # @param [Hash] opts options # @note that you must also provide a :redirect_uri with most OAuth 2.0 providers def get_token(code, params = {}, opts = {}) params = {'grant_type' => 'authorization_code', 'code' => code}.merge(@client.redirection_params).merge(params) @client.get_token(params, opts) end end end end oauth2-1.4.1/lib/oauth2/strategy/base.rb000066400000000000000000000002011336033110500177540ustar00rootroot00000000000000module OAuth2 module Strategy class Base def initialize(client) @client = client end end end end oauth2-1.4.1/lib/oauth2/strategy/client_credentials.rb000066400000000000000000000013621336033110500227060ustar00rootroot00000000000000module OAuth2 module Strategy # The Client Credentials Strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.4 class ClientCredentials < Base # Not used for this strategy # # @raise [NotImplementedError] def authorize_url raise(NotImplementedError, 'The authorization endpoint is not used in this strategy') end # Retrieve an access token given the specified client. # # @param [Hash] params additional params # @param [Hash] opts options def get_token(params = {}, opts = {}) params = params.merge('grant_type' => 'client_credentials') @client.get_token(params, opts.merge('refresh_token' => nil)) end end end end oauth2-1.4.1/lib/oauth2/strategy/implicit.rb000066400000000000000000000015571336033110500206730ustar00rootroot00000000000000module OAuth2 module Strategy # The Implicit Strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-26#section-4.2 class Implicit < Base # The required query parameters for the authorize URL # # @param [Hash] params additional query parameters def authorize_params(params = {}) params.merge('response_type' => 'token', 'client_id' => @client.id) end # The authorization URL endpoint of the provider # # @param [Hash] params additional query parameters for the URL def authorize_url(params = {}) @client.authorize_url(authorize_params.merge(params)) end # Not used for this strategy # # @raise [NotImplementedError] def get_token(*) raise(NotImplementedError, 'The token is accessed differently in this strategy') end end end end oauth2-1.4.1/lib/oauth2/strategy/password.rb000066400000000000000000000016611336033110500207170ustar00rootroot00000000000000module OAuth2 module Strategy # The Resource Owner Password Credentials Authorization Strategy # # @see http://tools.ietf.org/html/draft-ietf-oauth-v2-15#section-4.3 class Password < Base # Not used for this strategy # # @raise [NotImplementedError] def authorize_url raise(NotImplementedError, 'The authorization endpoint is not used in this strategy') end # Retrieve an access token given the specified End User username and password. # # @param [String] username the End User username # @param [String] password the End User password # @param [Hash] params additional params def get_token(username, password, params = {}, opts = {}) params = {'grant_type' => 'password', 'username' => username, 'password' => password}.merge(params) @client.get_token(params, opts) end end end end oauth2-1.4.1/lib/oauth2/version.rb000066400000000000000000000015421336033110500166760ustar00rootroot00000000000000module OAuth2 module Version module_function # The major version # # @return [Integer] def major 1 end # The minor version # # @return [Integer] def minor 4 end # The patch version # # @return [Integer] def patch 1 end # The pre-release version, if any # # @return [Integer, NilClass] def pre nil end # The version number as a hash # # @return [Hash] def to_h { :major => major, :minor => minor, :patch => patch, :pre => pre, } end # The version number as an array # # @return [Array] def to_a [major, minor, patch, pre].compact end # The version number as a string # # @return [String] def to_s to_a.join('.') end end end oauth2-1.4.1/oauth2.gemspec000066400000000000000000000032161336033110500154630ustar00rootroot00000000000000# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'oauth2/version' Gem::Specification.new do |spec| spec.add_dependency 'faraday', ['>= 0.8', '< 0.16.0'] spec.add_dependency 'jwt', ['>= 1.0', '< 3.0'] spec.add_dependency 'multi_json', '~> 1.3' spec.add_dependency 'multi_xml', '~> 0.5' spec.add_dependency 'rack', ['>= 1.2', '< 3'] spec.authors = ['Peter Boling', 'Michael Bleigh', 'Erik Michaels-Ober'] spec.description = 'A Ruby wrapper for the OAuth 2.0 protocol built with a similar style to the original OAuth spec.' spec.email = ['peter.boling@gmail.com'] spec.homepage = 'https://github.com/oauth-xx/oauth2' spec.licenses = %w[MIT] spec.name = 'oauth2' spec.required_ruby_version = '>= 1.9.0' spec.required_rubygems_version = '>= 1.3.5' spec.summary = 'A Ruby wrapper for the OAuth 2.0 protocol.' spec.version = OAuth2::Version spec.require_paths = %w[lib] spec.bindir = 'exe' spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.files = `git ls-files -z`.split("\x0").reject do |f| f.match(%r{^(bin|test|spec|features)/}) end spec.add_development_dependency 'addressable', '~> 2.3' spec.add_development_dependency 'backports', '~> 3.11' spec.add_development_dependency 'bundler', '~> 1.16' spec.add_development_dependency 'coveralls', '~> 0.8' spec.add_development_dependency 'rake', '~> 12.3' spec.add_development_dependency 'rdoc', ['>= 5.0', '< 7'] spec.add_development_dependency 'rspec', '~> 3.0' spec.add_development_dependency 'wwtd' end oauth2-1.4.1/spec/000077500000000000000000000000001336033110500136445ustar00rootroot00000000000000oauth2-1.4.1/spec/helper.rb000066400000000000000000000012741336033110500154540ustar00rootroot00000000000000if RUBY_VERSION >= '1.9' require 'simplecov' require 'coveralls' SimpleCov.formatters = [SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter] SimpleCov.start do add_filter '/spec' minimum_coverage(95) end end require 'oauth2' require 'addressable/uri' require 'rspec' RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect end end Faraday.default_adapter = :test RSpec.configure do |conf| include OAuth2 end def capture_output begin old_stdout = $stdout $stdout = StringIO.new yield result = $stdout.string ensure $stdout = old_stdout end result end VERBS = [:get, :post, :put, :delete].freeze oauth2-1.4.1/spec/oauth2/000077500000000000000000000000001336033110500150465ustar00rootroot00000000000000oauth2-1.4.1/spec/oauth2/access_token_spec.rb000066400000000000000000000145171336033110500210560ustar00rootroot00000000000000require 'helper' describe AccessToken do subject { described_class.new(client, token) } let(:token) { 'monkey' } let(:refresh_body) { MultiJson.encode(:access_token => 'refreshed_foo', :expires_in => 600, :refresh_token => 'refresh_bar') } let(:client) do Client.new('abc', 'def', :site => 'https://api.example.com') do |builder| builder.request :url_encoded builder.adapter :test do |stub| VERBS.each do |verb| stub.send(verb, '/token/header') { |env| [200, {}, env[:request_headers]['Authorization']] } stub.send(verb, "/token/query?access_token=#{token}") { |env| [200, {}, Addressable::URI.parse(env[:url]).query_values['access_token']] } stub.send(verb, '/token/body') { |env| [200, {}, env[:body]] } end stub.post('/oauth/token') { |env| [200, {'Content-Type' => 'application/json'}, refresh_body] } end end end describe '#initialize' do it 'assigns client and token' do expect(subject.client).to eq(client) expect(subject.token).to eq(token) end it 'assigns extra params' do target = described_class.new(client, token, 'foo' => 'bar') expect(target.params).to include('foo') expect(target.params['foo']).to eq('bar') end def assert_initialized_token(target) # rubocop:disable Metrics/AbcSize expect(target.token).to eq(token) expect(target).to be_expires expect(target.params.keys).to include('foo') expect(target.params['foo']).to eq('bar') end it 'initializes with a Hash' do hash = {:access_token => token, :expires_at => Time.now.to_i + 200, 'foo' => 'bar'} target = described_class.from_hash(client, hash) assert_initialized_token(target) end it 'from_hash does not modify opts hash' do hash = {:access_token => token, :expires_at => Time.now.to_i} hash_before = hash.dup described_class.from_hash(client, hash) expect(hash).to eq(hash_before) end it 'initalizes with a form-urlencoded key/value string' do kvform = "access_token=#{token}&expires_at=#{Time.now.to_i + 200}&foo=bar" target = described_class.from_kvform(client, kvform) assert_initialized_token(target) end it 'sets options' do target = described_class.new(client, token, :param_name => 'foo', :header_format => 'Bearer %', :mode => :body) expect(target.options[:param_name]).to eq('foo') expect(target.options[:header_format]).to eq('Bearer %') expect(target.options[:mode]).to eq(:body) end it 'does not modify opts hash' do opts = {:param_name => 'foo', :header_format => 'Bearer %', :mode => :body} opts_before = opts.dup described_class.new(client, token, opts) expect(opts).to eq(opts_before) end it 'initializes with a string expires_at' do hash = {:access_token => token, :expires_at => '1361396829', 'foo' => 'bar'} target = described_class.from_hash(client, hash) assert_initialized_token(target) expect(target.expires_at).to be_a(Integer) end end describe '#request' do context 'with :mode => :header' do before do subject.options[:mode] = :header end VERBS.each do |verb| it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do expect(subject.post('/token/header').body).to include(token) end end end context 'with :mode => :query' do before do subject.options[:mode] = :query end VERBS.each do |verb| it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do expect(subject.post('/token/query').body).to eq(token) end end end context 'with :mode => :body' do before do subject.options[:mode] = :body end VERBS.each do |verb| it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do expect(subject.post('/token/body').body.split('=').last).to eq(token) end end end end describe '#expires?' do it 'is false if there is no expires_at' do expect(described_class.new(client, token)).not_to be_expires end it 'is true if there is an expires_in' do expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 600)).to be_expires end it 'is true if there is an expires_at' do expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => Time.now.getutc.to_i + 600)).to be_expires end end describe '#expired?' do it 'is false if there is no expires_in or expires_at' do expect(described_class.new(client, token)).not_to be_expired end it 'is false if expires_in is in the future' do expect(described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 10_800)).not_to be_expired end it 'is true if expires_at is in the past' do access = described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 600) @now = Time.now + 10_800 allow(Time).to receive(:now).and_return(@now) expect(access).to be_expired end end describe '#refresh!' do let(:access) do described_class.new(client, token, :refresh_token => 'abaca', :expires_in => 600, :param_name => 'o_param') end it 'returns a refresh token with appropriate values carried over' do refreshed = access.refresh! expect(access.client).to eq(refreshed.client) expect(access.options[:param_name]).to eq(refreshed.options[:param_name]) end context 'with a nil refresh_token in the response' do let(:refresh_body) { MultiJson.encode(:access_token => 'refreshed_foo', :expires_in => 600, :refresh_token => nil) } it 'copies the refresh_token from the original token' do refreshed = access.refresh! expect(refreshed.refresh_token).to eq(access.refresh_token) end end end describe '#to_hash' do it 'return a hash equals to the hash used to initialize access token' do hash = {:access_token => token, :refresh_token => 'foobar', :expires_at => Time.now.to_i + 200, 'foo' => 'bar'} access_token = described_class.from_hash(client, hash.clone) expect(access_token.to_hash).to eq(hash) end end end oauth2-1.4.1/spec/oauth2/authenticator_spec.rb000066400000000000000000000040751336033110500212650ustar00rootroot00000000000000require 'helper' describe OAuth2::Authenticator do subject do described_class.new(client_id, client_secret, mode) end let(:client_id) { 'foo' } let(:client_secret) { 'bar' } let(:mode) { :undefined } it 'raises NotImplementedError for unknown authentication mode' do expect { subject.apply({}) }.to raise_error(NotImplementedError) end describe '#apply' do context 'with parameter-based authentication' do let(:mode) { :request_body } it 'adds client_id and client_secret to params' do output = subject.apply({}) expect(output).to eq('client_id' => 'foo', 'client_secret' => 'bar') end it 'does not overwrite existing credentials' do input = {'client_secret' => 's3cr3t'} output = subject.apply(input) expect(output).to eq('client_id' => 'foo', 'client_secret' => 's3cr3t') end it 'preserves other parameters' do input = {'state' => '42', :headers => {'A' => 'b'}} output = subject.apply(input) expect(output).to eq( 'client_id' => 'foo', 'client_secret' => 'bar', 'state' => '42', :headers => {'A' => 'b'} ) end end context 'with Basic authentication' do let(:mode) { :basic_auth } let(:header) { 'Basic ' + Base64.encode64("#{client_id}:#{client_secret}").delete("\n") } it 'encodes credentials in headers' do output = subject.apply({}) expect(output).to eq(:headers => {'Authorization' => header}) end it 'does not overwrite existing credentials' do input = {:headers => {'Authorization' => 'Bearer abc123'}} output = subject.apply(input) expect(output).to eq(:headers => {'Authorization' => 'Bearer abc123'}) end it 'does not overwrite existing params or headers' do input = {'state' => '42', :headers => {'A' => 'b'}} output = subject.apply(input) expect(output).to eq( 'state' => '42', :headers => {'A' => 'b', 'Authorization' => header} ) end end end end oauth2-1.4.1/spec/oauth2/client_spec.rb000066400000000000000000000300761336033110500176710ustar00rootroot00000000000000# coding: utf-8 require 'helper' require 'nkf' describe OAuth2::Client do subject do described_class.new('abc', 'def', :site => 'https://api.example.com') do |builder| builder.adapter :test do |stub| stub.get('/success') { |env| [200, {'Content-Type' => 'text/awesome'}, 'yay'] } stub.get('/reflect') { |env| [200, {}, env[:body]] } stub.post('/reflect') { |env| [200, {}, env[:body]] } stub.get('/unauthorized') { |env| [401, {'Content-Type' => 'application/json'}, MultiJson.encode(:error => error_value, :error_description => error_description_value)] } stub.get('/conflict') { |env| [409, {'Content-Type' => 'text/plain'}, 'not authorized'] } stub.get('/redirect') { |env| [302, {'Content-Type' => 'text/plain', 'location' => '/success'}, ''] } stub.post('/redirect') { |env| [303, {'Content-Type' => 'text/plain', 'location' => '/reflect'}, ''] } stub.get('/error') { |env| [500, {'Content-Type' => 'text/plain'}, 'unknown error'] } stub.get('/empty_get') { |env| [204, {}, nil] } stub.get('/different_encoding') { |env| [500, {'Content-Type' => 'application/json'}, NKF.nkf('-We', MultiJson.encode(:error => error_value, :error_description => '∞'))] } stub.get('/ascii_8bit_encoding') { |env| [500, {'Content-Type' => 'application/json'}, MultiJson.encode(:error => 'invalid_request', :error_description => 'é').force_encoding('ASCII-8BIT')] } end end end let!(:error_value) { 'invalid_token' } let!(:error_description_value) { 'bad bad token' } describe '#initialize' do it 'assigns id and secret' do expect(subject.id).to eq('abc') expect(subject.secret).to eq('def') end it 'assigns site from the options hash' do expect(subject.site).to eq('https://api.example.com') end it 'assigns Faraday::Connection#host' do expect(subject.connection.host).to eq('api.example.com') end it 'leaves Faraday::Connection#ssl unset' do expect(subject.connection.ssl).to be_empty end it 'is able to pass a block to configure the connection' do connection = double('connection') builder = double('builder') allow(connection).to receive(:build).and_yield(builder) allow(Faraday::Connection).to receive(:new).and_return(connection) expect(builder).to receive(:adapter).with(:test) described_class.new('abc', 'def') do |client| client.adapter :test end.connection end it 'defaults raise_errors to true' do expect(subject.options[:raise_errors]).to be true end it 'allows true/false for raise_errors option' do client = described_class.new('abc', 'def', :site => 'https://api.example.com', :raise_errors => false) expect(client.options[:raise_errors]).to be false client = described_class.new('abc', 'def', :site => 'https://api.example.com', :raise_errors => true) expect(client.options[:raise_errors]).to be true end it 'allows override of raise_errors option' do client = described_class.new('abc', 'def', :site => 'https://api.example.com', :raise_errors => true) do |builder| builder.adapter :test do |stub| stub.get('/notfound') { |env| [404, {}, nil] } end end expect(client.options[:raise_errors]).to be true expect { client.request(:get, '/notfound') }.to raise_error(OAuth2::Error) response = client.request(:get, '/notfound', :raise_errors => false) expect(response.status).to eq(404) end it 'allows get/post for access_token_method option' do client = described_class.new('abc', 'def', :site => 'https://api.example.com', :access_token_method => :get) expect(client.options[:access_token_method]).to eq(:get) client = described_class.new('abc', 'def', :site => 'https://api.example.com', :access_token_method => :post) expect(client.options[:access_token_method]).to eq(:post) end it 'does not mutate the opts hash argument' do opts = {:site => 'http://example.com/'} opts2 = opts.dup described_class.new 'abc', 'def', opts expect(opts).to eq(opts2) end end %w[authorize token].each do |url_type| describe ":#{url_type}_url option" do it "defaults to a path of /oauth/#{url_type}" do expect(subject.send("#{url_type}_url")).to eq("https://api.example.com/oauth/#{url_type}") end it "is settable via the :#{url_type}_url option" do subject.options[:"#{url_type}_url"] = '/oauth/custom' expect(subject.send("#{url_type}_url")).to eq('https://api.example.com/oauth/custom') end it 'allows a different host than the site' do subject.options[:"#{url_type}_url"] = 'https://api.foo.com/oauth/custom' expect(subject.send("#{url_type}_url")).to eq('https://api.foo.com/oauth/custom') end end end describe ':redirect_uri option' do let(:auth_code_params) do { 'client_id' => 'abc', 'client_secret' => 'def', 'code' => 'code', 'grant_type' => 'authorization_code', } end context 'when blank' do it 'there is no redirect_uri param added to authorization URL' do expect(subject.authorize_url('a' => 'b')).to eq('https://api.example.com/oauth/authorize?a=b') end it 'does not add the redirect_uri param to the auth_code token exchange request' do client = described_class.new('abc', 'def', :site => 'https://api.example.com') do |builder| builder.adapter :test do |stub| stub.post('/oauth/token', auth_code_params) do [200, {'Content-Type' => 'application/json'}, '{"access_token":"token"}'] end end end client.auth_code.get_token('code') end end context 'when set' do before { subject.options[:redirect_uri] = 'https://site.com/oauth/callback' } it 'adds the redirect_uri param to authorization URL' do expect(subject.authorize_url('a' => 'b')).to eq('https://api.example.com/oauth/authorize?a=b&redirect_uri=https%3A%2F%2Fsite.com%2Foauth%2Fcallback') end it 'adds the redirect_uri param to the auth_code token exchange request' do client = described_class.new('abc', 'def', :redirect_uri => 'https://site.com/oauth/callback', :site => 'https://api.example.com') do |builder| builder.adapter :test do |stub| stub.post('/oauth/token', auth_code_params.merge('redirect_uri' => 'https://site.com/oauth/callback')) do [200, {'Content-Type' => 'application/json'}, '{"access_token":"token"}'] end end end client.auth_code.get_token('code') end end end describe '#request' do it 'works with a null response body' do expect(subject.request(:get, 'empty_get').body).to eq('') end it 'returns on a successful response' do response = subject.request(:get, '/success') expect(response.body).to eq('yay') expect(response.status).to eq(200) expect(response.headers).to eq('Content-Type' => 'text/awesome') end it 'outputs to $stdout when OAUTH_DEBUG=true' do allow(ENV).to receive(:[]).with('http_proxy').and_return(nil) allow(ENV).to receive(:[]).with('OAUTH_DEBUG').and_return('true') output = capture_output do subject.request(:get, '/success') end expect(output).to include 'INFO -- : get https://api.example.com/success', 'INFO -- : get https://api.example.com/success' end it 'posts a body' do response = subject.request(:post, '/reflect', :body => 'foo=bar') expect(response.body).to eq('foo=bar') end it 'follows redirects properly' do response = subject.request(:get, '/redirect') expect(response.body).to eq('yay') expect(response.status).to eq(200) expect(response.headers).to eq('Content-Type' => 'text/awesome') end it 'redirects using GET on a 303' do response = subject.request(:post, '/redirect', :body => 'foo=bar') expect(response.body).to be_empty expect(response.status).to eq(200) end it 'obeys the :max_redirects option' do max_redirects = subject.options[:max_redirects] subject.options[:max_redirects] = 0 response = subject.request(:get, '/redirect') expect(response.status).to eq(302) subject.options[:max_redirects] = max_redirects end it 'returns if raise_errors is false' do subject.options[:raise_errors] = false response = subject.request(:get, '/unauthorized') expect(response.status).to eq(401) expect(response.headers).to eq('Content-Type' => 'application/json') expect(response.error).not_to be_nil end %w[/unauthorized /conflict /error /different_encoding /ascii_8bit_encoding].each do |error_path| it "raises OAuth2::Error on error response to path #{error_path}" do expect { subject.request(:get, error_path) }.to raise_error(OAuth2::Error) end end it 're-encodes response body in the error message' do begin subject.request(:get, '/ascii_8bit_encoding') rescue StandardError => ex expect(ex.message.encoding.name).to eq('UTF-8') expect(ex.message).to eq("invalid_request: é\n{\"error\":\"invalid_request\",\"error_description\":\"��\"}") end end it 'parses OAuth2 standard error response' do begin subject.request(:get, '/unauthorized') rescue StandardError => e expect(e.code).to eq(error_value) expect(e.description).to eq(error_description_value) expect(e.to_s).to match(/#{error_value}/) expect(e.to_s).to match(/#{error_description_value}/) end end it 'provides the response in the Exception' do begin subject.request(:get, '/error') rescue StandardError => e expect(e.response).not_to be_nil expect(e.to_s).to match(/unknown error/) end end end describe '#get_token' do it 'returns a configured AccessToken' do client = stubbed_client do |stub| stub.post('/oauth/token') do [200, {'Content-Type' => 'application/json'}, MultiJson.encode('access_token' => 'the-token')] end end token = client.get_token({}) expect(token).to be_a OAuth2::AccessToken expect(token.token).to eq('the-token') end it 'authenticates with request parameters' do client = stubbed_client(:auth_scheme => :request_body) do |stub| stub.post('/oauth/token', 'client_id' => 'abc', 'client_secret' => 'def') do |env| [200, {'Content-Type' => 'application/json'}, MultiJson.encode('access_token' => 'the-token')] end end client.get_token({}) end it 'authenticates with Basic auth' do client = stubbed_client(:auth_scheme => :basic_auth) do |stub| stub.post('/oauth/token') do |env| raise Faraday::Adapter::Test::Stubs::NotFound unless env[:request_headers]['Authorization'] == OAuth2::Authenticator.encode_basic_auth('abc', 'def') [200, {'Content-Type' => 'application/json'}, MultiJson.encode('access_token' => 'the-token')] end end client.get_token({}) end def stubbed_client(params = {}, &stubs) params = {:site => 'https://api.example.com'}.merge(params) OAuth2::Client.new('abc', 'def', params) do |builder| builder.adapter :test, &stubs end end end it 'instantiates an AuthCode strategy with this client' do expect(subject.auth_code).to be_kind_of(OAuth2::Strategy::AuthCode) end it 'instantiates an Implicit strategy with this client' do expect(subject.implicit).to be_kind_of(OAuth2::Strategy::Implicit) end context 'with SSL options' do subject do cli = described_class.new('abc', 'def', :site => 'https://api.example.com', :ssl => {:ca_file => 'foo.pem'}) cli.connection.build do |b| b.adapter :test end cli end it 'passes the SSL options along to Faraday::Connection#ssl' do expect(subject.connection.ssl.fetch(:ca_file)).to eq('foo.pem') end end end oauth2-1.4.1/spec/oauth2/mac_token_spec.rb000066400000000000000000000070111336033110500203440ustar00rootroot00000000000000require 'helper' describe MACToken do subject { described_class.new(client, token, 'abc123') } let(:token) { 'monkey' } let(:client) do Client.new('abc', 'def', :site => 'https://api.example.com') do |builder| builder.request :url_encoded builder.adapter :test do |stub| VERBS.each do |verb| stub.send(verb, '/token/header') { |env| [200, {}, env[:request_headers]['Authorization']] } end end end end describe '#initialize' do it 'assigns client and token' do expect(subject.client).to eq(client) expect(subject.token).to eq(token) end it 'assigns secret' do expect(subject.secret).to eq('abc123') end it 'defaults algorithm to hmac-sha-256' do expect(subject.algorithm).to be_instance_of(OpenSSL::Digest::SHA256) end it 'handles hmac-sha-256' do mac = described_class.new(client, token, 'abc123', :algorithm => 'hmac-sha-256') expect(mac.algorithm).to be_instance_of(OpenSSL::Digest::SHA256) end it 'handles hmac-sha-1' do mac = described_class.new(client, token, 'abc123', :algorithm => 'hmac-sha-1') expect(mac.algorithm).to be_instance_of(OpenSSL::Digest::SHA1) end it 'raises on improper algorithm' do expect { described_class.new(client, token, 'abc123', :algorithm => 'invalid-sha') }.to raise_error(ArgumentError) end end describe '#request' do VERBS.each do |verb| it "sends the token in the Authorization header for a #{verb.to_s.upcase} request" do expect(subject.post('/token/header').body).to include("MAC id=\"#{token}\"") end end end describe '#header' do it 'does not generate the same header twice' do header = subject.header('get', 'https://www.example.com/hello') duplicate_header = subject.header('get', 'https://www.example.com/hello') expect(header).not_to eq(duplicate_header) end it 'generates the proper format' do header = subject.header('get', 'https://www.example.com/hello?a=1') expect(header).to match(/MAC id="#{token}", ts="[0-9]+", nonce="[^"]+", mac="[^"]+"/) end it 'passes ArgumentError with an invalid url' do expect { subject.header('get', 'this-is-not-valid') }.to raise_error(ArgumentError) end it 'passes URI::InvalidURIError through' do expect { subject.header('get', nil) }.to raise_error(URI::InvalidURIError) end end describe '#signature' do it 'generates properly' do signature = subject.signature(0, 'random-string', 'get', URI('https://www.google.com')) expect(signature).to eq('rMDjVA3VJj3v1OmxM29QQljKia6msl5rjN83x3bZmi8=') end end describe '#headers' do it 'is an empty hash' do expect(subject.headers).to eq({}) end end describe '.from_access_token' do subject { described_class.from_access_token(access_token, 'hello') } let(:access_token) do AccessToken.new( client, token, :expires_at => 1, :expires_in => 1, :refresh_token => 'abc', :random => 1 ) end it 'initializes client, token, and secret properly' do expect(subject.client).to eq(client) expect(subject.token).to eq(token) expect(subject.secret).to eq('hello') end it 'initializes configuration options' do expect(subject.expires_at).to eq(1) expect(subject.expires_in).to eq(1) expect(subject.refresh_token).to eq('abc') end it 'initializes params' do expect(subject.params).to eq(:random => 1) end end end oauth2-1.4.1/spec/oauth2/response_spec.rb000066400000000000000000000062321336033110500202460ustar00rootroot00000000000000require 'helper' describe OAuth2::Response do describe '#initialize' do let(:status) { 200 } let(:headers) { {'foo' => 'bar'} } let(:body) { 'foo' } it 'returns the status, headers and body' do response = double('response', :headers => headers, :status => status, :body => body) subject = Response.new(response) expect(subject.headers).to eq(headers) expect(subject.status).to eq(status) expect(subject.body).to eq(body) end end describe '.register_parser' do let(:response) do double('response', :headers => {'Content-Type' => 'application/foo-bar'}, :status => 200, :body => 'baz') end before do described_class.register_parser(:foobar, 'application/foo-bar') do |body| "foobar #{body}" end end it 'adds to the content types and parsers' do expect(described_class.send(:class_variable_get, :@@parsers).keys).to include(:foobar) expect(described_class.send(:class_variable_get, :@@content_types).keys).to include('application/foo-bar') end it 'is able to parse that content type automatically' do expect(described_class.new(response).parsed).to eq('foobar baz') end end describe '#parsed' do it 'parses application/x-www-form-urlencoded body' do headers = {'Content-Type' => 'application/x-www-form-urlencoded'} body = 'foo=bar&answer=42' response = double('response', :headers => headers, :body => body) subject = Response.new(response) expect(subject.parsed.keys.size).to eq(2) expect(subject.parsed['foo']).to eq('bar') expect(subject.parsed['answer']).to eq('42') end it 'parses application/json body' do headers = {'Content-Type' => 'application/json'} body = MultiJson.encode(:foo => 'bar', :answer => 42) response = double('response', :headers => headers, :body => body) subject = Response.new(response) expect(subject.parsed.keys.size).to eq(2) expect(subject.parsed['foo']).to eq('bar') expect(subject.parsed['answer']).to eq(42) end it "doesn't try to parse other content-types" do headers = {'Content-Type' => 'text/html'} body = '' response = double('response', :headers => headers, :body => body) expect(MultiJson).not_to receive(:decode) expect(MultiJson).not_to receive(:load) expect(Rack::Utils).not_to receive(:parse_query) subject = Response.new(response) expect(subject.parsed).to be_nil end end context 'with xml parser registration' do it 'tries to load multi_xml and use it' do expect(described_class.send(:class_variable_get, :@@parsers)[:xml]).not_to be_nil end it 'is able to parse xml' do headers = {'Content-Type' => 'text/xml'} body = 'baz' response = double('response', :headers => headers, :body => body) expect(described_class.new(response).parsed).to eq('foo' => {'bar' => 'baz'}) end end end oauth2-1.4.1/spec/oauth2/strategy/000077500000000000000000000000001336033110500167105ustar00rootroot00000000000000oauth2-1.4.1/spec/oauth2/strategy/assertion_spec.rb000066400000000000000000000027401336033110500222610ustar00rootroot00000000000000require 'helper' describe OAuth2::Strategy::Assertion do subject { client.assertion } let(:client) do cli = OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') cli.connection.build do |b| b.adapter :test do |stub| stub.post('/oauth/token') do |env| case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, 'expires_in=600&access_token=salmon&refresh_token=trout'] when 'json' [200, {'Content-Type' => 'application/json'}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}'] end end end end cli end let(:params) { {:hmac_secret => 'foo'} } describe '#authorize_url' do it 'raises NotImplementedError' do expect { subject.authorize_url }.to raise_error(NotImplementedError) end end %w[json formencoded].each do |mode| describe "#get_token (#{mode})" do before do @mode = mode @access = subject.get_token(params) end it 'returns AccessToken with same Client' do expect(@access.client).to eq(client) end it 'returns AccessToken with #token' do expect(@access.token).to eq('salmon') end it 'returns AccessToken with #expires_in' do expect(@access.expires_in).to eq(600) end it 'returns AccessToken with #expires_at' do expect(@access.expires_at).not_to be_nil end end end end oauth2-1.4.1/spec/oauth2/strategy/auth_code_spec.rb000066400000000000000000000071041336033110500222040ustar00rootroot00000000000000# encoding: utf-8 require 'helper' describe OAuth2::Strategy::AuthCode do subject { client.auth_code } let(:code) { 'sushi' } let(:kvform_token) { 'expires_in=600&access_token=salmon&refresh_token=trout&extra_param=steve' } let(:facebook_token) { kvform_token.gsub('_in', '') } let(:json_token) { MultiJson.encode(:expires_in => 600, :access_token => 'salmon', :refresh_token => 'trout', :extra_param => 'steve') } let(:client) do OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') do |builder| builder.adapter :test do |stub| stub.get("/oauth/token?client_id=abc&client_secret=def&code=#{code}&grant_type=authorization_code") do |env| case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token] when 'json' [200, {'Content-Type' => 'application/json'}, json_token] when 'from_facebook' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, facebook_token] end end stub.post('/oauth/token', 'client_id' => 'abc', 'client_secret' => 'def', 'code' => 'sushi', 'grant_type' => 'authorization_code') do |env| case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token] when 'json' [200, {'Content-Type' => 'application/json'}, json_token] when 'from_facebook' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, facebook_token] end end end end end describe '#authorize_url' do it 'includes the client_id' do expect(subject.authorize_url).to include('client_id=abc') end it 'includes the type' do expect(subject.authorize_url).to include('response_type=code') end it 'includes passed in options' do cb = 'http://myserver.local/oauth/callback' expect(subject.authorize_url(:redirect_uri => cb)).to include("redirect_uri=#{Rack::Utils.escape(cb)}") end end describe '#get_token (handling utf-8 data)' do let(:json_token) { MultiJson.encode(:expires_in => 600, :access_token => 'salmon', :refresh_token => 'trout', :extra_param => 'André') } before do @mode = 'json' client.options[:token_method] = :post end it 'does not raise an error' do expect { subject.get_token(code) }.not_to raise_error end it 'does not create an error instance' do expect(OAuth2::Error).not_to receive(:new) subject.get_token(code) end end %w[json formencoded from_facebook].each do |mode| [:get, :post].each do |verb| describe "#get_token (#{mode}, access_token_method=#{verb}" do before do @mode = mode client.options[:token_method] = verb @access = subject.get_token(code) end it 'returns AccessToken with same Client' do expect(@access.client).to eq(client) end it 'returns AccessToken with #token' do expect(@access.token).to eq('salmon') end it 'returns AccessToken with #refresh_token' do expect(@access.refresh_token).to eq('trout') end it 'returns AccessToken with #expires_in' do expect(@access.expires_in).to eq(600) end it 'returns AccessToken with #expires_at' do expect(@access.expires_at).to be_kind_of(Integer) end it 'returns AccessToken with params accessible via []' do expect(@access['extra_param']).to eq('steve') end end end end end oauth2-1.4.1/spec/oauth2/strategy/base_spec.rb000066400000000000000000000002731336033110500211630ustar00rootroot00000000000000require 'helper' describe OAuth2::Strategy::Base do it 'initializes with a Client' do expect { described_class.new(OAuth2::Client.new('abc', 'def')) }.not_to raise_error end end oauth2-1.4.1/spec/oauth2/strategy/client_credentials_spec.rb000066400000000000000000000046331336033110500241100ustar00rootroot00000000000000require 'helper' describe OAuth2::Strategy::ClientCredentials do subject { client.client_credentials } let(:kvform_token) { 'expires_in=600&access_token=salmon&refresh_token=trout' } let(:json_token) { '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}' } let(:client) do OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') do |builder| builder.adapter :test do |stub| stub.post('/oauth/token', 'grant_type' => 'client_credentials') do |env| client_id, client_secret = Base64.decode64(env[:request_headers]['Authorization'].split(' ', 2)[1]).split(':', 2) client_id == 'abc' && client_secret == 'def' || raise(Faraday::Adapter::Test::Stubs::NotFound) case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token] when 'json' [200, {'Content-Type' => 'application/json'}, json_token] end end stub.post('/oauth/token', 'client_id' => 'abc', 'client_secret' => 'def', 'grant_type' => 'client_credentials') do |env| case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, kvform_token] when 'json' [200, {'Content-Type' => 'application/json'}, json_token] end end end end end describe '#authorize_url' do it 'raises NotImplementedError' do expect { subject.authorize_url }.to raise_error(NotImplementedError) end end %w[json formencoded].each do |mode| [:basic_auth, :request_body].each do |auth_scheme| describe "#get_token (#{mode}) (#{auth_scheme})" do before do @mode = mode client.options[:auth_scheme] = auth_scheme @access = subject.get_token end it 'returns AccessToken with same Client' do expect(@access.client).to eq(client) end it 'returns AccessToken with #token' do expect(@access.token).to eq('salmon') end it 'returns AccessToken without #refresh_token' do expect(@access.refresh_token).to be_nil end it 'returns AccessToken with #expires_in' do expect(@access.expires_in).to eq(600) end it 'returns AccessToken with #expires_at' do expect(@access.expires_at).not_to be_nil end end end end end oauth2-1.4.1/spec/oauth2/strategy/implicit_spec.rb000066400000000000000000000014311336033110500220600ustar00rootroot00000000000000require 'helper' describe OAuth2::Strategy::Implicit do subject { client.implicit } let(:client) { OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') } describe '#authorize_url' do it 'includes the client_id' do expect(subject.authorize_url).to include('client_id=abc') end it 'includes the type' do expect(subject.authorize_url).to include('response_type=token') end it 'includes passed in options' do cb = 'http://myserver.local/oauth/callback' expect(subject.authorize_url(:redirect_uri => cb)).to include("redirect_uri=#{Rack::Utils.escape(cb)}") end end describe '#get_token' do it 'raises NotImplementedError' do expect { subject.get_token }.to raise_error(NotImplementedError) end end end oauth2-1.4.1/spec/oauth2/strategy/password_spec.rb000066400000000000000000000030701336033110500221110ustar00rootroot00000000000000require 'helper' describe OAuth2::Strategy::Password do subject { client.password } let(:client) do cli = OAuth2::Client.new('abc', 'def', :site => 'http://api.example.com') cli.connection.build do |b| b.adapter :test do |stub| stub.post('/oauth/token') do |env| case @mode when 'formencoded' [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, 'expires_in=600&access_token=salmon&refresh_token=trout'] when 'json' [200, {'Content-Type' => 'application/json'}, '{"expires_in":600,"access_token":"salmon","refresh_token":"trout"}'] end end end end cli end describe '#authorize_url' do it 'raises NotImplementedError' do expect { subject.authorize_url }.to raise_error(NotImplementedError) end end %w[json formencoded].each do |mode| describe "#get_token (#{mode})" do before do @mode = mode @access = subject.get_token('username', 'password') end it 'returns AccessToken with same Client' do expect(@access.client).to eq(client) end it 'returns AccessToken with #token' do expect(@access.token).to eq('salmon') end it 'returns AccessToken with #refresh_token' do expect(@access.refresh_token).to eq('trout') end it 'returns AccessToken with #expires_in' do expect(@access.expires_in).to eq(600) end it 'returns AccessToken with #expires_at' do expect(@access.expires_at).not_to be_nil end end end end