diff --git a/client/client.go b/client/client.go index 15b7286aca3..23ce612bb1f 100644 --- a/client/client.go +++ b/client/client.go @@ -1,8 +1,9 @@ package client import ( - "github.com/ory-am/fosite" "strings" + + "github.com/ory-am/fosite" ) type Client struct { @@ -12,7 +13,7 @@ type Client struct { RedirectURIs []string `json:"redirect_uris" gorethink:"redirect_uris"` GrantTypes []string `json:"grant_types" gorethink:"grant_types"` ResponseTypes []string `json:"response_types" gorethink:"response_types"` - Scopes string `json:"scopes" gorethink:"scopes"` + Scope string `json:"scope" gorethink:"scope"` Owner string `json:"owner" gorethink:"owner"` PolicyURI string `json:"policy_uri" gorethink:"policy_uri"` TermsOfServiceURI string `json:"tos_uri" gorethink:"tos_uri"` @@ -34,7 +35,7 @@ func (c *Client) GetHashedSecret() []byte { } func (c *Client) GetScopes() fosite.Arguments { - return fosite.Arguments(strings.Split(c.Scopes, " ")) + return fosite.Arguments(strings.Split(c.Scope, " ")) } func (c *Client) GetGrantTypes() fosite.Arguments { diff --git a/cmd/cli/handler_client.go b/cmd/cli/handler_client.go index 48a532ae89e..578282a07c2 100644 --- a/cmd/cli/handler_client.go +++ b/cmd/cli/handler_client.go @@ -5,11 +5,12 @@ import ( "fmt" "os" + "strings" + "github.com/ory-am/hydra/client" "github.com/ory-am/hydra/config" "github.com/ory-am/hydra/pkg" "github.com/spf13/cobra" - "strings" ) type ClientHandler struct { @@ -70,7 +71,7 @@ func (h *ClientHandler) CreateClient(cmd *cobra.Command, args []string) { ID: id, Secret: string(secret), ResponseTypes: responseTypes, - Scopes: strings.Join(allowedScopes, " "), + Scope: strings.Join(allowedScopes, " "), GrantTypes: grantTypes, RedirectURIs: callbacks, Name: name, diff --git a/cmd/server/helper_client.go b/cmd/server/helper_client.go index 2c0f8c9c9eb..f38ea79cc17 100644 --- a/cmd/server/helper_client.go +++ b/cmd/server/helper_client.go @@ -42,7 +42,7 @@ func (h *Handler) createRootIfNewInstall(c *config.Config) { Name: "This temporary client is generated by hydra and is granted all of hydra's administrative privileges. It must be removed when everything is set up.", ResponseTypes: []string{"id_token", "code", "token"}, GrantTypes: []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"}, - Scopes: "hydra openid offline", + Scope: "hydra openid offline", RedirectURIs: []string{"http://localhost:4445/callback"}, Secret: secret, } @@ -63,8 +63,8 @@ func (h *Handler) createRootIfNewInstall(c *config.Config) { logrus.Infoln("Temporary root client created.") if forceRoot == "" { - logrus.Infoln("client_id: %s", root.GetID()) - logrus.Infoln("client_secret: %s", string(secret)) + logrus.Infof("client_id: %s", root.GetID()) + logrus.Infof("client_secret: %s", string(secret)) logrus.Warn("WARNING: YOU MUST delete this client once in production, as credentials may have been leaked logfiles.") } } diff --git a/config/config.go b/config/config.go index e5745ce57ae..688d4541968 100644 --- a/config/config.go +++ b/config/config.go @@ -52,6 +52,7 @@ type Config struct { cluster *url.URL `yaml:"-"` oauth2Client *http.Client `yaml:"-"` context *Context `yaml:"-"` + systemSecret []byte } func matchesRange(r *http.Request, ranges []string) error { @@ -238,11 +239,15 @@ func (c *Config) OAuth2Client(cmd *cobra.Command) *http.Client { } func (c *Config) GetSystemSecret() []byte { + if len(c.systemSecret) > 0 { + return c.systemSecret + } + var secret = []byte(c.SystemSecret) if len(secret) >= 16 { hash := sha256.Sum256(secret) secret = hash[:] - c.SystemSecret = string(secret) + c.systemSecret = secret return secret } @@ -254,7 +259,7 @@ func (c *Config) GetSystemSecret() []byte { logrus.Infof("Generated system secret: %s", secret) hash := sha256.Sum256(secret) secret = hash[:] - c.SystemSecret = string(secret) + c.systemSecret = secret logrus.Warnln("WARNING: DO NOT generate system secrets in production. The secret will be leaked to the logs.") return secret } diff --git a/config/config_test.go b/config/config_test.go index baa1670b914..bf0a7c6b72e 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1,8 +1,72 @@ package config -import "testing" +import ( + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) func TestConfig(t *testing.T) { c := &Config{} _ = c.Context() + + assert.Equal(t, c.GetAccessTokenLifespan(), time.Hour) +} + +func TestDoesRequestSatisfyTermination(t *testing.T) { + c := &Config{AllowTLSTermination: ""} + assert.NotNil(t, c.DoesRequestSatisfyTermination(new(http.Request))) + + c = &Config{AllowTLSTermination: "127.0.0.1/24"} + r := &http.Request{Header: http.Header{}} + assert.NotNil(t, c.DoesRequestSatisfyTermination(r)) + + r = &http.Request{Header: http.Header{"X-Forwarded-Proto": []string{"http"}}} + assert.NotNil(t, c.DoesRequestSatisfyTermination(r)) + + r = &http.Request{ + RemoteAddr: "227.0.0.1:123", + Header: http.Header{"X-Forwarded-Proto": []string{"https"}}, + } + assert.NotNil(t, c.DoesRequestSatisfyTermination(r)) + + r = &http.Request{ + RemoteAddr: "127.0.0.1:123", + Header: http.Header{"X-Forwarded-Proto": []string{"https"}}, + } + assert.Nil(t, c.DoesRequestSatisfyTermination(r)) +} + +func TestSystemSecret(t *testing.T) { + c3 := &Config{} + assert.EqualValues(t, c3.GetSystemSecret(), c3.GetSystemSecret()) + c := &Config{SystemSecret: "foobarbazbarasdfasdffoobarbazbarasdfasdf"} + assert.EqualValues(t, c.GetSystemSecret(), c.GetSystemSecret()) + c2 := &Config{SystemSecret: "foobarbazbarasdfasdffoobarbazbarasdfasdf"} + assert.EqualValues(t, c.GetSystemSecret(), c2.GetSystemSecret()) +} + +func TestResolve(t *testing.T) { + c := &Config{ClusterURL: "https://localhost:1234"} + assert.Equal(t, c.Resolve("foo", "bar").String(), "https://localhost:1234/foo/bar") + assert.Equal(t, c.Resolve("/foo", "/bar").String(), "https://localhost:1234/foo/bar") + + c = &Config{ClusterURL: "https://localhost:1234/"} + assert.Equal(t, c.Resolve("/foo", "/bar").String(), "https://localhost:1234/foo/bar") + + c = &Config{ClusterURL: "https://localhost:1234/bar"} + assert.Equal(t, c.Resolve("/foo", "/bar").String(), "https://localhost:1234/bar/foo/bar") +} + +func TestLifespan(t *testing.T) { + assert.Equal(t, (&Config{}).GetAccessTokenLifespan(), time.Hour) + assert.Equal(t, (&Config{AccessTokenLifespan: "6h"}).GetAccessTokenLifespan(), time.Hour*6) + + assert.Equal(t, (&Config{}).GetAuthCodeLifespan(), time.Minute*10) + assert.Equal(t, (&Config{AuthCodeLifespan: "15m"}).GetAuthCodeLifespan(), time.Minute*15) + + assert.Equal(t, (&Config{}).GetIDTokenLifespan(), time.Hour) + assert.Equal(t, (&Config{IDTokenLifespan: "10s"}).GetIDTokenLifespan(), time.Second*10) } diff --git a/doc.go b/doc.go index 0bd3c58d177..1d32270048e 100644 --- a/doc.go +++ b/doc.go @@ -6,4 +6,4 @@ // Hydra is built for high throughput environments. Check out the below siege benchmark on a Macbook Pro Late 2013, connected to RethinkDB validating access tokens. // // The official repository is located at https://github.com/ory-am/hydra -package main \ No newline at end of file +package main diff --git a/oauth2/consent_strategy.go b/oauth2/consent_strategy.go index c5479bf9d49..722310599ce 100644 --- a/oauth2/consent_strategy.go +++ b/oauth2/consent_strategy.go @@ -5,8 +5,8 @@ import ( "time" "crypto/rsa" - "github.com/dgrijalva/jwt-go" + "github.com/go-errors/errors" "github.com/ory-am/fosite" "github.com/ory-am/fosite/handler/openid" diff --git a/oauth2/oauth2_test.go b/oauth2/oauth2_test.go index f7c9636aab8..9825eb4b3eb 100644 --- a/oauth2/oauth2_test.go +++ b/oauth2/oauth2_test.go @@ -1,12 +1,12 @@ package oauth2_test import ( - "net/http/httptest" - "time" - "fmt" + "net/http/httptest" "net/url" + "time" + "github.com/dgrijalva/jwt-go" "github.com/go-errors/errors" "github.com/julienschmidt/httprouter" "github.com/ory-am/fosite" @@ -19,7 +19,6 @@ import ( "github.com/ory-am/hydra/pkg" "golang.org/x/oauth2" "golang.org/x/oauth2/clientcredentials" - "github.com/dgrijalva/jwt-go" ) var hasher = &hash.BCrypt{} @@ -87,7 +86,7 @@ func init() { RedirectURIs: []string{ts.URL + "/callback"}, ResponseTypes: []string{"id_token", "code", "token"}, GrantTypes: []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"}, - Scopes: "hydra", + Scope: "hydra", } c, _ := url.Parse(ts.URL + "/consent") @@ -100,7 +99,7 @@ func init() { RedirectURIs: []string{ts.URL + "/callback"}, ResponseTypes: []string{"id_token", "code", "token"}, GrantTypes: []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"}, - Scopes: "hydra", + Scope: "hydra", } oauthConfig = &oauth2.Config{ diff --git a/warden/warden_http.go b/warden/warden_http.go index 482d563fe28..780f18e20c6 100644 --- a/warden/warden_http.go +++ b/warden/warden_http.go @@ -4,6 +4,11 @@ import ( "net/http" "net/url" + "bytes" + "encoding/json" + "io/ioutil" + "strconv" + "github.com/go-errors/errors" "github.com/ory-am/fosite" "github.com/ory-am/hydra/firewall" @@ -12,10 +17,6 @@ import ( "golang.org/x/net/context" "golang.org/x/oauth2" "golang.org/x/oauth2/clientcredentials" - "bytes" - "io/ioutil" - "strconv" - "encoding/json" ) type HTTPWarden struct {