jwt

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2021 License: BSD-3-Clause Imports: 11 Imported by: 1

Documentation

Overview

Package jwt implements the OAuth 2.0 JSON Web Token flow, commonly known as "two-legged OAuth 2.0".

See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Signer is the func used to sign the JWT header and payload
	Signer jws.Signer

	// Issuer is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	Issuer string `json:"email,omitempty"`

	// Subject is the optional user to impersonate.
	Subject string `json:"subject,omitempty"`

	// TokenURL is the endpoint required to complete the 2-legged JWT flow.
	TokenURL string `json:"token_url,omitempty"`

	// Audience fills the claimset's aud parameter.  For Google Client API
	// this should be set to the TokenURL value.
	Audience string `json:"audience,omitempty"`

	// Scopes optionally specifies a list of requested permission scopes
	// which will be included as private claims named scopes in the
	// JWT claimset payload.
	Scopes []string `json:"scopes,omitempty"`

	// additional options for creating and sending claimset payload
	Options *ConfigOptions `json:"options,omitempty"`

	// HTTPClientFunc (Optional) specifies a function specifiying
	// the *http.Client used on Token calls to the oauth2
	// server.
	HTTPClientFunc ctxclient.Func `json:"-"`
}

Config is the configuration for using JWT to fetch tokens, commonly known as "two-legged OAuth 2.0".

Example
package main

import (
	"log"

	"github.com/ICGGroup/oauth2/jws"
	"github.com/ICGGroup/oauth2/jwt"
)

func main() {
	// The contents of your RSA private key or your PEM file
	// that contains a private key.
	// If you have a p12 file instead, you
	// can use `openssl` to export the private key into a pem file.
	//
	//    $ openssl pkcs12 -in key.p12 -out key.pem -nodes
	//
	// It only supports PEM containers with no passphrase.
	signer, err := jws.RS256FromPEM([]byte("-----BEGIN RSA PRIVATE KEY-----..."), "")
	if err != nil {
		log.Fatalf("Invalid key: %v", err)
	}
	conf := &jwt.Config{
		Issuer: "xxx@developer.com",

		Signer:   signer,
		Subject:  "user@example.com",
		TokenURL: "https://provider.com/o/oauth2/token",
	}
	// Initiate an http.Client, the following GET request will be
	// authorized and authenticated on the behalf of user@example.com.

	client, _ := conf.Client(nil)
	client.Get("...")
}
Output:

func (*Config) Client

func (c *Config) Client(t *oauth2.Token) (*http.Client, error)

Client returns an HTTP client wrapping the context's HTTP transport and adding Authorization headers with tokens obtained from c.

The returned client and its Transport should not be modified.

func (*Config) Token

func (c *Config) Token(ctx context.Context) (*oauth2.Token, error)

Token performs a signed JWT request to obtain a new token.

func (*Config) TokenSource

func (c *Config) TokenSource(t *oauth2.Token) oauth2.TokenSource

TokenSource returns a JWT TokenSource using the configuration in c and the HTTP client from the provided context.

Example
package main

import (
	"context"
	"errors"
	"log"
	"sync"

	"github.com/ICGGroup/oauth2"
	"github.com/ICGGroup/oauth2/jws"
	"github.com/ICGGroup/oauth2/jwt"
)

type userEmailCtx struct{}

var UserEmailKey userEmailCtx

func main() {
	signer, err := jws.RS256FromPEM([]byte("-----BEGIN RSA PRIVATE KEY-----..."), "")
	if err != nil {
		log.Fatalf("Invalid key: %v", err)
	}
	conf := &jwt.Config{
		Issuer:   "xxx@developer.com",
		Signer:   signer,
		TokenURL: "https://provider.com/o/oauth2/token",
		Options:  jwt.DefaultCfgOptions().SetExpiryDelta(20),
	}

	ts := NewCustomCachingTokenSource(conf)
	client := oauth2.Client(ts, nil)
	client.Get("...")
}

func NewCustomCachingTokenSource(cfg *jwt.Config) *CustomCachingTokenSource {
	return &CustomCachingTokenSource{
		refresher: cfg,
		tokenMap:  make(map[string]*oauth2.Token),
	}
}

type CustomCachingTokenSource struct {
	refresher *jwt.Config
	mu        sync.Mutex               // guards t
	tokenMap  map[string]*oauth2.Token // token cache
}

func (cts *CustomCachingTokenSource) Token(ctx context.Context) (*oauth2.Token, error) {
	email, _ := ctx.Value(UserEmailKey).(string)
	if email == "" {
		return nil, errors.New("no user email passed in context")
	}
	if token := cts.GetCachedValidToken(ctx, email); token.Valid() {
		return token, nil
	}
	cfgWithEmail := *cts.refresher
	cfgWithEmail.Subject = email
	newToken, err := (&cfgWithEmail).Token(ctx)
	if err != nil {
		return nil, err
	}
	cts.Save(email, newToken)
	return newToken, nil
}

func (cts *CustomCachingTokenSource) Save(email string, t *oauth2.Token) {
	cts.mu.Lock()
	defer cts.mu.Unlock()

	cts.tokenMap[email] = t
	return
}

func (cts *CustomCachingTokenSource) GetCachedValidToken(ctx context.Context, email string) *oauth2.Token {
	cts.mu.Lock()
	defer cts.mu.Unlock()

	return cts.tokenMap[email]
}
Output:

type ConfigOptions

type ConfigOptions struct {
	// ExpiresIn specifies how many seconds the token should be valid.  A server
	// may ignore the requested duration.  Default to 3600 (1 hour) if not set.
	// Use the SetExpiresIn func to set.
	ExpiresIn *int64
	// IatOffset is the number of seconds subtracted from the current time to
	// set the iat claim. Used for machines whose time is not perfectly in sync.
	// Google servers and others will not issue a token if the issued at time(iat)
	// is in the future. Nil value indicates a default of 10 secounds.  Use
	// the SetIatOffset func to set.
	IatOffset *int64
	// ExpiryDelta determines how many seconds sooner a token should
	// expire than the retrieved expires_in setting. Nil uses
	// oauth2.DefaultExpiryDelta.  Use the SetExpiryDelta func for setting.
	ExpiryDelta *int64
	// PrivateClaims(Optional) adds additional private claims to add
	// to the request
	PrivateClaims map[string]interface{} `json:"private_claims,omitempty"`
	// FormValues(Optional) adds addional form fields to request body
	FormValues url.Values `json:"form_values,omitempty"`
	// NewTokenFunc is called when after retrieving a new *oauth2.Token
	NewTokenFunc func(context.Context, *oauth2.Token, *Config) error
}

ConfigOptions provide additional (rarely used options for the config)

func DefaultCfgOptions

func DefaultCfgOptions() *ConfigOptions

DefaultCfgOptions returns ptr to an empty *ConfigOptions

func IDTokenAsAccessToken

func IDTokenAsAccessToken() *ConfigOptions

IDTokenAsAccessToken returns a *ConfigOptions which sets the new Token access token to the id_token response

func IDTokenSetsExpiry

func IDTokenSetsExpiry() *ConfigOptions

IDTokenSetsExpiry returns a *ConfigOptions that sets new Token expiry based using id_token

func (*ConfigOptions) AddFormValue

func (opts *ConfigOptions) AddFormValue(key string, value string) *ConfigOptions

AddFormValue adds the key/value to the JWT urlform request

func (*ConfigOptions) AddPrivateClaim

func (opts *ConfigOptions) AddPrivateClaim(key string, value interface{}) *ConfigOptions

AddPrivateClaim add claim of key/value to the claimset

func (*ConfigOptions) SetExpiresIn

func (opts *ConfigOptions) SetExpiresIn(numOfSeconds int64) *ConfigOptions

SetExpiresIn sets the requested expiration time. A new *ConfigOptions is returned if opts is nil.

func (*ConfigOptions) SetExpiryDelta

func (opts *ConfigOptions) SetExpiryDelta(numOfSeconds int64) *ConfigOptions

SetExpiryDelta sets the ExpiryDelta and returns a new *ConfigOptions if opts is nil

func (*ConfigOptions) SetFormValues

func (opts *ConfigOptions) SetFormValues(values url.Values) *ConfigOptions

SetFormValues does exactly what its name says

func (*ConfigOptions) SetIatOffset

func (opts *ConfigOptions) SetIatOffset(numOfSeconds int64) *ConfigOptions

SetIatOffset sets the IatOffset and returns a new *ConfigOptions if opts is nil

func (*ConfigOptions) SetPrivateClaims

func (opts *ConfigOptions) SetPrivateClaims(claims map[string]interface{}) *ConfigOptions

SetPrivateClaims does exactly what its name says

type ServiceAccount

type ServiceAccount struct {
	// Email is the OAuth client identifier used when communicating with
	// the configured OAuth provider.
	Email string `json:"client_email,omitempty"`

	// PrivateKey contains the contents of an RSA private key or the
	// contents of a PEM file that contains a private key. The provided
	// private key is used to sign JWT payloads.
	// PEM containers with a passphrase are not supported.
	// Use the following command to convert a PKCS 12 file into a PEM.
	//
	//    $ openssl pkcs12 -in key.p12 -out key.pem -nodes
	//
	PrivateKey []byte `json:"private_key,omitempty"`

	// PrivateKeyID contains an optional hint indicating which key is being
	// used.
	PrivateKeyID string `json:"private_key_id,omitempty"`

	// Subject is the optional user to impersonate.
	Subject string `json:"subject,omitempty"`

	// Scopes optionally specifies a list of requested permission scopes.
	Scopes []string `json:"scopes,omitempty"`

	// TokenURL is the endpoint required to complete the 2-legged JWT flow.
	TokenURL string `json:"token_uri,omitempty"`

	// Expires optionally specifies how long the token is valid for.
	Expires time.Duration `json:"expires,omitempty"`
}

ServiceAccount conforms to the json format of a Google Service Account Key and has the same structure as the golang.org/x/oauth2/jwt Config struct. Use ServiceAccount.Config() to convert to jwt.Config.

func (ServiceAccount) Client

func (cfg ServiceAccount) Client(tk *oauth2.Token) (*http.Client, error)

Client returns a *jwt.Config client with the passed token. Error returned if problems found with the private key

func (ServiceAccount) Config

func (cfg ServiceAccount) Config() (*Config, error)

Config translates the ServiceAccount settings to a jwt.Config

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL