Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.5.0 #243

Merged
merged 15 commits into from
Sep 22, 2016
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ script:
- $GOPATH/bin/hydra token client --skip-tls-verify

after_success:
- gox -ldflags "-X main.Version=`git describe --tags` -X main.BuildTime=`TZ=UTC date -u '+%Y-%m-%dT%H:%M:%SZ'` -X main.GitHash=`git rev-parse HEAD`" -output "dist/{{.Dir}}-{{.OS}}-{{.Arch}}"
# - ghr --username arekkas --token $GITHUB_TOKEN --replace --prerelease --debug pre-release dist/
- gox -ldflags "-X github.com/ory-am/hydra/cmd.Version=`git describe --tags` -X github.com/ory-am/hydra/cmd.BuildTime=`TZ=UTC date -u '+%Y-%m-%dT%H:%M:%SZ'` -X github.com/ory-am/hydra/cmd.GitHash=`git rev-parse HEAD`" -output "dist/{{.Dir}}-{{.OS}}-{{.Arch}}"

deploy:
provider: releases
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ![Ory/Hydra](docs/dist/images/logo.png)
# ![Ory/Hydra](docs/images/logo.png)

[![Join the chat at https://gitter.im/ory-am/hydra](https://img.shields.io/badge/join-chat-00cc99.svg)](https://gitter.im/ory-am/hydra?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join mailinglist](https://img.shields.io/badge/join-mailinglist-00cc99.svg)](https://groups.google.com/forum/#!forum/ory-hydra/new)
Expand Down Expand Up @@ -118,7 +118,7 @@ Hydra is packaged using [Docker](https://hub.docker.com/r/oryam/hydra/).
6. **Open Source:** Hydra is licensed under Apache Version 2.0
7. **Professional:** Hydra implements peer reviewed open standards published by [The Internet Engineering Task Force (IETF®)](https://www.ietf.org/) and the [OpenID Foundation](https://openid.net/)
and under supervision of the [LMU Teaching and Research Unit Programming and Modelling Languages](http://www.en.pms.ifi.lmu.de). No funny business.
8. <img src="docs/dist/images/monitoring.gif" width="45%" align="right"> **Real Time:** Operation is a lot easier with real time. There are no caches,
8. <img src="docs/images/monitoring.gif" width="45%" align="right"> **Real Time:** Operation is a lot easier with real time. There are no caches,
no invalidation strategies and no magic - just simple, cloud native pub-sub. Hydra leverages RethinkDB, so check out their real time database monitoring too!

<br clear="all">
Expand Down Expand Up @@ -188,7 +188,7 @@ The **[tutorial](https://ory-am.gitbooks.io/hydra/content/demo.html)** teaches y
a RethinkDB instance and an exemplary identity provider written in React using docker compose.
It will take you about 5 minutes to get complete the **[tutorial](https://ory-am.gitbooks.io/hydra/content/demo.html)**.

<img src="docs/dist/images/oauth2-flow.gif" alt="OAuth2 Flow">
<img src="docs/images/oauth2-flow.gif" alt="OAuth2 Flow">

<br clear="all">

Expand Down
40 changes: 37 additions & 3 deletions client/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"net/http"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"github.com/julienschmidt/httprouter"
"github.com/ory-am/common/rand/sequence"
"github.com/ory-am/hydra/firewall"
Expand Down Expand Up @@ -33,6 +33,7 @@ func (h *Handler) SetRoutes(r *httprouter.Router) {
r.GET(ClientsHandlerPath, h.GetAll)
r.POST(ClientsHandlerPath, h.Create)
r.GET(ClientsHandlerPath+"/:id", h.Get)
r.PUT(ClientsHandlerPath+"/:id", h.Update)
r.DELETE(ClientsHandlerPath+"/:id", h.Delete)
}

Expand All @@ -41,7 +42,7 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
var ctx = herodot.NewContext()

if err := json.NewDecoder(r.Body).Decode(&c); err != nil {
h.H.WriteError(ctx, w, r, errors.New(err))
h.H.WriteError(ctx, w, r, errors.Wrap(err, ""))
return
}

Expand All @@ -59,7 +60,7 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
if len(c.Secret) == 0 {
secret, err := sequence.RuneSequence(12, []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-.,:;$%!&/()=?+*#<>"))
if err != nil {
h.H.WriteError(ctx, w, r, errors.New(err))
h.H.WriteError(ctx, w, r, errors.Wrap(err, ""))
return
}
c.Secret = string(secret)
Expand All @@ -77,6 +78,39 @@ func (h *Handler) Create(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
h.H.WriteCreated(ctx, w, r, ClientsHandlerPath+"/"+c.GetID(), &c)
}

func (h *Handler) Update(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var c Client
var ctx = herodot.NewContext()

if err := json.NewDecoder(r.Body).Decode(&c); err != nil {
h.H.WriteError(ctx, w, r, errors.Wrap(err, ""))
return
}

if _, err := h.W.TokenAllowed(ctx, h.W.TokenFromRequest(r), &ladon.Request{
Resource: ClientsResource,
Action: "update",
Context: ladon.Context{
"owner": c.Owner,
},
}, Scope); err != nil {
h.H.WriteError(ctx, w, r, err)
return
}

if len(c.Secret) > 0 && len(c.Secret) < 6 {
h.H.WriteError(ctx, w, r, errors.New("The client secret must be at least 6 characters long"))
}

c.ID = ps.ByName("id")
if err := h.Manager.UpdateClient(&c); err != nil {
h.H.WriteError(ctx, w, r, err)
return
}

h.H.WriteCreated(ctx, w, r, ClientsHandlerPath+"/"+c.GetID(), &c)
}

func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var ctx = herodot.NewContext()

Expand Down
2 changes: 2 additions & 0 deletions client/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type Storage interface {

CreateClient(c *Client) error

UpdateClient(c *Client) error

DeleteClient(id string) error

GetClients() (map[string]Client, error)
Expand Down
7 changes: 7 additions & 0 deletions client/manager_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ func (m *HTTPManager) GetClient(id string) (fosite.Client, error) {
return m.GetConcreteClient(id)
}

func (m *HTTPManager) UpdateClient(c *Client) error {
var r = pkg.NewSuperAgent(pkg.JoinURL(m.Endpoint, c.ID).String())
r.Client = m.Client
r.Dry = m.Dry
return r.Update(c)
}

func (m *HTTPManager) CreateClient(c *Client) error {
var r = pkg.NewSuperAgent(m.Endpoint.String())
r.Client = m.Client
Expand Down
34 changes: 29 additions & 5 deletions client/manager_memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package client
import (
"sync"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"github.com/ory-am/fosite"
"github.com/ory-am/fosite/hash"
"github.com/ory-am/hydra/pkg"
"github.com/pborman/uuid"
"github.com/imdario/mergo"
)

type MemoryManager struct {
Expand All @@ -22,7 +23,7 @@ func (m *MemoryManager) GetConcreteClient(id string) (*Client, error) {

c, ok := m.Clients[id]
if !ok {
return nil, errors.New(pkg.ErrNotFound)
return nil, errors.Wrap(pkg.ErrNotFound, "")
}
return &c, nil
}
Expand All @@ -31,17 +32,40 @@ func (m *MemoryManager) GetClient(id string) (fosite.Client, error) {
return m.GetConcreteClient(id)
}

func (m *MemoryManager) UpdateClient(c *Client) error {
o, err := m.GetClient(c.ID)
if err != nil {
return err
}

if c.Secret == "" {
c.Secret = string(o.GetHashedSecret())
} else {
h, err := m.Hasher.Hash([]byte(c.Secret))
if err != nil {
return errors.Wrap(err, "")
}
c.Secret = string(h)
}
if err := mergo.Merge(c, o); err != nil {
return errors.Wrap(err, "")
}

m.Clients[c.GetID()] = *c
return nil
}

func (m *MemoryManager) Authenticate(id string, secret []byte) (*Client, error) {
m.RLock()
defer m.RUnlock()

c, ok := m.Clients[id]
if !ok {
return nil, errors.New(pkg.ErrNotFound)
return nil, errors.Wrap(pkg.ErrNotFound, "")
}

if err := m.Hasher.Compare(c.GetHashedSecret(), secret); err != nil {
return nil, errors.New(err)
return nil, errors.Wrap(err, "")
}

return &c, nil
Expand All @@ -57,7 +81,7 @@ func (m *MemoryManager) CreateClient(c *Client) error {

hash, err := m.Hasher.Hash([]byte(c.Secret))
if err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}
c.Secret = string(hash)

Expand Down
58 changes: 46 additions & 12 deletions client/manager_rethinkdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import (
"time"

"github.com/Sirupsen/logrus"
"github.com/go-errors/errors"
"github.com/pkg/errors"
"github.com/ory-am/fosite"
"github.com/ory-am/fosite/hash"
"github.com/ory-am/hydra/pkg"
"github.com/pborman/uuid"
"golang.org/x/net/context"
r "gopkg.in/dancannon/gorethink.v2"
"github.com/imdario/mergo"
)

type RethinkManager struct {
Expand All @@ -29,7 +30,7 @@ func (m *RethinkManager) GetConcreteClient(id string) (*Client, error) {

c, ok := m.Clients[id]
if !ok {
return nil, errors.New(pkg.ErrNotFound)
return nil, errors.Wrap(pkg.ErrNotFound, "")
}
return &c, nil
}
Expand All @@ -44,11 +45,11 @@ func (m *RethinkManager) Authenticate(id string, secret []byte) (*Client, error)

c, ok := m.Clients[id]
if !ok {
return nil, errors.New(pkg.ErrNotFound)
return nil, errors.Wrap(pkg.ErrNotFound, "")
}

if err := m.Hasher.Compare(c.GetHashedSecret(), secret); err != nil {
return nil, errors.New(err)
return nil, errors.Wrap(err, "")
}

return &c, nil
Expand All @@ -59,11 +60,11 @@ func (m *RethinkManager) CreateClient(c *Client) error {
c.ID = uuid.New()
}

hash, err := m.Hasher.Hash([]byte(c.Secret))
h, err := m.Hasher.Hash([]byte(c.Secret))
if err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}
c.Secret = string(hash)
c.Secret = string(h)

if err := m.publishCreate(c); err != nil {
return err
Expand All @@ -72,6 +73,32 @@ func (m *RethinkManager) CreateClient(c *Client) error {
return nil
}

func (m *RethinkManager) UpdateClient(c *Client) error {
o, err := m.GetClient(c.ID)
if err != nil {
return err
}

if c.Secret == "" {
c.Secret = string(o.GetHashedSecret())
} else {
h, err := m.Hasher.Hash([]byte(c.Secret))
if err != nil {
return errors.Wrap(err, "")
}
c.Secret = string(h)
}
if err := mergo.Merge(c, o); err != nil {
return errors.Wrap(err, "")
}

if err := m.publishUpdate(c); err != nil {
return err
}

return nil
}

func (m *RethinkManager) DeleteClient(id string) error {
if err := m.publishDelete(id); err != nil {
return err
Expand All @@ -95,7 +122,7 @@ func (m *RethinkManager) ColdStart() error {
m.Clients = map[string]Client{}
clients, err := m.Table.Run(m.Session)
if err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}

var client Client
Expand All @@ -108,16 +135,23 @@ func (m *RethinkManager) ColdStart() error {
return nil
}

func (m *RethinkManager) publishUpdate(client *Client) error {
if err := m.publishDelete(client.ID); err != nil {
return err
}
return m.publishCreate(client)
}

func (m *RethinkManager) publishCreate(client *Client) error {
if _, err := m.Table.Insert(client).RunWrite(m.Session); err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}
return nil
}

func (m *RethinkManager) publishDelete(id string) error {
if _, err := m.Table.Get(id).Delete().RunWrite(m.Session); err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}
return nil
}
Expand All @@ -126,7 +160,7 @@ func (m *RethinkManager) Watch(ctx context.Context) {
go pkg.Retry(time.Second*15, time.Minute, func() error {
clients, err := m.Table.Changes().Run(m.Session)
if err != nil {
return errors.New(err)
return errors.Wrap(err, "")
}
defer clients.Close()

Expand All @@ -148,7 +182,7 @@ func (m *RethinkManager) Watch(ctx context.Context) {
}

if clients.Err() != nil {
err = errors.New(clients.Err())
err = errors.Wrap(clients.Err(), "")
pkg.LogError(err)
return err
}
Expand Down
Loading