Skip to content

TelpeNight/oauthctx

Repository files navigation

Go Go Reference GitHub License GitHub Tag Go Report Card

oauthctx

Context-aware OAuth2 token sources for Go.

Problem

The standard golang.org/x/oauth2 package does not propagate context through token refresh, making it impossible to respect deadlines and cancellations during OAuth2 operations (golang/oauth2#262). oauthctx solves this with a minimal, context-aware TokenSource interface that wraps the standard library rather than replacing it.

Installation

go get github.com/TelpeNight/oauthctx

Code examples

3-legged OAuth2 (Config)

import (
    "golang.org/x/oauth2"
    "github.com/TelpeNight/oauthctx"
)

conf := oauthctx.NewConfig(&oauth2.Config{
    ClientID:     "client-id",
    ClientSecret: "client-secret",
    Endpoint:     oauth2.Endpoint{TokenURL: "https://auth.example.com/token"},
    Scopes:       []string{"scope1"},
})

// TokenSource caches the token and refreshes it automatically.
ts := conf.TokenSource(&oauth2.Token{RefreshToken: refreshToken})

// Or get an HTTP client directly:
client := conf.Client(&oauth2.Token{RefreshToken: refreshToken})

2-legged OAuth2 (ClientCredentials)

import (
    "golang.org/x/oauth2/clientcredentials"
    "github.com/TelpeNight/oauthctx"
)

creds := oauthctx.NewClientCredentials(&clientcredentials.Config{
    ClientID:     "client-id",
    ClientSecret: "client-secret",
    TokenURL:     "https://auth.example.com/token",
    Scopes:       []string{"scope1"},
})

client := creds.Client()

Adopting existing oauth2 types

If you already have an oauth2-package type and just need context support:

import (
    "golang.org/x/oauth2/clientcredentials"
    "github.com/TelpeNight/oauthctx"
)

existing := &clientcredentials.Config{ /* ... */ }

// AdoptTokenSourceWithContext wraps types with a Token(ctx) method.
ts := oauthctx.AdoptTokenSourceWithContext(existing)
ts = oauthctx.ReuseTokenSource(nil, ts) // add caching
client := oauthctx.NewClient(ts)

Force token refresh

To force a ReuseTokenSource to bypass its cache and fetch a new token:

ctx := oauthctx.WithExpiredToken(context.Background())
token, err := ts.TokenContext(ctx)

gRPC

import (
    "golang.org/x/oauth2"
    "google.golang.org/grpc/credentials"
    gcred "google.golang.org/grpc/credentials/google"

    "github.com/TelpeNight/oauthctx"
    grpcctx "github.com/TelpeNight/oauthctx/grpc"
)

conf := oauthctx.NewConfig(&oauth2.Config{ /* ... */ })
ts := conf.TokenSource(&oauth2.Token{RefreshToken: refreshToken})

// grpcctx.TokenSource forwards each RPC's context to token refresh,
// so deadlines and cancellations propagate correctly.
var bundle credentials.Bundle = gcred.NewDefaultCredentialsWithOptions(
    gcred.DefaultCredentialsOptions{
        PerRPCCreds: &grpcctx.TokenSource{TokenSource: ts},
    },
)
// use bundle to create a gRPC connection

Design

The aim of this library is to implement only the smallest possible subset of functionality for context support, reusing golang.org/x/oauth2 as much as possible. This is achieved through three strategies:

  1. Adopt existing types — types that implement Oauth2TokenConfig or Oauth2TokenSourceWithContext can be wrapped without changing their token logic. See AdoptTokenConfig and AdoptTokenSourceWithContext in convert.go.
  2. Reuse high-level transport — tokens are fetched through the context-aware TokenSource and injected into the existing oauth2 transport implementation via oauth2.StaticTokenSource. See transport.go and grpc/credentials.go.
  3. Reimplement a focused subset — only ReuseTokenSource and tokenRefresher are reimplemented, as they are the exact point where context support cannot be delegated to the upstream library.

All configuration is provided via option functions (RequestFlowOp, TokenSourceOp, ClientOp) — no context.WithValue mess. All functions mirror the golang.org/x/oauth2 API and should feel familiar. The library is used in production.

Contributing

If something is missing, feel free to open an issue or make a PR. Everything should be adoptable with this approach.

About

OAuth2 library which respects Context

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages