oauth2

package module
v2.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 15, 2021 License: MIT Imports: 17 Imported by: 4

README

oauth2

Test GoDoc Release

A fundamental and extendable OAuth2 library for Go.

Package oauth2 provides structures and functions to implement OAuth2 compatible authentication servers. The library can be used standalone or with any framework as it is built on top of the standard Go http library.

Specifications

The library considers and implements the following specifications:

Example

The test server implements a basic but feature-complete in-memory OAuth2 authentication server. The code can be used as a template to build a custom implementation of an OAuth2 compatible authentication server.

Installation

Get the package using the go tool:

$ go get -u github.com/256dpi/oauth2/v2

License

The MIT License (MIT)

Copyright (c) 2016 Joël Gähwiler

Documentation

Overview

Package oauth2 provides structures and functions to implement OAuth2 compatible authentication servers.

The library can be used standalone or with any framework as it is built on top of the standard Go http library.

Index

Constants

View Source
const (
	PasswordGrantType          = "password"
	ClientCredentialsGrantType = "client_credentials"
	AuthorizationCodeGrantType = "authorization_code"
	RefreshTokenGrantType      = "refresh_token"
)

The known OAuth2 grant types.

View Source
const (
	TokenResponseType = "token"
	CodeResponseType  = "code"
)

The known OAuth2 response types.

View Source
const (
	AccessToken  = "access_token"
	RefreshToken = "refresh_token"
)

The known OAuth2 token types.

View Source
const BearerAccessTokenType = "bearer"

BearerAccessTokenType is the bearer access token type as defined by the OAuth2 Bearer Token spec.

Variables

This section is empty.

Functions

func BuildIntrospectionRequest

func BuildIntrospectionRequest(uri string, r IntrospectionRequest) (*http.Request, error)

BuildIntrospectionRequest will build the provided request.

func BuildRevocationRequest

func BuildRevocationRequest(uri string, r RevocationRequest) (*http.Request, error)

BuildRevocationRequest will build the provided request.

func BuildTokenRequest

func BuildTokenRequest(uri string, r TokenRequest) (*http.Request, error)

BuildTokenRequest will build a request from the provided data.

func IntrospectionRequestValues

func IntrospectionRequestValues(r IntrospectionRequest) url.Values

IntrospectionRequestValues will return the form values for the provided request.

func KnownGrantType

func KnownGrantType(str string) bool

KnownGrantType returns true if the grant type is a known grant type (e.g. password, client credentials, authorization code or refresh token).

func KnownResponseType

func KnownResponseType(str string) bool

KnownResponseType returns true if the response type is a known response type (e.g. token or code).

func KnownTokenType

func KnownTokenType(str string) bool

KnownTokenType returns true if the token type is a known token type (e.g. access token or refresh token).

func ParseBearerToken

func ParseBearerToken(r *http.Request) (string, error)

ParseBearerToken parses and returns the bearer token from a request. It will return an Error if the extraction failed.

Note: The spec also allows obtaining the bearer token from query parameters and the request body (form data). This implementation only supports obtaining the token from the "Authorization" header as this is the most common use case and considered most secure.

func ParseRequestError

func ParseRequestError(res *http.Response, limit int64) error

ParseRequestError will try to parse an oauth2.Error from the provided response. It will fall back to an error containing the response status.

func RevocationRequestValues

func RevocationRequestValues(r RevocationRequest) url.Values

RevocationRequestValues will return the form values for the provided request.

func TokenRequestValues

func TokenRequestValues(r TokenRequest) url.Values

TokenRequestValues will return the form values for the provided request.

func Write

func Write(w http.ResponseWriter, obj interface{}, status int) error

Write will encode the specified object as json and write a response to the response writer as specified by the OAuth2 spec.

func WriteBearerError

func WriteBearerError(w http.ResponseWriter, err error) error

WriteBearerError will write the specified error to the response writer. The function will fall back and write an internal server error if the specified error is not known.

Common bearer token errors: ProtectedResource, InvalidRequest, InvalidToken, InsufficientScope, ServerError.

func WriteCodeResponse

func WriteCodeResponse(w http.ResponseWriter, r *CodeResponse) error

WriteCodeResponse will write a redirection based on the specified code response to the response writer.

func WriteError

func WriteError(w http.ResponseWriter, err error) error

WriteError will write the specified error to the response writer. The function will fall back and write a server error if the specified error is not known. If the RedirectURI field is present on the error a redirection will be written instead.

func WriteIntrospectionResponse

func WriteIntrospectionResponse(w http.ResponseWriter, r *IntrospectionResponse) error

WriteIntrospectionResponse will write a response to the response writer.

func WriteRedirect

func WriteRedirect(w http.ResponseWriter, uri string, params map[string]string, useFragment bool) error

WriteRedirect will either add the specified parameters to the query of the specified uri or encode them and it as the fragment as specified by the OAuth2 spec.

func WriteTokenResponse

func WriteTokenResponse(w http.ResponseWriter, r *TokenResponse) error

WriteTokenResponse will write the specified response to the response writer. If the RedirectURI field is present on the response a redirection that transmits the token in the fragment will be written instead.

Types

type AuthorizationRequest

type AuthorizationRequest struct {
	ResponseType string
	Scope        Scope
	ClientID     string
	RedirectURI  string
	State        string
}

A AuthorizationRequest is typically returned by ParseAuthorizationRequest and holds all information necessary to handle an authorization request.

func ParseAuthorizationRequest

func ParseAuthorizationRequest(r *http.Request) (*AuthorizationRequest, error)

ParseAuthorizationRequest parses an incoming request and returns an AuthorizationRequest. The function validates basic constraints given by the OAuth2 spec.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a low-level OAuth2 client.

func NewClient

func NewClient(config ClientConfig) *Client

NewClient will create and return a new client.

func NewClientWithClient

func NewClientWithClient(config ClientConfig, client *http.Client) *Client

NewClientWithClient will create and return a new client using the provided client.

func (*Client) Authenticate

func (c *Client) Authenticate(trq TokenRequest) (*TokenResponse, error)

Authenticate will send the provided token request and return the servers token response or an error if failed.

func (*Client) Introspect

func (c *Client) Introspect(irq IntrospectionRequest) (*IntrospectionResponse, error)

Introspect will send the provided introspection request and return the server response or an error if failed.

func (*Client) Revoke

func (c *Client) Revoke(rrq RevocationRequest) error

Revoke will send the provided revocation request and return and error if it failed.

type ClientConfig

type ClientConfig struct {
	BaseURI               string
	TokenEndpoint         string
	IntrospectionEndpoint string
	RevocationEndpoint    string
	ResponseLimit         int64
}

ClientConfig is used to configure a client.

func Default

func Default(baseURI string) ClientConfig

Default will return a default configuration.

type CodeResponse

type CodeResponse struct {
	Code  string `json:"code"`
	State string `json:"state,omitempty"`

	RedirectURI string `json:"-"`
}

A CodeResponse is typically constructed after an authorization code request has been authenticated to return an authorization code.

func NewCodeResponse

func NewCodeResponse(code, redirectURI, state string) *CodeResponse

NewCodeResponse constructs a CodeResponse.

func (*CodeResponse) Map

func (r *CodeResponse) Map() map[string]string

Map returns a map of all fields that can be presented to the client. This method can be used to construct query parameters or a fragment when redirecting the code response.

type Error

type Error struct {
	Name        string `json:"error"`
	State       string `json:"state,omitempty"`
	Scope       Scope  `json:"scope,omitempty"`
	Realm       string `json:"realm,omitempty"`
	Description string `json:"error_description,omitempty"`
	URI         string `json:"error_uri,omitempty"`

	Status      int               `json:"-"`
	Headers     map[string]string `json:"-"`
	RedirectURI string            `json:"-"`
	UseFragment bool              `json:"-"`
}

An Error represents an error object defined by the OAuth2 specification. All functions that are used during the authorization and token request processing flow return such error instances.

func AccessDenied

func AccessDenied(description string) *Error

AccessDenied constructs an error that indicates that the resource owner or authorization server denied the request.

func InsufficientScope

func InsufficientScope(necessaryScope Scope) *Error

InsufficientScope constructs and error that indicates that the request requires higher privileges than provided by the access token.

func InvalidClient

func InvalidClient(description string) *Error

InvalidClient constructs an error that indicates that the client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).

func InvalidGrant

func InvalidGrant(description string) *Error

InvalidGrant constructs an error that indicates that the provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.

func InvalidRequest

func InvalidRequest(description string) *Error

InvalidRequest constructs an error that indicates that the request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.

func InvalidScope

func InvalidScope(description string) *Error

InvalidScope constructs an error that indicates that the requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner.

func InvalidToken

func InvalidToken(description string) *Error

InvalidToken constructs and error that indicates that the access token provided is expired, revoked, malformed, or invalid for other reasons.

func ProtectedResource

func ProtectedResource() *Error

ProtectedResource constructs and error that indicates that the requested resource needs authentication.

func ServerError

func ServerError(description string) *Error

ServerError constructs an error that indicates that the authorization server encountered an unexpected condition that prevented it from fulfilling the request.

func TemporarilyUnavailable

func TemporarilyUnavailable(description string) *Error

TemporarilyUnavailable constructs an error that indicates that the authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.

func UnauthorizedClient

func UnauthorizedClient(description string) *Error

UnauthorizedClient constructs an error that indicates that the authenticated client is not authorized to use this authorization grant type or method to request and access token.

func UnsupportedGrantType

func UnsupportedGrantType(description string) *Error

UnsupportedGrantType constructs an error that indicates that the authorization grant type is not supported by the authorization server.

func UnsupportedResponseType

func UnsupportedResponseType(description string) *Error

UnsupportedResponseType constructs an error that indicates that the authorization server does not support obtaining an access token using this method.

func UnsupportedTokenType

func UnsupportedTokenType(description string) *Error

UnsupportedTokenType constructs an error that indicates that the authorization server does not support the introspection of the presented token type.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) Map

func (e *Error) Map() map[string]string

Map returns a map of all fields that can be presented to the client. This method can be used to construct query parameters or a fragment when redirecting the error.

func (*Error) Params

func (e *Error) Params() string

Params returns a string encoded representation of the error parameters.

func (*Error) SetRedirect

func (e *Error) SetRedirect(uri, state string, useFragment bool) *Error

SetRedirect marks the error to be redirected by setting the state value as well as the redirect URI and whether the error should be added to the query parameter or fragment part of the URI.

func (*Error) String

func (e *Error) String() string

String implements the fmt.Stringer interface.

type HS256Token

type HS256Token struct {
	Key       []byte
	Signature []byte
}

HS256Token implements a simple abstraction around generating token using the hmac-sha256 algorithm.

func GenerateHS256Token

func GenerateHS256Token(secret []byte, length int) (*HS256Token, error)

GenerateHS256Token will return a new hmac-sha256 token that is constructed using the specified secret and random key of the specified length.

Note: The secret and the to be generated token key should both at least have a length of 16 characters to be considered unguessable.

func HS256TokenFromKey

func HS256TokenFromKey(secret []byte, key []byte) *HS256Token

HS256TokenFromKey will return a new hmac-sha256 token that is constructed using the specified secret and key.

Note: The secret and the token key should both at least have a length of 16 characters to be considered unguessable.

func MustGenerateHS256Token

func MustGenerateHS256Token(secret []byte, length int) *HS256Token

MustGenerateHS256Token will generate a token using GenerateHS256Token and panic instead of returning an error.

Note: The cryptographically secure pseudo-random number generator provided by the operating system may fail. However, such a fail would mean that something seriously must be wrong with the machine running this code.

func ParseHS256Token

func ParseHS256Token(secret []byte, str string) (*HS256Token, error)

ParseHS256Token will parse a token that is in its string representation.

func (*HS256Token) Equal

func (t *HS256Token) Equal(signature []byte) bool

Equal returns true then the specified signature is the same as the token signature.

Note: This method should be used over just comparing the byte slices as it computed in constant time and limits time based attacks.

func (*HS256Token) KeyString

func (t *HS256Token) KeyString() string

KeyString returns a string (base64) representation of the key.

func (*HS256Token) SignatureString

func (t *HS256Token) SignatureString() string

SignatureString returns a string (base64) representation of the signature.

func (*HS256Token) String

func (t *HS256Token) String() string

String returns a string representation of the whole token.

func (*HS256Token) Valid

func (t *HS256Token) Valid(secret []byte) bool

Valid returns true when the token's key matches its signature.

type IntrospectionRequest

type IntrospectionRequest struct {
	Token         string
	TokenTypeHint string
	ClientID      string
	ClientSecret  string
}

A IntrospectionRequest is returned by ParseIntrospectionRequest and holds all information necessary to handle an introspection request.

func ParseIntrospectionRequest

func ParseIntrospectionRequest(r *http.Request) (*IntrospectionRequest, error)

ParseIntrospectionRequest parses an incoming request and returns an IntrospectionRequest. The function validates basic constraints given by the OAuth2 spec.

type IntrospectionResponse

type IntrospectionResponse struct {
	Active     bool   `json:"active"`
	Scope      Scope  `json:"scope,omitempty"`
	ClientID   string `json:"client_id,omitempty"`
	Username   string `json:"username,omitempty"`
	TokenType  string `json:"token_type,omitempty"`
	ExpiresAt  int64  `json:"exp,omitempty"`
	IssuedAt   int64  `json:"iat,omitempty"`
	NotBefore  int64  `json:"nbf,omitempty"`
	Subject    string `json:"sub,omitempty"`
	Audience   string `json:"aud,omitempty"`
	Issuer     string `json:"iss,omitempty"`
	Identifier string `json:"jti,omitempty"`

	Extra map[string]interface{} `json:"extra,omitempty"`
}

IntrospectionResponse is a response returned by the token introspection endpoint.

func NewIntrospectionResponse

func NewIntrospectionResponse(active bool, scope Scope, clientID, username, tokenType string) *IntrospectionResponse

NewIntrospectionResponse constructs an IntrospectionResponse.

func ParseIntrospectionResponse

func ParseIntrospectionResponse(res *http.Response, limit int64) (*IntrospectionResponse, error)

ParseIntrospectionResponse will parse the provided response.

type RevocationRequest

type RevocationRequest struct {
	Token         string
	TokenTypeHint string
	ClientID      string
	ClientSecret  string
}

A RevocationRequest is returned by ParseRevocationRequest and holds all information necessary to handle a revocation request.

func ParseRevocationRequest

func ParseRevocationRequest(r *http.Request) (*RevocationRequest, error)

ParseRevocationRequest parses an incoming request and returns a RevocationRequest. The function validates basic constraints given by the OAuth2 spec.

type Scope

type Scope []string

A Scope is received typically in an authorization and token request.

func ParseScope

func ParseScope(str string) Scope

ParseScope parses the joined string representation of a scope.

func (Scope) Contains

func (s Scope) Contains(str string) bool

Contains returns true if the specified string is part of the scope.

func (Scope) Empty

func (s Scope) Empty() bool

Empty return true if the scope is empty.

func (Scope) Includes

func (s Scope) Includes(scope Scope) bool

Includes returns true if the specified scope is included in this scope.

func (Scope) MarshalJSON

func (s Scope) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface.

func (Scope) String

func (s Scope) String() string

String implements the fmt.Stringer interface.

func (*Scope) UnmarshalJSON added in v2.2.0

func (s *Scope) UnmarshalJSON(buf []byte) error

UnmarshalJSON implements the json.Unmarshaler interface.

type Server

type Server struct {
	Config             ServerConfig
	Clients            map[string]*ServerEntity
	Users              map[string]*ServerEntity
	AccessTokens       map[string]*ServerCredential
	RefreshTokens      map[string]*ServerCredential
	AuthorizationCodes map[string]*ServerCredential
	Mutex              sync.Mutex
}

Server implements a basic in-memory OAuth2 authentication server intended for testing purposes.

func NewServer

func NewServer(config ServerConfig) *Server

NewServer creates and returns a new server.

func (*Server) Authorize

func (s *Server) Authorize(w http.ResponseWriter, r *http.Request, required Scope) bool

Authorize will authorize the request and require a valid access token. An error has already be written to the client if false is returned.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will handle the provided request based on the last path segment of the request URL.

type ServerConfig

type ServerConfig struct {
	Secret                    []byte
	KeyLength                 int
	AllowedScope              Scope
	AccessTokenLifespan       time.Duration
	RefreshTokenLifespan      time.Duration
	AuthorizationCodeLifespan time.Duration
}

ServerConfig is used to configure a server.

func DefaultServerConfig

func DefaultServerConfig(secret []byte, allowed Scope) ServerConfig

DefaultServerConfig will return a default configuration.

func (ServerConfig) MustGenerate

func (c ServerConfig) MustGenerate() *HS256Token

MustGenerate will generate a new token.

type ServerCredential

type ServerCredential struct {
	ClientID    string
	Username    string
	ExpiresAt   time.Time
	Scope       Scope
	RedirectURI string
	Code        string
	Used        bool
}

ServerCredential represents an access token, refresh token or authorization code.

type ServerEntity

type ServerEntity struct {
	Secret       string
	RedirectURI  string
	Confidential bool
}

ServerEntity represents a client or resource owner.

type TokenRequest

type TokenRequest struct {
	GrantType    string
	Scope        Scope
	ClientID     string
	ClientSecret string
	Username     string
	Password     string
	RefreshToken string
	RedirectURI  string
	Code         string
}

A TokenRequest is typically returned by ParseTokenRequest and holds all information necessary to handle a token request.

func ParseTokenRequest

func ParseTokenRequest(r *http.Request) (*TokenRequest, error)

ParseTokenRequest parses an incoming request and returns a TokenRequest. The function validates basic constraints given by the OAuth2 spec.

Note: Obtaining the client id and secret from the request body (form data) is not implemented by default due to security considerations.

type TokenResponse

type TokenResponse struct {
	TokenType    string `json:"token_type"`
	AccessToken  string `json:"access_token"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token,omitempty"`
	Scope        Scope  `json:"scope,omitempty"`
	State        string `json:"state,omitempty"`

	RedirectURI string `json:"-"`
}

A TokenResponse is typically constructed after a token request has been authenticated and authorized to return an access token, a potential refresh token and more detailed information.

func NewBearerTokenResponse

func NewBearerTokenResponse(token string, expiresIn int) *TokenResponse

NewBearerTokenResponse creates and returns a new token response that carries a bearer access token.

func NewTokenResponse

func NewTokenResponse(tokenType, accessToken string, expiresIn int) *TokenResponse

NewTokenResponse constructs a TokenResponse.

func ParseTokenResponse

func ParseTokenResponse(res *http.Response, limit int64) (*TokenResponse, error)

ParseTokenResponse will parse the provided response.

func (*TokenResponse) Map

func (r *TokenResponse) Map() map[string]string

Map returns a map of all fields that can be presented to the client. This method can be used to construct query parameters or a fragment when redirecting the token response.

func (*TokenResponse) SetRedirect

func (r *TokenResponse) SetRedirect(uri, state string) *TokenResponse

SetRedirect marks the response to be redirected by setting the redirect URI and state.

Directories

Path Synopsis
Package oauth2test implements reusable integration tests to run against any OAuth2 authentication server.
Package oauth2test implements reusable integration tests to run against any OAuth2 authentication server.

Jump to

Keyboard shortcuts

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