ssokenizer

package module
v0.0.0-...-53c253e Latest Latest
Warning

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

Go to latest
Published: Dec 12, 2023 License: Apache-2.0 Imports: 14 Imported by: 0

README

ssokenizer

Ssokenizer provides a layer of abstraction for applications wanting to authenticate users and access 3rd party APIs via OAuth, but not wanting to directly handle users' API tokens. Ssokenizer is responsible for performing the OAuth dance, obtaining the user's OAuth access token. The token is then encrypted for use with the tokenizer HTTP proxy. By delegating OAuth authentication to ssokenizer and access token usage to tokenizer, applications limit the risk of tokens being lost, stolen, or misused.

Configuration

Ssokenizer searches for a configuration file at /etc/ssokenizer.yml, but a path can be specified with the -config flag. See /etc/ssokenizer.yml in this repo for an annotated example configuration. Environment variables in the configuration file are expanded when the application is booting.

Deploying to fly.io

  • Fork this repository on GitHub
  • Clone the forked repository
  • In a terminal, enter the repository directory and run fly launch
  • Follow the prompts, declining to deploy the new application.
  • Set secrets (TOKENIZER_SEAL_KEY, PROXY_AUTH, <PROVIDER>_CLIENT_SECRET) by running fly secrets set --stage SECRET_NAME="SECRET_VALUE"
  • Edit the configuration file in /etc/ssokenizer.yml to reflect the OAuth providers you would like to support. The secrets you set in the previous step will be available as environment variables in this configuration file.
  • Run make deploy or fly deploy

Usage

To start the authentication flow, navigate users to https://<ssokenizer-url>/<provider-name>/start?state=<state>. The <ssokenizer-url> and <provider-name> will depend on your configuration and how you've deployed the app. The state parameter is used to prevent login-CSRF attacks. Your application should generate a random string and associate it with the user's session by either putting it in the session-store provided by your web framework or by putting it directly in a cookie.

The user will now perform the OAuth dance with ssokenizer and the identity provider. Upon successful completion, the user will be redirected back to your configured return_url with several parameters:

  • sealed - The sealed OAuth access token and refresh token (if applicable), ready for use with your tokenizer deployment.
  • expires - The unix epoch time when the access token will expire, if applicable.
  • state - The state parameter that you passed to the /start URL. It is important for your application to verify that this matches the state value you stored in the user's session or cookie.

If the OAuth dance doesn't finish successfully, an error parameter will be added to the configured return_url instead of the sealed and expired parameter.

Using the sealed token

You are now ready to communicate with the provider API using the sealed token via the tokenizer HTTP proxy. You'll need to send the sealed token in the Proxy-Tokenizer header. You'll need to send the configured proxy_authorization secret in the Proxy-Authorization with the Bearer authorization scheme. Remember that requests made via tokenizer must use HTTP instead of HTTPS.

The following demonstrates how you might call the Google "userinfo" endpoint using cURL:

curl \
    -x $TOKENIZER_URL \
    -H "Proxy-Authorization: Bearer $PROXY_AUTH" \
    -H "Proxy-Tokenizer: $SEALED_TOKEN" \
    http://openidconnect.googleapis.com/v1/userinfo
Refreshing access tokens

Some identity providers issue access tokens that expire quickly along with refresh tokens that can be used to fetch new access tokens. To fetch a new access token, send a request to https://<ssokenizer-url>/<provider-name>/refresh via tokenizer. Include the sealed token in the Proxy-Tokenizer header, including a st=refresh parameter in the header. The response body will contain the new token, sealed for use with tokenizer.

The following demonstrates how you might refresh a token using cURL:

curl \
    -x $TOKENIZER_URL \
    -H "Proxy-Authorization: Bearer $PROXY_AUTH" \
    -H "Proxy-Tokenizer: $SEALED_TOKEN; st=refresh" \
    http://$SSOKENIZER_HOSTNAME/$PROVIDER_NAME/refresh

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetLog

func GetLog(r *http.Request) logrus.FieldLogger

Gets the logrus.FieldLogger from the context. Requests are logged by Transaction.ReturnData/ReturnError.

func WithError

func WithError(r *http.Request, err error) *http.Request

Updates the logrus.FieldLogger in the context with "error" field. Requests are logged by Transaction.ReturnData/ReturnError.

func WithField

func WithField(r *http.Request, key string, value any) *http.Request

Updates the logrus.FieldLogger in the context with added field. Requests are logged by Transaction.ReturnData/ReturnError.

func WithFields

func WithFields(r *http.Request, fields logrus.Fields) *http.Request

Updates the logrus.FieldLogger in the context with added fields. Requests are logged by Transaction.ReturnData/ReturnError.

func WithLog

func WithLog(r *http.Request, l logrus.FieldLogger) *http.Request

Updates the logrus.FieldLogger in the context with added data. Requests are logged by Transaction.ReturnData/ReturnError.

Types

type ProviderConfig

type ProviderConfig interface {
	// Register should validate the provider configuration and return a handler
	// for requests to the provider. The provider can call GetTransaction to
	// receive user state from the in-progress SSO transaction. The Transaction
	// can be used to return data or error messages to the relying party.
	Register(sealKey string, auth tokenizer.AuthConfig) (http.Handler, error)
}

Arbitrary configuration type for providers to implement.

type Server

type Server struct {
	Address string
	Done    chan struct{}
	Err     error
	// contains filtered or unexported fields
}

func NewServer

func NewServer(sealKey string) *Server

Returns a new Server. When a user successfully completes SSO, the sealKey is used to encrypt the resulting token for use with tokenizer. The rpAuth is set as the authentication token for the tokenizer sealed token and must be provided to tokenizer by the relying party in order to use the sealed token.

func (*Server) AddProvider

func (s *Server) AddProvider(name string, pc ProviderConfig, returnURL string, auth tokenizer.AuthConfig) error

Configure the server with an SSO provider. The name dictates the path that the provider's routes are served under. The returnURL is where the user is returned after an SSO transaction completes.

func (*Server) ServeHTTP

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

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Gracefully shut down the server. If the context is cancelled before the shutdown completes, the server will be shutdown immediately.

func (*Server) Start

func (s *Server) Start(address string) error

Start the server in a goroutine, listening at the specified address (host:port).

type Transaction

type Transaction struct {
	// Random state string that will be returned in our redirect to the relying
	//  party. This is used to prevent login-CSRF attacks.
	ReturnState string

	// Random string that provider implementations can use as the state
	// parameter for downstream SSO flows.
	Nonce string

	// Time after which this transaction cookie will be ignored.
	Expiry time.Time
}

State about the user's SSO attempt that is stored as a cookie. Cookies are set with per-provider paths to prevent transactions from different providers from interfering with each other.

func GetTransaction

func GetTransaction(r *http.Request) *Transaction

func (*Transaction) ReturnData

func (t *Transaction) ReturnData(w http.ResponseWriter, r *http.Request, data map[string]string)

Return the user to the returnURL with the provided data set as query string parameters.

func (*Transaction) ReturnError

func (t *Transaction) ReturnError(w http.ResponseWriter, r *http.Request, msg string)

Return the user to the returnURL with the provided msg set in the `error` query string parameter.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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