oauth2 - A Ruby wrapper for the OAuth 2.0, & 2.1 Authorization Frameworks, including OpenID Connect (OIDC)
oauth2 - A Ruby wrapper for the OAuth 2.0, & 2.1 Authorization Frameworks, including OpenID Connect (OIDC)
[![Version][versioni]][version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][license-img]][license] [![Downloads Rank][dl-ranki]][dl-rank] [![CodeCov Test Coverage][codecovi]][codecov] [![Coveralls Test Coverage][coveralls-img]][coveralls] [![QLTY Test Coverage][qlty-covi]][qlty-cov] [![QLTY Maintainability][qlty-mnti]][qlty-mnt] [![CI Heads][3-hd-wfi]][3-hd-wf] [![CI Runtime Dependencies @ HEAD][12-crh-wfi]][12-crh-wf] [![CI Current][11-c-wfi]][11-c-wf] [![CI Truffle Ruby][9-t-wfi]][9-t-wf] [![CI JRuby][10-j-wfi]][10-j-wf] [![Deps Locked][13-️-wfi]][13-️-wf] [![Deps Unlocked][14-️-wfi]][14-️-wf] [![CI Test Coverage][2-cov-wfi]][2-cov-wf] [![CI Style][5-st-wfi]][5-st-wf] [![Apache SkyWalking Eyes License Compatibility Check][15--wfi]][15--wf]
if ci_badges.map(&:color).detect { it != "green"} ☝️ [let me know][✉️discord-invite], as I may have missed the [discord notification][✉️discord-invite].
if ci_badges.map(&:color).all? { it == "green"} ️ send money so I can do more of this. FLOSS maintenance is now my full-time job.
[![OpenCollective Backers][osc-backers-i]][osc-backers] [![OpenCollective Sponsors][osc-sponsors-i]][osc-sponsors] [![Sponsor Me on Github][sponsor-img]][sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][paypal-img]][paypal] [![Buy me a coffee][buyme-small-img]][buyme] [![Donate at ko-fi.com][kofi-img]][kofi]
How will this project approach the September 2025 hostile takeover of RubyGems? ️I've summarized my thoughts in this blog post.
OAuth 2.0 is the industry-standard protocol for authorization. This is a RubyGem for implementing OAuth 2.0 clients (not servers) in Ruby applications.
⭐️ including OAuth 2.1 draft spec & OpenID Connect (OIDC)
curl --request POST \
--url 'https://login.microsoftonline.com/REDMOND_REDACTED/oauth2/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=REDMOND_CLIENT_ID \
--data client_secret=REDMOND_CLIENT_SECRET \
--data resource=REDMOND_RESOURCE_UUID
NOTE: In the ruby version below, certain params are passed to the get_token call, instead of the client creation.
client = OAuth2::Client.new(
"REDMOND_CLIENT_ID", # client_id
"REDMOND_CLIENT_SECRET", # client_secret
auth_scheme: :request_body, # Other modes are supported: :basic_auth, :tls_client_auth, :private_key_jwt
token_url: "oauth2/token", # relative path, except with leading `/`, then absolute path
site: "https://login.microsoftonline.com/REDMOND_REDACTED"
)
client.
client_credentials. # There are many other types to choose from!
get_token(resource: "REDMOND_RESOURCE_UUID")
NOTE: header - The content type specified in the curl is already the default!
docker compose -f docker-compose-ssl.yml up -d --wait
ruby examples/e2e.rb
# If your machine is slow or Docker pulls are cold, increase the wait:
E2E_WAIT_TIMEOUT=120 ruby examples/e2e.rb
# The mock server serves HTTP on 8080; the example points to http://localhost:8080 by default.
The output should be something like this:
➜ ruby examples/e2e.rb
Access token (truncated): eyJraWQiOiJkZWZhdWx0...
userinfo status: 200
userinfo body: {"sub" => "demo-sub", "aud" => ["demo-aud"], "nbf" => 1757816758000, "iss" => "http://localhost:8080/default", "exp" => 1757820358000, "iat" => 1757816758000, "jti" => "d63b97a7-ebe5-4dea-93e6-d542caba6104"}
E2E complete
Make sure to shut down the mock server when you are done:
docker compose -f docker-compose-ssl.yml down
Troubleshooting: validate connectivity to the mock server
docker compose -f docker-compose-ssl.yml pscurl -v http://localhost:8080/default/.well-known/openid-configurationcurl -v --connect-timeout 2 http://127.0.0.1:8080/default/.well-known/openid-configurationdocker exec -it oauth2-mock-oauth2-server-1 curl -v http://127.0.0.1:8080/default/.well-known/openid-configurationnc -vz localhost 8080 # or: ruby -rsocket -e 'TCPSocket.new("localhost",8080).close; puts "tcp ok"'docker inspect -f '{{ (index (index .NetworkSettings.Ports "8080/tcp") 0).HostPort }}' oauth2-mock-oauth2-server-1docker logs -n 200 oauth2-mock-oauth2-server-1ss -ltnp | grep :8080Notes
http://localhost:8080/<realm>/.well-known/openid-configuration, where <realm> defaults to default.E2E_ISSUER_BASE (default: http://localhost:8080)E2E_REALM (default: default)This gem is a low-level OAuth 2.0 client (it talks to an authorization server to obtain and use tokens). If that isn't quite what you need, one of the following libraries may be a better fit (the first row is this gem for comparison):
| Library | Role | When to use it |
|---|---|---|
| this gem ([oauth2][src-gh]) | OAuth 2.0 / 2.1 + OIDC client | You are calling an OAuth 2.0 API, or signing in against a provider, and want a small, dependency-light, spec-faithful client with fine-grained control over the request/response cycle. |
| oauth2-mcp | OAuth 2.1 MCP Auth client and server | Focused, spec-faithful, MCP Auth client with fine-grained control over the request/response cycle. Rack/Roda compatible clients and servers. Built on top of this gem, [oauth2][src-gh]. |
| omniauth + omniauth-oauth2 | "Log in with…" client (Rack) | You primarily want user authentication ("Log in with GitHub/GitLab/Google") wired into a Rack/Rails app via a strategy, rather than driving the token flow yourself. Built on top of this gem, [oauth2][src-gh]. |
| openid_connect | OpenID Connect client & server | You need full OpenID Connect (ID-token validation, discovery, userinfo, etc.) with batteries included. Maintained by @nov. |
| rack-oauth2 | OAuth 2.0 client and server | You want lower-level Rack primitives, need both client and server pieces, or are building on top of openid_connect. Maintained by @nov. |
| doorkeeper | OAuth 2.0 server / provider | You want to be the authorization server — issuing tokens to other apps — in a Rails/Grape/Sinatra application, rather than acting as a client. |
| oauth | OAuth 1.0a client & server | The provider you integrate with only speaks the older OAuth 1.0a protocol. This is our sibling gem. |
See also the OAuth 2.0 Spec, the OpenID Connect Spec, and the MCP Auth Spec.
| Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
|---|---|
| Works with JRuby | [![JRuby 9.2 Compat][jruby-9.2i]][jruby-9.2-wf] [![JRuby 9.3 Compat][jruby-9.3i]][jruby-9.3-wf] [![JRuby 9.4 Compat][jruby-9.4i]][jruby-9.4-wf] [![JRuby 10.0 Compat][jruby-10.0i]][jruby-10.0-wf] [![JRuby current Compat][jruby-c-i]][10-j-wf] [![JRuby HEAD Compat][jruby-headi]][3-hd-wf] |
| Works with Truffle Ruby | [![Truffle Ruby 22.3 Compat][truby-22.3i]][truby-22.3-wf] [![Truffle Ruby 23.0 Compat][truby-23.0i]][truby-23.0-wf] [![Truffle Ruby 23.1 Compat][truby-23.1i]][truby-23.1-wf] [![Truffle Ruby 24.2 Compat][truby-24.2i]][truby-24.2-wf] [![Truffle Ruby 25.0 Compat][truby-25.0i]][truby-25.0-wf] [![Truffle Ruby 33.0 Compat][truby-33.0i]][truby-33.0-wf] [![Truffle Ruby current Compat][truby-c-i]][9-t-wf] [![Truffle Ruby HEAD Compat][truby-headi]][3-hd-wf] |
| Works with MRI Ruby 4 | [![Ruby current Compat][ruby-c-i]][11-c-wf] [![Ruby HEAD Compat][ruby-headi]][3-hd-wf] |
| Works with MRI Ruby 3 | [![Ruby 3.0 Compat][ruby-3.0i]][ruby-3.0-wf] [![Ruby 3.1 Compat][ruby-3.1i]][ruby-3.1-wf] [![Ruby 3.2 Compat][ruby-3.2i]][ruby-3.2-wf] [![Ruby 3.3 Compat][ruby-3.3i]][ruby-3.3-wf] [![Ruby 3.4 Compat][ruby-3.4i]][ruby-3.4-wf] |
| Works with MRI Ruby 2 | ![Ruby 2.2 Compat][ruby-2.2i] ![Ruby 2.3 Compat][ruby-2.3i] [![Ruby 2.4 Compat][ruby-2.4i]][ruby-2.4-wf] [![Ruby 2.5 Compat][ruby-2.5i]][ruby-2.5-wf] [![Ruby 2.6 Compat][ruby-2.6i]][ruby-2.6-wf] [![ |
No open issues yet, or sync has not completed.