/fosite

Extensible security first OAuth2 and OpenID Connect framework for Google's Go Language.

Primary LanguageGoApache License 2.0Apache-2.0

Fosite security first OAuth2 framework

The security first OAuth2 & OpenID Connect framework for Google's Go Language. Built simple, powerful and extensible. This library implements peer-reviewed IETF RFC6749, counterfeits weaknesses covered in peer-reviewed IETF RFC6819 and countermeasures various database attack scenarios, keeping your application safe when that hacker penetrates or leaks your database. OpenID Connect is implemented according to OpenID Connect Core 1.0 incorporating errata set 1 and includes all flows: code, implicit, hybrid.

Build Status Coverage Status Go Report Card

During development, we reviewed the following open specifications:

Table of Contents

Motivation

Fosite was written because our OAuth2 and OpenID Connect service Hydra required a secure and extensible OAuth2 library. We had to realize that nothing matching our requirements was out there, so we decided to build it ourselves.

API Stability

The core public API is almost stable as most changes will only touch the inner workings.

We strongly encourage vendoring fosite using glide or comparable tools.

Example

The example does not have nice visuals but it should give you an idea of what you can do with Fosite and a few lines of code.

Authorize Code Grant

You can run this minimalistic example by doing

go get github.com/Masterminds/glide
go get -d github.com/ory-am/fosite
cd $GOPATH/src/github.com/ory-am/fosite
glide install
go install github.com/ory-am/fosite/fosite-example
fosite-example

There should be a server listening on localhost:3846. You can check out the example's source code here.

A word on quality

We tried to set up as many tests as possible and test for as many cases covered in the RFCs as possible. But we are only human. Please, feel free to add tests for the various cases defined in the OAuth2 RFCs 6749 and 6819 or any other cases that improve the tests.

Everyone writing an RFC conform test that breaks with the current implementation, will receive a place in the Hall of Fame!

A word on security

Please be aware that Fosite only secures parts your server side security. You still need to secure your apps and clients, keep your tokens safe, prevent CSRF attacks, ensure database security, use valid and strong TLS certificates and much more. If you need any help or advice feel free to contact our security staff through our website!

We have given the various specifications, especially OAuth 2.0 Threat Model and Security Considerations, a very close look and included everything we thought was in the scope of this framework. Here is a complete list of things we implemented in Fosite:

Additionally, we added these safeguards:

  • Enforcing random states: Without a random-looking state or OpenID Connect nonce the request will fail.
  • Advanced Token Validation: Tokens are layouted as <key>.<signature> where <signature> is created using HMAC-SHA256 using a global secret. This is what a token can look like: /tgBeUhWlAT8tM8Bhmnx+Amf8rOYOUhrDi3pGzmjP7c=.BiV/Yhma+5moTP46anxMT6cWW8gz5R5vpC9RbpwSDdM=
  • Enforging scopes: By default, you always need to include the fosite scope or fosite will not execute the request properly. Obviously, you can change the scope to basic or core but be aware that you should use scopes if you use OAuth2.

Sections below Section 5 that are not covered in the list above should be reviewed by you. If you think that a specific section should be something that is covered in Fosite, feel free to create an issue. Please be aware that OpenID Connect requires specific knowledge of the identity provider, which is why Fosite only implements core requirements and most things must be implemented by you (for example prompt, max_age, ui_locales, id_token_hint, user authentication, session management, ...).

It is strongly encouraged to use the handlers shipped with Fosite as they follow the specs and are well tested.

A word on extensibility

Fosite is extensible ... because OAuth2 is an extensible and flexible framework. Fosite let's you register custom token and authorize endpoint handlers with the security that the requests have been validated against the OAuth2 specs beforehand. You can easily extend Fosite's capabilities. For example, if you want to provide OpenID Connect on top of your OAuth2 stack, that's no problem. Or custom assertions, what ever you like and as long as it is secure. ;)

Usage

There is an API documentation available at godoc.org/ory-am/fosite.

Installation

You will need Go installed on your machine and it is required that you have set up your GOPATH environment variable.

go get -d github.com/ory-am/fosite

We recommend to use Glide or Godep, because there might be breaking changes in the future.

Examples

Take a look at these real-life implementations:

Exemplary Storage Implementation

Fosite does not ship a storage implementation yet. To get fosite running, you need to implement github.com/ory-am/fosite.Storage. Additionally, most of the token / authorize endpoint handlers require a dedicated store implementation as well. You could however use one struct to implement all the signatures.

You can find a working store implementation at fosite-example/internal/store.go.

Extensible handlers

You can replace the Token and Authorize endpoint logic by modifying Fosite.TokenEndpointHandlers and Fosite.AuthorizeEndpointHandlers.

Let's take the explicit authorize handler. He is responsible for handling the authorize code workflow.

If you want to enable the handler able to handle this workflow, you can do this:

var accessTokenLifespan = time.Hour
var authorizeCodeLifespan = time.Minute * 10

var hmacStrategy = &strategy.HMACSHAStrategy{
	Enigma: &enigma.Enigma{
		GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows"),
	},
	AccessTokenLifespan: accessTokenLifespan,
	AuthorizeCodeLifespan: authorizeCodeLifespan,
}

// var store = ...

var f = NewFosite(store)

// Let's enable the explicit authorize code grant!
explicitHandler := &explicit.AuthorizeExplicitGrantTypeHandler{
    AccessTokenStrategy:   hmacStrategy,
    RefreshTokenStrategy:  hmacStrategy,
    AuthorizeCodeStrategy: hmacStrategy,
    Store:                 store,
    AuthCodeLifespan:      authorizeCodeLifespan,
    AccessTokenLifespan:   accessTokenLifespan,
}

// Please note that order matters!
f.AuthorizeEndpointHandlers.Append(explicitHandler)
f.TokenEndpointHandlers.Append(explicitHandler)

As you probably noticed, there are two types of handlers, one for the authorization /auth endpoint and one for the token /token endpoint. The AuthorizeExplicitEndpointHandler implements API requirements for both endpoints, while, for example, the AuthorizeImplicitEndpointHandler only implements the AuthorizeEndpointHandler API.

You can find a complete list of handlers inside the handler directory. A short list is documented here:

There are also OpenID Connect Handlers available.

Develop fosite

You need git and golang installed on your system.

go get -d github.com/ory-am/fosite
cd $GOPATH/src/github.com/ory-am/fosite
git status
git remote add myfork <url-to-your-fork>
go test ./...

Simple, right? Now you are ready to go! Make sure to run go test ./... often, detecting problems with your code rather sooner than later.

Refresh mock objects

Run ./generate-mocks.sh in fosite's root directory or run the contents of [generate-mocks.sh] in a shell.

Known Limitations and Issues

  • Validator handler receives empty Request object

Hall of Fame

This place is reserved for the fearless bug hunters, reviewers and contributors (alphabetical order).

Find out more about the author of Fosite and Hydra, and the Ory Company.