Skip to content

Commit

Permalink
Store user session in browser
Browse files Browse the repository at this point in the history
  • Loading branch information
feedmeapples committed Sep 19, 2022
1 parent 5d0a358 commit 5a9eac5
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 294 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ e2e/test-results
e2e/playwright/.cache
e2e/.env


# session filesystem store path
.tmp

# Output of code generation tools
third_party/OpenAPI/temporal

Expand Down
30 changes: 2 additions & 28 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ import (
"fmt"
"os"
"path"
"path/filepath"

"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
"github.com/temporalio/ui-server/v2/plugins/forwardheaders"
"github.com/temporalio/ui-server/v2/plugins/fs_config_provider"
"github.com/temporalio/ui-server/v2/server"
"github.com/temporalio/ui-server/v2/server/api"
"github.com/temporalio/ui-server/v2/server/headers"
"github.com/temporalio/ui-server/v2/server/server_options"
"github.com/temporalio/ui-server/v2/server/version"
"github.com/urfave/cli/v2"
Expand Down Expand Up @@ -99,27 +96,10 @@ func buildCLI() *cli.App {
opts := []server_options.ServerOption{
server_options.WithConfigProvider(cfgProvider),
server_options.WithAPIMiddleware([]api.Middleware{
forwardheaders.WithForwardHeaders(cfg.ForwardHeaders),
headers.WithForwardHeaders(cfg.ForwardHeaders),
}),
}

if cfg.Session.Filesystem.Path != "" {
fmt.Println("Using filesystem session store at: ", cfg.Session.Filesystem.Path)
if _, err := os.Stat(cfg.Session.Filesystem.Path); os.IsNotExist(err) {
fmt.Println("Creating session store directory: ", cfg.Session.Filesystem.Path)
os.Mkdir(cfg.Session.Filesystem.Path, 0755)
}

sessStore := sessions.NewFilesystemStore(cfg.Session.Filesystem.Path,
securecookie.GenerateRandomKey(32),
securecookie.GenerateRandomKey(32),
)
sessStore.MaxLength(64 * 1024)
opts = append(opts, server_options.WithSessionStore(sessStore))
} else {
fmt.Println("Using cookie session store")
}

s := server.NewServer(opts...)
defer s.Stop()
err = s.Start()
Expand All @@ -133,9 +113,3 @@ func buildCLI() *cli.App {
}
return app
}

func getDefaultFilesystemSessionPath() string {
dir, _ := os.Getwd()
sessDir := filepath.Join(dir, ".tmp")
return sessDir
}
4 changes: 0 additions & 4 deletions docker/config_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ auth:
codec:
endpoint: {{ default .Env.TEMPORAL_CODEC_ENDPOINT "" }}
passAccessToken: {{ default .Env.TEMPORAL_CODEC_PASS_ACCESS_TOKEN "false" }}
session:
filesystem:
# if non-empty, switches to filesystem store instead of cookie store. Increases size limit from 4K to 64K
path: {{ default .Env.TEMPORAL_SESSION_STORE_PATH "" }}
forwardHeaders: # comma separated list of headers to pass from HTTP API requests to Temporal gRPC backend
{{ if .Env.TEMPORAL_FORWARD_HEADERS }}
{{ range $seed := (split .Env.TEMPORAL_FORWARD_HEADERS ",") }}
Expand Down
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.2
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/labstack/echo-contrib v0.12.0
github.com/labstack/echo/v4 v4.6.3
github.com/stretchr/testify v1.8.0
github.com/urfave/cli/v2 v2.3.0
Expand All @@ -28,7 +26,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/labstack/gommon v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
Expand Down
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand All @@ -149,8 +145,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo-contrib v0.12.0 h1:NPr1ez+XUa5s/4LujEon+32Bxg5DO6EKSW/va06pmLc=
github.com/labstack/echo-contrib v0.12.0/go.mod h1:kR62TbwsBgmpV2HVab5iQRsQtLuhPyGqCBee88XRc4M=
github.com/labstack/echo/v4 v4.6.3 h1:VhPuIZYxsbPmo4m9KAkMU/el2442eB7EBFFhNTTT9ac=
github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A=
github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o=
Expand Down
29 changes: 8 additions & 21 deletions server/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (

"github.com/gogo/gateway"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"golang.org/x/net/context"
"google.golang.org/grpc"
Expand All @@ -46,8 +45,8 @@ type Auth struct {
}

type CodecResponse struct {
Endpoint string
AccessToken string
Endpoint string
PassAccessToken bool
}

type SettingsResponse struct {
Expand Down Expand Up @@ -105,20 +104,6 @@ func GetSettings(cfgProvier *config.ConfigProviderWithRefresh) func(echo.Context
}
}

codec := &CodecResponse{
Endpoint: cfg.Codec.Endpoint,
}
if cfg.Codec.PassAccessToken {
sess, _ := session.Get(auth.AuthCookie, c)
if sess != nil {
token := sess.Values[auth.AccessTokenKey]
if token != nil {
codec.AccessToken = token.(string)
}

}
}

settings := &SettingsResponse{
Auth: &Auth{
Enabled: cfg.Auth.Enabled,
Expand All @@ -128,9 +113,12 @@ func GetSettings(cfgProvier *config.ConfigProviderWithRefresh) func(echo.Context
ShowTemporalSystemNamespace: cfg.ShowTemporalSystemNamespace,
FeedbackURL: cfg.FeedbackURL,
NotifyOnNewVersion: cfg.NotifyOnNewVersion,
Codec: codec,
Version: version.UIVersion,
DisableWriteActions: cfg.DisableWriteActions,
Codec: &CodecResponse{
Endpoint: cfg.Codec.Endpoint,
PassAccessToken: cfg.Codec.PassAccessToken,
},
Version: version.UIVersion,
DisableWriteActions: cfg.DisableWriteActions,
}

return c.JSON(http.StatusOK, settings)
Expand All @@ -146,7 +134,6 @@ func getTemporalClientMux(c echo.Context, temporalConn *grpc.ClientConn, apiMidd
tMux := runtime.NewServeMux(
append(muxOpts,
withMarshaler(),
auth.WithAuth(c),
version.WithVersionHeader(c),
// This is necessary to get error details properly
// marshalled in unary requests.
Expand Down
186 changes: 15 additions & 171 deletions server/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,83 +25,36 @@
package auth

import (
"context"
"bytes"
"net/http"
"time"

"github.com/gorilla/sessions"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"github.com/temporalio/ui-server/v2/server/config"
"google.golang.org/grpc/metadata"
)

const (
AuthCookie = "auth"
AccessTokenKey = "access-token"
AuthExtrasCookie = "auth-extras"
IDTokenKey = "id-token"
EmailKey = "email"
NameKey = "name"
PictureKey = "picture"
AuthorizationExtrasHeader = "authorization-extras"
)

var (
sessOpts = &sessions.Options{
Path: "/",
MaxAge: 7 * 24 * int(time.Hour.Seconds()),
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Secure: true,
}
)

func GetCurrentUser(c echo.Context) error {
sess, _ := session.Get(AuthExtrasCookie, c)
email := sess.Values[EmailKey]
name := sess.Values[NameKey]
picture := sess.Values[PictureKey]

if email == nil {
return c.JSON(http.StatusOK, nil)
}
func SetUser(html []byte, user *User) []byte {
html = bytes.Replace(html, []byte("{{.AccessToken}}"), []byte(user.OAuth2Token.AccessToken), 1)
html = bytes.Replace(html, []byte("{{.IDToken}}"), []byte(user.IDToken.RawToken), 1)
html = bytes.Replace(html, []byte("{{.UserName}}"), []byte(user.IDToken.Claims.Name), 1)
html = bytes.Replace(html, []byte("{{.UserEmail}}"), []byte(user.IDToken.Claims.Email), 1)
html = bytes.Replace(html, []byte("{{.UserPicture}}"), []byte(user.IDToken.Claims.Picture), 1)

user := struct {
Email string
Name string
Picture string
}{email.(string), name.(string), picture.(string)}

return c.JSON(http.StatusOK, user)
return html
}

func SetUser(c echo.Context, user *User) error {
err := setAccessToken(c, user.OAuth2Token.AccessToken)
if err != nil {
return err
}

err = setIDToken(c, user.IDToken)
if err != nil {
return err
}
func SetReturnURL(html []byte, returnURL, publicPath string) []byte {
html = bytes.Replace(html, []byte("{{.ReturnUrl}}"), []byte(returnURL), 1)
html = bytes.Replace(html, []byte("{{.PublicPath}}"), []byte(publicPath), 1)

return nil
return html
}

func ClearUser(c echo.Context) error {
err := clearAccessToken(c)
if err != nil {
return err
}

err = clearIDToken(c)
if err != nil {
return err
}

// TODO logout user from IDP
return nil
}

Expand All @@ -124,119 +77,10 @@ func ValidateAuth(c echo.Context, cfgProvider *config.ConfigProviderWithRefresh)
return nil
}

func WithAuth(c echo.Context) runtime.ServeMuxOption {
return runtime.WithMetadata(
func(ctx context.Context, req *http.Request) metadata.MD {
md := metadata.MD{}

token := getAccessToken(c)
if token != "" {
md.Set(echo.HeaderAuthorization, token)
}

extras := getAuthorizationExtras(c)
if extras != "" {
md.Set(AuthorizationExtrasHeader, extras)
}

return md
},
)
}

func getAccessToken(c echo.Context) string {
rToken := c.Request().Header.Get(echo.HeaderAuthorization)
if rToken != "" {
return rToken
}

sess, _ := session.Get(AuthCookie, c)
if sess == nil {
return ""
}

cToken := sess.Values[AccessTokenKey]
if cToken == nil {
return ""
}

return "Bearer " + cToken.(string)
}

func setAccessToken(c echo.Context, token string) error {
sess, _ := session.Get(AuthCookie, c)
sess.Options = sessOpts
sess.Values[AccessTokenKey] = &token

err := sess.Save(c.Request(), c.Response())
if err != nil {
return err
}

return nil
}

func clearAccessToken(c echo.Context) error {
sess, _ := session.Get(AuthCookie, c)
sess.Options = &sessions.Options{
Path: "/",
MaxAge: -1,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Secure: true,
}
err := sess.Save(c.Request(), c.Response())
if err != nil {
return err
}

return nil
return c.Request().Header.Get(echo.HeaderAuthorization)
}

func getAuthorizationExtras(c echo.Context) string {
sess, _ := session.Get(AuthExtrasCookie, c)
if sess == nil {
return ""
}

extras := sess.Values[IDTokenKey]
if extras == nil {
return ""
}

return extras.(string)
}

func setIDToken(c echo.Context, idToken *IDToken) error {
sess, _ := session.Get(AuthExtrasCookie, c)
sess.Options = sessOpts

sess.Values[EmailKey] = &idToken.Claims.Email
sess.Values[PictureKey] = &idToken.Claims.Picture
sess.Values[NameKey] = &idToken.Claims.Name
sess.Values[IDTokenKey] = &idToken.RawToken

err := sess.Save(c.Request(), c.Response())
if err != nil {
return err
}

return nil
}

func clearIDToken(c echo.Context) error {
sess, _ := session.Get(AuthExtrasCookie, c)
sess.Options = &sessions.Options{
Path: "/",
MaxAge: -1,
HttpOnly: true,
SameSite: http.SameSiteStrictMode,
Secure: true,
}
err := sess.Save(c.Request(), c.Response())
if err != nil {
return err
}

return nil
return c.Request().Header.Get(AuthorizationExtrasHeader)
}
Loading

0 comments on commit 5a9eac5

Please sign in to comment.