DEV Community

Cover image for đź’Ž ANN: oauth2 v2.0.17
Peter H. Boling
Peter H. Boling

Posted on

đź’Ž ANN: oauth2 v2.0.17

Announcing oauth2 v2.0.17 — Static Hash for verb‑dependent token mode (Instagram‑friendly)

The oauth2 v2.0.17 is a small but useful release: it adds support for configuring verb‑dependent token transmission with a static Hash in addition to the previously available Proc. This makes integrations like Instagram’s Graph API a little simpler and slightly more performant.

TL;DR

  • v2.0.15 introduced verb‑dependent token mode, so you could decide per HTTP verb whether the access token should be sent in the query string or the Authorization header.
  • v2.0.17 lets you provide that mapping as a static Hash instead of a Proc.
  • Example mapping: {get: :query, post: :header, delete: :header}.

Why this matters

Some APIs (notably Instagram’s Graph API) require you to send the access token in the query for GET requests (e.g., ?access_token=...), but in the Authorization header for POST/DELETE (e.g., Authorization: Bearer ...).

In v2.0.15 we added support for a verb‑dependent mode via a Proc, like:

{mode: ->(verb) { verb == :get ? :query : :header }}
Enter fullscreen mode Exit fullscreen mode

In v2.0.17 you can now configure the same behavior using a static Hash, which avoids calling a Proc for each request, keeps intent obvious at a glance, and can be trivially serialized or reused:

verb_dependent_token = {get: :query, post: :header, delete: :header}
Enter fullscreen mode Exit fullscreen mode

Example: Instagram Graph API with a static Hash

Below is a concrete example that exchanges a short‑lived token for a long‑lived token, refreshes it, and then makes API calls — all while automatically placing the token in the right place per HTTP verb using the static Hash mode.

require "oauth2"

client = OAuth2::Client.new(nil, nil, site: "https://graph.instagram.com")

# Start with a short‑lived token you already obtained via Facebook Login
verb_dependent_token = {get: :query, post: :header, delete: :header}

short_lived = OAuth2::AccessToken.new(
  client,
  ENV["IG_SHORT_LIVED_TOKEN"],
  mode: verb_dependent_token,
)

# 1) Exchange for a long‑lived token (GET with token in query)
#    Endpoint: GET https://graph.instagram.com/access_token
#    Params: grant_type=ig_exchange_token, client_secret=APP_SECRET
exchange = short_lived.get(
  "/access_token",
  params: {
    grant_type: "ig_exchange_token",
    client_secret: ENV["IG_APP_SECRET"],
    # access_token will be added automatically in the query
  },
)
long_lived_token_value = exchange.parsed["access_token"]

long_lived = OAuth2::AccessToken.new(
  client,
  long_lived_token_value,
  mode: verb_dependent_token,
)

# 2) Refresh the long‑lived token (GET with token in query)
#    Endpoint: GET https://graph.instagram.com/refresh_access_token
refresh_resp = long_lived.get(
  "/refresh_access_token",
  params: {grant_type: "ig_refresh_token"},
)
long_lived = OAuth2::AccessToken.new(
  client,
  refresh_resp.parsed["access_token"],
  mode: verb_dependent_token,
)

# 3) Typical API GET request (token automatically in query)
me = long_lived.get("/me", params: {fields: "id,username"}).parsed

# 4) Example POST (token automatically in Authorization header)
# long_lived.post("/me/media", body: {image_url: "https://...", caption: "hello"})
Enter fullscreen mode Exit fullscreen mode

Notes

  • Instagram is a special case that explicitly requires query‑string tokens for GET endpoints. For most providers you should prefer header‑based tokens when possible.
  • If you need custom logic beyond a simple mapping, you can still use a Proc: mode: ->(verb) { ... }.

Migrating from Proc to Hash

If you already use the v2.0.15 Proc style:

{mode: ->(verb) { verb == :get ? :query : :header }}
Enter fullscreen mode Exit fullscreen mode

You can switch to the Hash form in v2.0.17:

{mode: {get: :query, post: :header, delete: :header}}
Enter fullscreen mode Exit fullscreen mode

Both are supported; choose whichever best fits your app. The Hash form is generally a bit faster and more explicit, while the Proc form is endlessly versatile!

Release links

Thanks

Thanks to everyone using oauth2 and filing issues. Keep the feedback coming!

Support & Funding Info

I am a full-time FLOSS maintainer. If you find my work valuable I ask that you become a sponsor. Every dollar helps!

🥰 Support FLOSS work 🥰 Get access "Sponsors" channel on Galtzo FLOSS Discord 👇️ Live Chat on Discord
OpenCollective Backers OpenCollective Sponsors Buy me a coffee Donate at ko-fi.com Donate on PayPal Donate on Polar Sponsor Me on Github Liberapay Goal Progress

Photo (cropped) by Wonder KIM on Unsplash

Top comments (0)