├── .codeclimate.yml
├── .github
└── workflows
│ └── ruby.yml
├── .gitignore
├── .simplecov
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── VERSION.txt
├── faraday_middleware-oauth2_refresh.gemspec
├── lib
├── faraday_middleware-oauth2_refresh.rb
└── faraday_middleware
│ └── oauth2_refresh.rb
└── test
└── test_setup.rb
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | # Save as .codeclimate.yml (note leading .) in project root directory
2 | languages:
3 | Ruby: true
4 | JavaScript: false
5 | PHP: false
6 | Python: false
7 | # exclude_paths:
8 | # - "foo/bar.rb"
--------------------------------------------------------------------------------
/.github/workflows/ruby.yml:
--------------------------------------------------------------------------------
1 | name: ruby build
2 | on:
3 | push:
4 | branches:
5 | - master
6 | pull_request:
7 | branches:
8 | - master
9 | workflow_dispatch:
10 | jobs:
11 | test:
12 | runs-on: ubuntu-latest
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | ruby: ['2.5', '2.6', '2.7', 'jruby-head', 'ruby-head']
17 | gemfile: ['Gemfile']
18 | exclude:
19 | - ruby: 2.7
20 | gemfile: activesupport-4.2.x
21 | - ruby: ruby-head
22 | gemfile: activesupport-4.2.x
23 | - ruby: jruby-head
24 | gemfile: activesupport-4.2.x
25 | env:
26 | BUNDLE_GEMFILE: ${{ matrix.gemfile }}
27 | name: Ruby ${{ matrix.ruby }} with ${{ matrix.gemfile }}
28 | steps:
29 | - uses: actions/checkout@v3
30 | - name: Set up Ruby
31 | uses: ruby/setup-ruby@v1
32 | with:
33 | ruby-version: ${{ matrix.ruby }}
34 | bundler-cache: true
35 | - name: Run tests
36 | run: bundle exec rake
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Gemfile.lock
2 | *.gem
3 | coverage
4 |
5 |
--------------------------------------------------------------------------------
/.simplecov:
--------------------------------------------------------------------------------
1 | require 'coveralls'
2 |
3 | SimpleCov.formatter = Coveralls::SimpleCov::Formatter
4 | SimpleCov.start do
5 | add_filter "/test/"
6 | end
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | CHANGELOG
2 | ---------
3 | - **2016-11-21**: 0.0.4
4 | - Add VersionEye reference tracking
5 | - **2016-08-23**: 0.0.3
6 | - Update dependencies
7 | - **2015-05-31**: 0.0.2
8 | - Update dependencies
9 | - **2015-05-31**: 0.0.1
10 | - Initial release
11 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | nationality, personal appearance, race, religion, or sexual identity and
10 | orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at johncwang@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at [http://contributor-covenant.org/version/1/4][version]
72 |
73 | [homepage]: http://contributor-covenant.org
74 | [version]: http://contributor-covenant.org/version/1/4/
75 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | gemspec
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015-2025 John Wang
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FaradayMiddleware::OAuth2Refresh
2 |
3 |
4 |
5 | [![Gem Version][gem-version-svg]][gem-version-url]
6 | [![Build Status][build-status-svg]][build-status-url]
7 | [![Coverage Status][coverage-status-svg]][coverage-status-url]
8 |
9 |
10 |
11 |
12 | [![Code Climate][codeclimate-status-svg]][codeclimate-status-url]
13 | [![Scrutinizer Code Quality][scrutinizer-status-svg]][scrutinizer-status-url]
14 |
15 |
16 |
17 |
18 | [![Docs][docs-rubydoc-svg]][docs-rubydoc-url]
19 | [![License][license-svg]][license-url]
20 |
21 |
22 |
23 | Faraday middleware to manage OAuth token authorization with token refresh.
24 |
25 | ## Description
26 |
27 | This gem is a piece of Faraday middleware that adds OAuth token handling using the [oauth2 gem](https://gitlab.com/oauth-xx/oauth2/).
28 |
29 | ## Installation
30 |
31 | Add this line to your application's Gemfile:
32 |
33 | ```ruby
34 | gem 'faraday_middleware-oauth2_refresh'
35 | ```
36 |
37 | And then execute:
38 |
39 | ```sh
40 | $ bundle
41 | ```
42 |
43 | Or install it yourself as:
44 |
45 | ```sh
46 | $ gem install faraday_middleware-oauth2_refresh
47 | ```
48 |
49 | ## Usage
50 |
51 | ```ruby
52 | require 'oauth2'
53 | require 'faraday_middleware/oauth2_refresh'
54 |
55 | client = OAuth2::Client.new('my_client_id', 'my_client_secret', site: 'https://example.com' )
56 | token = client.password.get_token('username', 'password', { headers: { 'Authorization' => 'Basic my_api_key' } })
57 |
58 | conn = Faraday.new(url: "http://example.com") do |builder|
59 | builder.request :oauth2_refresh, token
60 | builder.adapter Faraday.default_adapter
61 | end
62 |
63 | conn.get "/foo" # sends token
64 | ```
65 |
66 | ## Change Log
67 |
68 | See [CHANGELOG.md](CHANGELOG.md)
69 |
70 | ## Links
71 |
72 | Project Repo
73 |
74 | * https://github.com/grokify/faraday_middleware-oauth2_refresh
75 |
76 | ## Problems, Comments, Suggestions, Contributions?
77 |
78 | Any reports of problems, comments or suggestions are most welcome.
79 |
80 | Please report these on [Github](https://github.com/grokify/faraday_middleware-oauth2_refresh)
81 |
82 | ## License
83 |
84 | `FaradayMiddleware::OAuth2Refresh` is available under an MIT-style license. See {file:LICENSE.md} for details.
85 |
86 | `FaradayMiddleware::OAuth2Refresh` © 2015-2023 by John Wang
87 |
88 | [gem-version-svg]: https://badge.fury.io/rb/faraday_middleware-oauth2_refresh.svg
89 | [gem-version-url]: http://badge.fury.io/rb/faraday_middleware-oauth2_refresh
90 | [downloads-svg]: http://ruby-gem-downloads-badge.herokuapp.com/faraday_middleware-oauth2_refresh
91 | [downloads-url]: https://rubygems.org/gems/faraday_middleware-oauth2_refresh
92 | [build-status-svg]: https://github.com/grokify/faraday_middleware-oauth2_refresh/workflows/ruby%20build/badge.svg?branch=master
93 | [build-status-url]: https://github.com/grokify/faraday_middleware-oauth2_refresh/actions
94 | [coverage-status-svg]: https://coveralls.io/repos/grokify/faraday_middleware-oauth2_refresh/badge.svg?branch=master
95 | [coverage-status-url]: https://coveralls.io/r/grokify/faraday_middleware-oauth2_refresh?branch=master
96 | [dependency-status-svg]: https://gemnasium.com/grokify/faraday_middleware-oauth2_refresh.svg
97 | [dependency-status-url]: https://gemnasium.com/grokify/faraday_middleware-oauth2_refresh
98 | [codacy-svg]: https://api.codacy.com/project/badge/Grade/88aedf52809d460891546fc7e11bd2c6
99 | [codacy-url]: https://app.codacy.com/manual/grokify/faraday_middleware-oauth2_refresh/dashboard
100 | [codeclimate-status-svg]: https://codeclimate.com/github/grokify/faraday_middleware-oauth2_refresh/badges/gpa.svg
101 | [codeclimate-status-url]: https://codeclimate.com/github/grokify/faraday_middleware-oauth2_refresh
102 | [scrutinizer-status-svg]: https://scrutinizer-ci.com/g/grokify/faraday_middleware-oauth2_refresh/badges/quality-score.png?b=master
103 | [scrutinizer-status-url]: https://scrutinizer-ci.com/g/grokify/faraday_middleware-oauth2_refresh/?branch=master
104 | [references-svg]: https://www.versioneye.com/ruby/faraday_middleware-oauth2_refresh/reference_badge.svg
105 | [references-url]: https://www.versioneye.com/ruby/faraday_middleware-oauth2_refresh/
106 | [docs-rubydoc-svg]: https://img.shields.io/badge/docs-rubydoc-blue.svg
107 | [docs-rubydoc-url]: http://www.rubydoc.info/gems/faraday_middleware-oauth2_refresh/
108 | [license-svg]: https://img.shields.io/badge/license-MIT-blue.svg
109 | [license-url]: https://github.com/grokify/faraday_middleware-oauth2_refresh/blob/master/LICENSE.txt
110 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rake'
2 | require 'rake/testtask'
3 |
4 | desc 'Default: run unit tests.'
5 | task :default => :test
6 |
7 | desc 'Test the library.'
8 | Rake::TestTask.new do |t|
9 | t.libs << 'lib'
10 | t.pattern = 'test/**/test_*.rb'
11 | t.verbose = false
12 | end
13 |
14 | desc 'Generate YARD documentation.'
15 | task :gendoc do
16 | # puts 'yard doc generation disabled until JRuby build native extensions for redcarpet or yard removes the dependency.'
17 | system "yardoc"
18 | system "yard stats --list-undoc"
19 | end
--------------------------------------------------------------------------------
/VERSION.txt:
--------------------------------------------------------------------------------
1 | 0.1.0
--------------------------------------------------------------------------------
/faraday_middleware-oauth2_refresh.gemspec:
--------------------------------------------------------------------------------
1 | Gem::Specification.new do |s|
2 | s.name = 'faraday_middleware-oauth2_refresh'
3 | s.version = '0.1.3'
4 | s.date = '2023-02-14'
5 | s.summary = 'Faraday OAuth2 request middleware with token refresh'
6 | s.description = 'This Faraday middleware gem adds OAuth2 token handling with token refresh'
7 | s.authors = ['John Wang']
8 | s.email = 'johncwang@gmail.com'
9 | s.homepage = 'https://github.com/grokify/faraday_middleware-oauth2_refresh'
10 | s.licenses = ['MIT']
11 | s.files = [
12 | 'CHANGELOG.md',
13 | 'CODE_OF_CONDUCT.md',
14 | 'LICENSE.txt',
15 | 'README.md',
16 | 'Rakefile',
17 | 'VERSION.txt',
18 | 'lib/faraday_middleware-oauth2_refresh.rb',
19 | 'lib/faraday_middleware/oauth2_refresh.rb',
20 | 'test/test_setup.rb'
21 | ]
22 | s.required_ruby_version = '>= 2.0.0'
23 |
24 | s.add_dependency 'faraday', '~> 1.10', '>= 1.10.3'
25 | s.add_dependency 'faraday_middleware', '~> 1.2', '>= 1.2.0'
26 |
27 | s.add_development_dependency 'coveralls', '~> 0'
28 | s.add_development_dependency 'rake', '~> 13', '>= 13.0.6'
29 | s.add_development_dependency 'simplecov', '~> 0'
30 | s.add_development_dependency 'test-unit', '~> 3'
31 | end
32 |
--------------------------------------------------------------------------------
/lib/faraday_middleware-oauth2_refresh.rb:
--------------------------------------------------------------------------------
1 | require 'faraday_middleware/oauth2_refresh'
--------------------------------------------------------------------------------
/lib/faraday_middleware/oauth2_refresh.rb:
--------------------------------------------------------------------------------
1 | require 'base64'
2 | require 'faraday'
3 | require 'forwardable'
4 |
5 | module FaradayMiddleware
6 | class OAuth2Refresh < Faraday::Middleware
7 | AUTH_HEADER = 'Authorization'.freeze
8 |
9 | attr_reader :oauth2_token
10 |
11 | extend Forwardable
12 |
13 | def call(env)
14 | if @oauth2_token.expired?
15 | @oauth2_token = @oauth2_token.refresh!({ headers: { 'Authorization' => 'Basic ' + get_api_key() } })
16 | end
17 |
18 | unless @oauth2_token.token.to_s.empty?
19 | env[:request_headers][AUTH_HEADER] = %(Bearer #{@oauth2_token.token})
20 | end
21 |
22 | @app.call env
23 | end
24 |
25 | def get_api_key
26 | api_key = Base64.encode64("#{@oauth2_token.client.id}:#{@oauth2_token.client.secret}").gsub(/[\s]/,'')
27 | return api_key
28 | end
29 |
30 | def initialize(app = nil, token = nil)
31 | super app
32 | @oauth2_token = token
33 | end
34 |
35 | end
36 | end
37 |
38 | Faraday::Request.register_middleware oauth2_refresh: FaradayMiddleware::OAuth2Refresh
39 |
--------------------------------------------------------------------------------
/test/test_setup.rb:
--------------------------------------------------------------------------------
1 | require 'coveralls'
2 | Coveralls.wear!
3 |
4 | require 'test/unit'
5 | require 'faraday'
6 | require 'faraday_middleware'
7 | require 'faraday_middleware-oauth2_refresh'
8 |
9 | class OAuth2Test < Test::Unit::TestCase
10 | def test_setup
11 |
12 | Faraday.new 'http://example.com/api' do |conn|
13 | conn.request :oauth2_refresh
14 | end
15 |
16 | ref = FaradayMiddleware::OAuth2Refresh.new
17 |
18 | assert_equal 'FaradayMiddleware::OAuth2Refresh', ref.class.name
19 |
20 | end
21 | end
22 |
--------------------------------------------------------------------------------