diff --git a/Dockerfile b/Dockerfile index 9a662c36..d1f6e57a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,11 +3,9 @@ FROM golang:1.11.4-alpine as builder RUN apk add --no-cache make git gcc musl-dev g++ RUN go get -u github.com/gobuffalo/packr/packr WORKDIR /go/src/github.com/berty/staff/tools/release -COPY go.mod go.sum ./ -RUN GO111MODULE=on go mod download COPY . . RUN packr -RUN make install +RUN GO111MODULE=on go install -mod=vendor -v ./cmd/... # runtime FROM alpine diff --git a/Makefile b/Makefile index eb6a7c30..cca11fb8 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ install: .PHONY: docker.build docker.build: + go mod vendor docker build -t "$(IMAGE)" . .PHONY: docker.push diff --git a/go.mod b/go.mod index b218c627..5f906aff 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/mattn/go-colorable v0.0.9 // indirect github.com/mattn/go-isatty v0.0.4 // indirect github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 + github.com/pkg/errors v0.8.1 github.com/spf13/cobra v0.0.3 github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4 // indirect diff --git a/go.sum b/go.sum index 1fe419f5..aefd6c53 100644 --- a/go.sum +++ b/go.sum @@ -198,6 +198,7 @@ github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdK github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -399,6 +400,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190116161447-11f53e031339 h1:g/Jesu8+QLnA0CPzF3E1pURg0Byr7i6jLoX5sqjcAh0= golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -425,6 +427,7 @@ golang.org/x/tools v0.0.0-20190104182027-498d95493402/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190111214448-fc1d57b08d7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= diff --git a/server/auth.go b/server/auth.go index 87df7ef2..198bbbfd 100644 --- a/server/auth.go +++ b/server/auth.go @@ -14,19 +14,22 @@ import ( "github.com/gorilla/sessions" "github.com/labstack/echo" "github.com/labstack/echo-contrib/session" + "github.com/pkg/errors" "golang.org/x/oauth2" ) const ( - AuthDomain = "berty.eu.auth0.com" - ClientID = "yqYy0K16xwgWbwS3dISg87Iacz06PMmX" - ClientSecret = "laLoKBfijXRDkyksnX4OP-LgsWzWqMl41kcQp_XwUmM1KbWnI3dKRxdveuheHdue" - SessionSecret = "***REMOVED***" + AuthDomain = "berty.eu.auth0.com" + ClientID = "yqYy0K16xwgWbwS3dISg87Iacz06PMmX" + ClientSecret = "laLoKBfijXRDkyksnX4OP-LgsWzWqMl41kcQp_XwUmM1KbWnI3dKRxdveuheHdue" + SessionSecret = "***REMOVED***" + authSessionCookieName = "yolo-auth-session" + stateCookieName = "yolo-state" ) type OAuth struct { conf *oauth2.Config - sf *sessions.FilesystemStore + sf *sessions.CookieStore } func NewOAuth(redirectUrl string, e *echo.Echo) *OAuth { @@ -41,7 +44,7 @@ func NewOAuth(redirectUrl string, e *echo.Echo) *OAuth { }, } - sf := sessions.NewFilesystemStore("", []byte(SessionSecret)) + sf := sessions.NewCookieStore([]byte(SessionSecret)) gob.Register(map[string]interface{}{}) e.Use(session.Middleware(sf)) @@ -60,7 +63,7 @@ func (o *OAuth) ProtectMiddleware(failureRedirect string, fverify func(map[strin return next(c) } - sess, err := session.Get("auth-session", c) + sess, err := session.Get(authSessionCookieName, c) if err != nil { return c.Redirect(http.StatusTemporaryRedirect, failureRedirect) } @@ -85,22 +88,22 @@ func (o *OAuth) LoginHandler() func(echo.Context) error { return func(c echo.Context) error { aud := "https://" + AuthDomain + "/userinfo" - sess, err := session.Get("state", c) + sess, err := session.Get(stateCookieName, c) if err != nil { - c.Logger().Warn("invalid session: ", err.Error()) + c.Logger().Warn("Login: invalid session: ", err.Error()) } if sess == nil { - return echo.NewHTTPError(http.StatusInternalServerError, "invalid session") + return errors.Wrap(err, "Login: failed to get session") } b := make([]byte, 32) rand.Read(b) state := base64.StdEncoding.EncodeToString(b) - sess.Values["state"] = state + sess.Values[stateCookieName] = state if err := sess.Save(c.Request(), c.Response()); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Login: failed to save session") } audience := oauth2.SetAuthURLParam("audience", aud) @@ -115,10 +118,10 @@ func (o *OAuth) LogoutHandler(redirectUrl string) func(echo.Context) error { var logoutUrl *url.URL logoutUrl, err := url.Parse("https://" + AuthDomain) if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Logout: failed to parse auth domain") } - for _, ck := range []string{"auth-session", "state"} { + for _, ck := range []string{authSessionCookieName, stateCookieName} { cookie, err := c.Cookie(ck) if err == nil { cookie.MaxAge = -1 // erase the cookie @@ -146,44 +149,44 @@ func (o *OAuth) LogoutHandler(redirectUrl string) func(echo.Context) error { func (o *OAuth) CallbackHandler(redirectUrl string) func(echo.Context) error { return func(c echo.Context) error { state := c.QueryParam("state") - sess, err := session.Get("state", c) + sess, err := session.Get(stateCookieName, c) if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Callback: failed to get state") } - if state != sess.Values["state"] { - return echo.NewHTTPError(http.StatusInternalServerError, "invalid state") + if state != sess.Values[stateCookieName] { + return errors.Errorf("Callback: invalid state (%q != %q)", state, sess.Values[stateCookieName]) } code := c.QueryParam("code") token, err := o.conf.Exchange(context.TODO(), code) if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Callback: failed to do the code exchange") } client := o.conf.Client(context.TODO(), token) resp, err := client.Get("https://" + AuthDomain + "/userinfo") if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Callback: failed to get userinfo") } defer resp.Body.Close() var profile map[string]interface{} if err = json.NewDecoder(resp.Body).Decode(&profile); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Callback: failed to decode profile") } - sessAuth, err := session.Get("auth-session", c) + sessAuth, err := session.Get(authSessionCookieName, c) if err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "Callback: failed to get auth-session") } sessAuth.Values["id_token"] = token.Extra("id_token") sessAuth.Values["access_token"] = token.AccessToken sessAuth.Values["profile"] = profile if err := sessAuth.Save(c.Request(), c.Response()); err != nil { - return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) + return errors.Wrap(err, "failed to save session") } return c.Redirect(http.StatusSeeOther, redirectUrl) diff --git a/server/server.go b/server/server.go index 90585a77..c283c2f6 100644 --- a/server/server.go +++ b/server/server.go @@ -107,7 +107,10 @@ func NewServer(cfg *ServerConfig) (*Server, error) { randStr := randStringRunes(10) e := echo.New() + e.Debug = cfg.Debug e.Use(middleware.Logger()) + e.Use(middleware.Recover()) + e.Use(middleware.Gzip()) templatesBox := packr.NewBox("../templates") s := &Server{ client: cfg.Client,