-
-
Notifications
You must be signed in to change notification settings - Fork 364
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
aeneasr
committed
Jan 2, 2016
1 parent
7adad58
commit 480af91
Showing
27 changed files
with
1,329 additions
and
2 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.idea | ||
*.iml | ||
.cover | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
sudo: required | ||
|
||
services: | ||
- docker | ||
|
||
env: | ||
- DOCKER_BIND_LOCALHOST=true | ||
|
||
language: go | ||
|
||
go: | ||
- 1.5 | ||
|
||
install: | ||
- go get golang.org/x/tools/cmd/vet | ||
- go get github.com/axw/gocov/gocov | ||
- go get github.com/mattn/goveralls | ||
- go get golang.org/x/tools/cmd/cover | ||
- go get github.com/golang/lint/golint | ||
- go get -t ./... | ||
|
||
script: | ||
- go vet -x ./... | ||
- ./coverage --coveralls |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# Contribution Guide | ||
|
||
We welcome and encourage community contributions to Fosite. | ||
|
||
Since the project is still unstable, there are specific priorities for development. Pull requests that do not address these priorities will not be accepted until Fosite is production ready. | ||
|
||
Please familiarize yourself with the Contribution Guidelines and Project Roadmap before contributing. | ||
|
||
There are many ways to help Fosite besides contributing code: | ||
|
||
- Fix bugs or file issues | ||
- Improve the documentation | ||
|
||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
**Table of Contents** | ||
|
||
- [Contributing Code](#contributing-code) | ||
- [Code Style](#code-style) | ||
- [Developer’s Certificate of Origin](#developer%E2%80%99s-certificate-of-origin) | ||
- [Pull request procedure](#pull-request-procedure) | ||
- [Conduct](#conduct) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
## Contributing Code | ||
|
||
Unless you are fixing a known bug, we **strongly** recommend discussing it with the core team via a GitHub issue before getting started to ensure your work is consistent with Fosite's roadmap and architecture. | ||
|
||
All contributions are made via pull request. Note that **all patches from all contributors get reviewed**. After a pull request is made other contributors will offer feedback, and if the patch passes review a maintainer will accept it with a comment. When pull requests fail testing, authors are expected to update their pull requests to address the failures until the tests pass and the pull request merges successfully. | ||
|
||
At least one review from a maintainer is required for all patches (even patches from maintainers). | ||
|
||
Reviewers should leave a "LGTM" comment once they are satisfied with the patch. If the patch was submitted by a maintainer with write access, the pull request should be merged by the submitter after review. | ||
|
||
## Code Style | ||
|
||
Please follow these guidelines when formatting source code: | ||
|
||
* Go code should match the output of `gofmt -s` | ||
|
||
## Developer’s Certificate of Origin | ||
|
||
All contributions must include acceptance of the DCO: | ||
|
||
```text | ||
Developer Certificate of Origin | ||
Version 1.1 | ||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors. | ||
660 York Street, Suite 102, | ||
San Francisco, CA 94110 USA | ||
Everyone is permitted to copy and distribute verbatim copies of this | ||
license document, but changing it is not allowed. | ||
Developer's Certificate of Origin 1.1 | ||
By making a contribution to this project, I certify that: | ||
(a) The contribution was created in whole or in part by me and I | ||
have the right to submit it under the open source license | ||
indicated in the file; or | ||
(b) The contribution is based upon previous work that, to the best | ||
of my knowledge, is covered under an appropriate open source | ||
license and I have the right under that license to submit that | ||
work with modifications, whether created in whole or in part | ||
by me, under the same open source license (unless I am | ||
permitted to submit under a different license), as indicated | ||
in the file; or | ||
(c) The contribution was provided directly to me by some other | ||
person who certified (a), (b) or (c) and I have not modified | ||
it. | ||
(d) I understand and agree that this project and the contribution | ||
are public and that a record of the contribution (including all | ||
personal information I submit with it, including my sign-off) is | ||
maintained indefinitely and may be redistributed consistent with | ||
this project or the open source license(s) involved. | ||
``` | ||
|
||
To accept the DCO, simply add this line to each commit message with your name and email address (`git commit -s` will do this for you): | ||
|
||
```text | ||
Signed-off-by: Jane Example <[email protected]> | ||
``` | ||
|
||
For legal reasons, no anonymous or pseudonymous contributions are accepted ([contact us](mailto:[email protected]) if this is an issue). | ||
|
||
## Pull request procedure | ||
|
||
To make a pull request, you will need a GitHub account; if you are unclear on this process, see GitHub's documentation on [forking](https://help.github.com/articles/fork-a-repo) and [pull requests](https://help.github.com/articles/using-pull-requests). Pull requests should be targeted at the `master` branch. Before creating a pull request, go through this checklist: | ||
|
||
1. Create a feature branch off of `master` so that changes do not get mixed up. | ||
1. [Rebase](http://git-scm.com/book/en/Git-Branching-Rebasing) your local changes against the `master` branch. | ||
1. Run the full project test suite with the `go test ./...` (or equivalent) command and confirm that it passes. | ||
1. Run `gofmt -s` (if the project is written in Go). | ||
1. Accept the Developer's Certificate of Origin on all commits (see above). | ||
1. Ensure that each commit has a subsystem prefix (ex: `controller: `). | ||
|
||
Pull requests will be treated as "review requests," and maintainers will give feedback on the style and substance of the patch. | ||
|
||
Normally, all pull requests must include tests that test your change. Occasionally, a change will be very difficult to test for. In those cases, please include a note in your commit message explaining why. | ||
|
||
## Conduct | ||
|
||
Whether you are a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. | ||
|
||
* We are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, disability, ethnicity, religion, or similar personal characteristic. | ||
* Please avoid using nicknames that might detract from a friendly, safe and welcoming environment for all. | ||
* Be kind and courteous. There is no need to be mean or rude. | ||
* We will exclude you from interaction if you insult, demean or harass anyone. In particular, we do not tolerate behavior that excludes people in socially marginalized groups. | ||
* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or a member of the Fosite core team immediately. | ||
* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behaviour is not welcome. | ||
|
||
We welcome discussion about creating a welcoming, safe, and productive environment for the community. If you have any questions, feedback, or concerns please let us know with a GitHub issue. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Aeneas Rekkas <[email protected]> (github: arekkas) | ||
Thomas Aidan Curran <[email protected]> (github: tacurran) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,176 @@ | ||
# oauth2 | ||
A simple and extensible oauth2 server framework | ||
# ![Fosite](fosite.png) | ||
|
||
Simple and extensible OAuth2 server-side helpers with enterprise security and zero suck. | ||
This library implements [rfc6749](https://tools.ietf.org/html/rfc6749) and enforces countermeasures suggested in [rfc6819](https://tools.ietf.org/html/rfc6819). | ||
|
||
[![Build Status](https://travis-ci.org/ory-am/fosite.svg?branch=master)](https://travis-ci.org/ory-am/fosite?branch=master) | ||
[![Coverage Status](https://coveralls.io/repos/ory-am/fosite/badge.svg?branch=master&service=github)](https://coveralls.io/github/ory-am/fosite?branch=master) | ||
|
||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
**Table of Contents** | ||
|
||
- [Motivation](#motivation) | ||
- [Good to know](#good-to-know) | ||
- [Security](#security) | ||
- [Encourage security by enforcing it!](#encourage-security-by-enforcing-it) | ||
- [Secure Tokens](#secure-tokens) | ||
- [No state, no token](#no-state-no-token) | ||
- [Opaque tokens](#opaque-tokens) | ||
- [Advanced Token Validation](#advanced-token-validation) | ||
- [Encrypt credentials at rest](#encrypt-credentials-at-rest) | ||
- [Implement peer reviewed IETF Standards](#implement-peer-reviewed-ietf-standards) | ||
- [Provide extensibility and interoperability](#provide-extensibility-and-interoperability) | ||
- [Tokens](#tokens) | ||
- [Usage](#usage) | ||
- [Store](#store) | ||
- [Authorize Endpoint](#authorize-endpoint) | ||
- [OpenID Connect](#openid-connect) | ||
- [Token Endpoint](#token-endpoint) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
## Motivation | ||
|
||
Why write another OAuth2 server side library for Go Lang? | ||
|
||
Other libraries are perfect for a non-critical set ups, but [fail](https://github.com/RangelReale/osin/issues/107) to comply with enterprise security standards. | ||
This is unfortunately not an issue exclusive to Go's eco system but to many other eco systems as well. | ||
|
||
OpenID Connect on top of OAuth2? Not possible with popular OAuth2 libraries. Current libraries do not support capture | ||
the extensibility of OAuth2 and instead bind you to a pattern-enforcing framework with almost no possibilities for extension. | ||
|
||
Fosite was written because [Hydra](https://github.com/ory-am/hydra) required a more secure and extensible OAuth2 library | ||
then the one it was using. | ||
|
||
## Good to know | ||
|
||
Fosite is in early development. We will use gopkg for releasing new versions of the API. | ||
Be aware that "go get github.com/ory-am/fosite" will give you the master branch, which is and always will be *unstable*. | ||
Once releases roll out, you will be able to fetch a specific fosite API version through gopkg.in. | ||
|
||
## Security | ||
|
||
Fosite has two commandments. | ||
|
||
### Encourage security by enforcing it! | ||
|
||
#### Secure Tokens | ||
|
||
Tokens are generated with a minimum entropy of 256 bit. You can use more, if you want. | ||
|
||
#### No state, no token | ||
|
||
Without a random-looking state, *GET /oauth2/auth* will fail. | ||
|
||
#### Opaque tokens | ||
|
||
Token generators should know nothing about the request or context. | ||
|
||
#### Advanced Token Validation | ||
|
||
Tokens are layouted as `<key>.<signature>`. The following workflow requires an attacker to gain | ||
|
||
a. access to the database | ||
b. write permission in the persistent store, | ||
c. get hold of the token encryption secret. | ||
|
||
A database leak or (exclusively) the knowledge of the token encrpytion secret are not enough to maliciously obtain or create a valid token. Tokens and credentials can | ||
however still be stolen by man-in-the-middle attacks, by malicious or vulnerable clients and other attack vectors. | ||
* Issuance | ||
1. The key is hashed using BCrypt (variable) and used as `<signature>`. | ||
2. The client is presented with `<key>.<signature>`. | ||
3. The signature is encrypted and stored in the database using AES (variable). | ||
* Validation | ||
1. The client presents `<key>.<signature>`. | ||
2. It is validated if <key> matches <signature> using BCrypt (variable). | ||
3. The signature is encrypted using AES (variable). | ||
4. The encrypted signature is looked up in the database, failing validation if no such row exists. | ||
5. They key is considered valid and is now subject for other validations, like audience, redirect or state matching. | ||
|
||
#### Encrypt credentials at rest | ||
|
||
Credentials (tokens, passwords and secrets) are always encrypted at rest. | ||
|
||
#### Implement peer reviewed IETF Standards | ||
|
||
Fosite implements [rfc6749](https://tools.ietf.org/html/rfc6749) and enforces countermeasures suggested in [rfc6819](https://tools.ietf.org/html/rfc6819). | ||
|
||
### Provide extensibility and interoperability | ||
|
||
... because OAuth2 is an extensible and flexible **framework**. Fosite let's you register new response types, new grant | ||
types and new response key value pares. This is useful, if you want to provide OpenID Connect on top of your | ||
OAuth2 stack. Or custom assertions, what ever you like and as long as it is secure. ;) | ||
|
||
### Tokens | ||
|
||
Tokens are formatted as `<key>.<signature>`. This is beneficial if you want to keep tokens encrypted at rest. | ||
To validate a token in a OAuth2 grant, you could first check if the key matches the signature and then lookup the signature | ||
in your persistent storage (e.g. MySQL). If your persistent storage is intruded (e.g. by SQL injection), an attacker would | ||
only have access to the token signatures and would be, because he does not know the key, unable to use them for authorization. | ||
|
||
A token generated by `generator.CryptoGenerator` looks like: | ||
|
||
``` | ||
GUULhK6Od/7UAlnKvMau8APHSKXSRwm9aoOk56SHBns.JDJhJDEwJDdwVmpCQmJLYzM2VDg1VHJ5aEdVOE81NVdRSkt6bHBHR1QwOC9pbTNFWmpQRXliTWRPeDQy | ||
``` | ||
|
||
## Usage | ||
|
||
This section is WIP and we welcome discussions via PRs or in the issues. | ||
|
||
### Store | ||
|
||
### Authorize Endpoint | ||
|
||
```go | ||
var r *http.Request // we're assuming that we are inside a http.Handler | ||
var rw http.ResponseWriter // we're assuming that we are inside a http.Handler | ||
|
||
var store fosite.Storage // needs to be implemented or by using some library | ||
config := fosite.NewDefaultConfig() | ||
oauth := fosite.NewOAuth(config) | ||
authorizeRequest, err := oauth.NewAuthorizeRequest(r, store) | ||
if err != nil { | ||
oauth.RedirectError(rw, error) | ||
// or, for example: oauth.WriteError(rw, error) | ||
return | ||
} | ||
|
||
// you have now access to authorizeRequest.Scope, ...Code ...ResponseTypes ...Scopes ... | ||
|
||
// decide what to do based on scope and response type | ||
// e.g: response, err = oauth.HandleAuthorizeRequest(authorizeRequest) | ||
|
||
// set up a session | ||
// session := oauth2.NewAuthorizeSession(123) | ||
// session.SetExtra(extra interface{}) | ||
|
||
// persist that stuff in the database | ||
// err = oauth2.PersistAuthorizeRequest(authorizeRequest, session) // sets e.g. session.Persistent = true | ||
|
||
// finally, persist code in store and send response | ||
// e.g: oauth2.WriteResponse(rw, response, session) | ||
``` | ||
|
||
Because each component returns a different type, we can be (if safeguards are installed) quite sure, that the developer | ||
implemented the work flow the right way: | ||
|
||
1. `NewAuthorizeRequest(args...) *AuthorizeRequest`: Fetch authorize request information | ||
2. do whatever you like | ||
3. `HandleAuthorizeRequest(args...) *AuthorizeResponse`: Handle authorize request (check scopes and response types, hydrate response...) | ||
4. do whatever you like | ||
5. `oauth2.NewAuthorizeSession(*AuthorizeResponse) *AuthorizeSession`: A session | ||
6. do whatever you like, e.g. `session.SetExtra(map[string]interface{"foo": "bar"})` | ||
7. `oauth2.PersistAuthorizeRequest` persists the request in the database so the token endpoint can look up information | ||
8. do whatever you like | ||
9. `oauth2.WriteResponse(rw, response, session)` to write the response | ||
10. done. | ||
|
||
It is not clear yet how HandleAuthorizeRequest could be extensible. It might be possible to introduce an interface like AuthorizeStrategy | ||
and implement different strategies like IDTokenStrategy, AuthorizeCodeStrategy, AccessTokenStrategy. | ||
What could be tricky though is to define a good response / result model because the strategies be very different in execution logic and requirements. | ||
|
||
### OpenID Connect | ||
|
||
### Token Endpoint |
Oops, something went wrong.