oauth

package module
v2.0.1 Latest Latest
Warning

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

Go to latest
Published: May 25, 2016 License: Apache-2.0 Imports: 6 Imported by: 3

README

oauth

Raiqub/oauth is a library for the Go Programming Language. It provides an implementation of OAuth 2.0 features.

Status

Build Status GoDoc

Installation

To install raiqub/oauth library run the following command:

go get gopkg.in/raiqub/oauth.v2

To import this package, add the following line to your code:

import "gopkg.in/raiqub/oauth.v2"

Usage

To create a server to handle token endpoint, as defined by OAuth 2.0 specification, an adapter must be created to define the following operations: find a client, create new access token, validate refresh token and validate user credentials.

To a type be qualified as an adapter must implements the TokenAdapter methods. As shown by the example below:

import (
	"gopkg.in/raiqub/oauth.v2"
	"gopkg.in/raiqub/slice.v1"
)

type MyAdapter struct {
	// Should has fields that allow database connection
}

// NewMyAdapter creates a new instance of MyAdapter.
func NewMyAdapter() *MyAdapter {
	return &MyAdapter{}
}

// FindClient gets the client information if valid.
func (a *MyAdapter) FindClient(c *oauth.TokenContext) *oauth.ClientEntry {
	// Should retrieve from database
	clientID, clientSecret := "example_client", "example_secret"
	clientScopes := []string{"profile.write", "calendar.read"}
	if c.HTTPUser != clientID ||
		c.HTTPSecret != clientSecret {
		return nil
	}

	return &oauth.ClientEntry{
		ClientID:          clientID,
		ClientSecret:      clientSecret,
		ClientType:        "public",
		RedirectUris:      []string{"http://client.example.com/callback"},
		JavascriptOrigins: []string{"http://client.example.com"},
		AllowedGrants:     []string{oauth.GrantTypeClient},
		AllowedScopes:     clientScopes,
	}
}

// NewAccessToken creates and returns a new access token.
func (a *MyAdapter) NewAccessToken(c *oauth.TokenContext) *oauth.TokenResponse {
	// Should create an unique token (and state when applicable)
	resp := oauth.NewTokenResponse(
		"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
		"bearer",
		3600,
		"",
		"profile.write calendar.read",
		"CudYQpuw",
	)
	return &resp
}

// ValidateRefresh validate provided refresh token.
func (a *MyAdapter) ValidateRefresh(*oauth.TokenContext) bool {
	// Should validate provided refresh token
    // Use: c.RefreshToken
	return false
}

// ValidateUser validate resource owner credentials for password grant type.
func (a *MyAdapter) ValidateUser(c *oauth.TokenContext) bool {
	// Should validate provided user credentials
    // Use: c.Username and c.Password
	return false
}

Then you can use a TokenServer to handle token endpoint:

import (
	"net/http"

	"gopkg.in/raiqub/oauth.v2"
	httptransport "gopkg.in/raiqub/oauth.v2/transport/http"
)

svcToken := oauth.NewTokenService(NewMyAdapter(),
	// Accepts client_credentials and refresh_token
	oauth.GrantTypeClient, oauth.GrantTypeRefresh)
srvToken := httptransport.NewTokenServer(svcToken)

http.HandleFunc("/token", srvToken.AccessTokenRequest)
http.ListenAndServe(":8080", nil)

Optionally new grant types can be accepted. To do that you will need to create a function that matchs TokenHandlerFunc function and SetHandler on server.

import "gopkg.in/raiqub/oauth.v2"

func MyHandler(adapter oauth.TokenAdapter, c *oauth.TokenContext,
) (*oauth.TokenResponse, *oauth.Error) {
	// Validates client authentication and authorization
	var oerr *oauth.Error
	c.Client, oerr = oauth.AuthClient(adapter, c)
	if oerr != nil {
		return nil, oerr
	}
	
	// You should implement here your logic
}
import (
	"net/http"

	"gopkg.in/raiqub/oauth.v2"
	httptransport "gopkg.in/raiqub/oauth.v2/transport/http"
)

svcToken := oauth.NewTokenService(NewMyAdapter(),
	// Accepts client_credentials and refresh_token
	oauth.GrantTypeClient, oauth.GrantTypeRefresh)

// Adds a custom handler
srvToken.SetHandler("urn:custom:myhandler", MyHandler)

srvToken := httptransport.NewTokenServer(svcToken)
http.HandleFunc("/token", srvToken.AccessTokenRequest)
http.ListenAndServe(":8080", nil)

For reference and examples browse library documentation.

License

raiqub/oauth is made available under the Apache Version 2.0 License.

Documentation

Overview

Package oauth provides implementations for an OAuth 2.0 server.

Index

Constants

View Source
const (
	// RFC6749ErrorResponseURI defines URI for documentation of error responses
	// from Auth 2.0 documentation.
	RFC6749ErrorResponseURI = "http://tools.ietf.org/html/rfc6749#section-5.2"

	// CodeInvalidClient defines error code when client authentication failed.
	CodeInvalidClient = "invalid_client"

	// CodeInvalidGrant defines error code when provided authorization grant or
	// refresh token is invalid.
	CodeInvalidGrant = "invalid_grant"

	// CodeInvalidRequest defines error code when the request has any error on
	// parameter or is malformed.
	CodeInvalidRequest = "invalid_request"

	// CodeInvalidScope defines error code when has any error related to scope.
	CodeInvalidScope = "invalid_scope"

	// CodeUnauthorizedClient defines error code when authenticated client lacks
	// authorization.
	CodeUnauthorizedClient = "unauthorized_client"

	// CodeUnsupportedGrantType defines error code when the authorization grant
	// type is not supported.
	CodeUnsupportedGrantType = "unsupported_grant_type"
)
View Source
const (
	// FormClientID defines the form's key name to define client identifier.
	FormClientID = "client_id"

	// FormKeyCode defines the form's key name to define authorization code.
	FormKeyCode = "code"

	// FormKeyGrantType defines the form's key name to define grant type.
	FormKeyGrantType = "grant_type"

	// FormKeyPassword defines the form's key name to define user password.
	FormKeyPassword = "password"

	// FormKeyRedirect defines the form's key name to define redirection
	// endpoint.
	FormKeyRedirect = "redirect_uri"

	// FormKeyRefreshToken defines the form's key name to define refresh token.
	FormKeyRefreshToken = "refresh_token"

	// FormKeyScope defines the form's key name to define client scopes.
	FormKeyScope = "scope"

	// FormKeyState defines the form's key name to define session nonce.
	FormKeyState = "state"

	// FormKeyUsername defines the form's key name to define user name.
	FormKeyUsername = "username"
)
View Source
const BearerTokenType = "Bearer"

BearerTokenType defines the token type for Bearer usage (RFC 6750).

View Source
const GrantTypeClient = "client_credentials"

GrantTypeClient defines the code for Client Credentials Grant authentication.

View Source
const GrantTypeCode = "authorization_code"

GrantTypeCode defines the code for Authorization Code Grant authentication.

View Source
const GrantTypePassword = "password"

GrantTypePassword defines the code for Resource Owner Password Credentials Grant authentication.

View Source
const GrantTypeRefresh = "refresh_token"

GrantTypeRefresh defines the code for Refresh Access Token authentication.

Variables

This section is empty.

Functions

func AuthClient

func AuthClient(adapter TokenAdapter, c *TokenContext,
) (*ClientEntry, *Error)

AuthClient validates client authentication and authorization.

func ErrorDescription

func ErrorDescription(code string) string

ErrorDescription returns an error description for error code.

func ErrorStatus

func ErrorStatus(code string) int

ErrorStatus returns a HTTP status code for error code.

func HandlerClient

func HandlerClient(adapter TokenAdapter, c *TokenContext) (*TokenResponse, *Error)

HandlerClient handles Client Credential Grant for TokenService.

func HandlerPassword

func HandlerPassword(adapter TokenAdapter, c *TokenContext) (*TokenResponse, *Error)

HandlerPassword handles Resource Owner Password Credentials Grant for TokenService.

func HandlerRefresh

func HandlerRefresh(adapter TokenAdapter, c *TokenContext) (*TokenResponse, *Error)

HandlerRefresh handles Refresh Access Token for TokenService.

Types

type ClientEntry

type ClientEntry struct {
	ClientID          string   `bson:"_id" json:"client_id"`
	ClientSecret      string   `bson:"secret" json:"client_secret,omitempty"`
	ClientType        string   `bson:"type" json:"client_type"`
	RedirectUris      []string `bson:"redirs" json:"redirect_uris"`
	JavascriptOrigins []string `bson:"origins" json:"javascript_origins"`
	AllowedGrants     []string `bson:"grants" json:"allowed_grants"`
	AllowedScopes     []string `bson:"scopes" json:"allowed_scopes"`
}

A ClientEntry represents a record for client credentials and authorizations.

func (*ClientEntry) MarshalJSON

func (mj *ClientEntry) MarshalJSON() ([]byte, error)

func (*ClientEntry) MarshalJSONBuf

func (mj *ClientEntry) MarshalJSONBuf(buf fflib.EncodingBuffer) error

func (*ClientEntry) UnmarshalJSON

func (uj *ClientEntry) UnmarshalJSON(input []byte) error

func (*ClientEntry) UnmarshalJSONFFLexer

func (uj *ClientEntry) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error

type Error

type Error struct {
	Code        string `json:"error"`
	Description string `json:"error_description,omitempty"`
	URI         string `json:"error_uri,omitempty"`

	// HTTP status code.
	Status int `json:"-"`
}

An Error represents an OAuth 2.0 error response.

func (Error) Error

func (e Error) Error() string

func (*Error) MarshalJSON

func (mj *Error) MarshalJSON() ([]byte, error)

func (*Error) MarshalJSONBuf

func (mj *Error) MarshalJSONBuf(buf fflib.EncodingBuffer) error

func (*Error) UnmarshalJSON

func (uj *Error) UnmarshalJSON(input []byte) error

func (*Error) UnmarshalJSONFFLexer

func (uj *Error) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error

type ErrorBuilder

type ErrorBuilder interface {
	// Build creates and returns a new Error.
	Build() Error

	// InvalidRequest sets current error to invalid request error.
	InvalidRequest() ErrorBuilder

	// InvalidClient sets current error to invalid client error.
	InvalidClient() ErrorBuilder

	// InvalidClientCredentials sets current error to invalid client
	// credentials error.
	InvalidClientCredentials() ErrorBuilder

	// InvalidGrant sets current error to invalid grant error.
	InvalidGrant() ErrorBuilder

	// InvalidRefreshToken sets current error to invalid refresh token error.
	InvalidRefreshToken() ErrorBuilder

	// InvalidScope sets current error to invalid scope error.
	InvalidScope() ErrorBuilder

	// InvalidUserCredential sets current error to invalid user credentials
	// error.
	InvalidUserCredentials(username string) ErrorBuilder

	// MissingClientCredentials sets current error to missing client
	// credentials error.
	MissingClientCredentials() ErrorBuilder

	// SetDescription sets the description for current error.
	SetDescription(string) ErrorBuilder

	// SetStatus sets the HTTP status for current error.
	SetStatus(int) ErrorBuilder

	// SetUri sets the URI for current error.
	SetURI(string) ErrorBuilder

	// UnauthorizedClient sets current error to unauthorized client error.
	UnauthorizedClient() ErrorBuilder

	// UnsupportedGrantType sets current error to unsupported grant type error.
	UnsupportedGrantType() ErrorBuilder
}

An ErrorBuilder provides methods to construct a new Error.

func NewError

func NewError() ErrorBuilder

NewError creates a new instance of ErrorBuilder.

type TokenAdapter

type TokenAdapter interface {
	// FindClient gets the client information if valid.
	FindClient(c *TokenContext) *ClientEntry

	// NewAccessToken creates and returns a new access token.
	NewAccessToken(c *TokenContext) *TokenResponse

	// ValidateRefresh validate provided refresh token.
	ValidateRefresh(c *TokenContext) bool

	// ValidateUser validate resource owner credentials for password grant type.
	ValidateUser(c *TokenContext) bool
}

A TokenAdapter provides an adapter for token management.

type TokenContext

type TokenContext struct {
	GrantType string
	Scope     string
	State     string

	Code        string
	RedirectURI string
	ClientID    string

	Username string
	Password string

	RefreshToken string

	HTTPUser   string
	HTTPSecret string
	Client     *ClientEntry
	Values     map[string]interface{}
}

A TokenContext represents an object to pass variables between TokenHandler and TokenProvider methods.

func (TokenContext) ScopeList

func (s TokenContext) ScopeList() []string

ScopeList returns scope split by its spaces.

type TokenHandlerFunc

type TokenHandlerFunc func(TokenAdapter, *TokenContext) (*TokenResponse, *Error)

A TokenHandlerFunc represents a function that handle a grant type for TokenService.

type TokenResponse

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

A TokenResponse represents a OAuth response that carry a new access token.

func NewTokenResponse

func NewTokenResponse(
	accessToken string,
	tokenType string,
	expiresIn int,
	refreshToken string,
	scope string,
	state string,
) TokenResponse

NewTokenResponse creates a new instance of TokenResponse.

func (*TokenResponse) MarshalJSON

func (mj *TokenResponse) MarshalJSON() ([]byte, error)

func (*TokenResponse) MarshalJSONBuf

func (mj *TokenResponse) MarshalJSONBuf(buf fflib.EncodingBuffer) error

func (*TokenResponse) UnmarshalJSON

func (uj *TokenResponse) UnmarshalJSON(input []byte) error

func (*TokenResponse) UnmarshalJSONFFLexer

func (uj *TokenResponse) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error

type TokenService

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

A TokenService provides token management for OAuth 2.0 server.

func NewTokenService

func NewTokenService(ta TokenAdapter, grantTypes ...string) *TokenService

NewTokenService creates a new instance of TokenService and pre-loads specified handlers.

func (*TokenService) AccessTokenRequest

func (svc *TokenService) AccessTokenRequest(context *TokenContext,
) (*TokenResponse, *Error)

AccessTokenRequest receives a request to create a new access token.

func (*TokenService) SetHandler

func (svc *TokenService) SetHandler(grantType string, handler TokenHandlerFunc)

SetHandler register a new handler for specified grant type.

Directories

Path Synopsis
Package oauthtest provides mocking to test oauth package.
Package oauthtest provides mocking to test oauth package.
transport
ginhttp
Package ginhttp provides an HTTP handler for an OAuth 2.0 server (gin-gonic/gin).
Package ginhttp provides an HTTP handler for an OAuth 2.0 server (gin-gonic/gin).
http
Package http provides an HTTP handler for an OAuth 2.0 server.
Package http provides an HTTP handler for an OAuth 2.0 server.

Jump to

Keyboard shortcuts

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