satellite/console: support hosting Vuetify POC on subdomain

This change allows you to host the vuetify app on <x>.example.com where
the main app is hosted on example.com. A configuration is added to
specify an exact subdomain for cookies. For example, if my production
app is hosted on us1.storj.io and my vuetify app is hosted on
vuetify.us1.storj.io, the cookie domain should be set to ".us1.storj.io"
so that any authentication cookie is accessible to lower-level
subdomains.

Since the vuetify app does not currently support login/signup on its
own, it is still required to first login to the main satellite UI, then
navigate to the Vuetify app after the session cookie is set.

If the "vuetifypoc" prefix is not desirable when using subdomain hosting
for vuetify, the VITE_VUETIFY_PREFIX variable can be modified in
web/satellite/.env before running `npm run build-vuetify`. For now, we
should keep this prefix because it makes developing on the vuetify app
significantly easier if subdomains are not being used.

Issue: https://github.com/storj/storj/issues/6144

Change-Id: Iba1a5737892c8ee8f38148a17b94e3222f8798e6
This commit is contained in:
Moby von Briesen 2023-08-02 13:29:42 -04:00 committed by Storj Robot
parent ceb7b7375c
commit b9206b1844
5 changed files with 25 additions and 7 deletions

View File

@ -20,12 +20,14 @@ type CookieSettings struct {
// CookieAuth handles cookie authorization.
type CookieAuth struct {
settings CookieSettings
domain string
}
// NewCookieAuth create new cookie authorization with provided settings.
func NewCookieAuth(settings CookieSettings) *CookieAuth {
func NewCookieAuth(settings CookieSettings, domain string) *CookieAuth {
return &CookieAuth{
settings: settings,
domain: domain,
}
}
@ -50,6 +52,7 @@ func (auth *CookieAuth) GetToken(r *http.Request) (console.TokenInfo, error) {
// SetTokenCookie sets parametrized token cookie that is not accessible from js.
func (auth *CookieAuth) SetTokenCookie(w http.ResponseWriter, tokenInfo console.TokenInfo) {
http.SetCookie(w, &http.Cookie{
Domain: auth.domain,
Name: auth.settings.Name,
Value: tokenInfo.Token.String(),
Path: auth.settings.Path,
@ -62,6 +65,7 @@ func (auth *CookieAuth) SetTokenCookie(w http.ResponseWriter, tokenInfo console.
// RemoveTokenCookie removes auth cookie that is not accessible from js.
func (auth *CookieAuth) RemoveTokenCookie(w http.ResponseWriter) {
http.SetCookie(w, &http.Cookie{
Domain: auth.domain,
Name: auth.settings.Name,
Value: "",
Path: auth.settings.Path,

View File

@ -73,8 +73,9 @@ type Config struct {
StaticDir string `help:"path to static resources" default:""`
Watch bool `help:"whether to load templates on each request" default:"false" devDefault:"true"`
AuthToken string `help:"auth token needed for access to registration token creation endpoint" default:"" testDefault:"very-secret-token"`
AuthTokenSecret string `help:"secret used to sign auth tokens" releaseDefault:"" devDefault:"my-suppa-secret-key"`
AuthToken string `help:"auth token needed for access to registration token creation endpoint" default:"" testDefault:"very-secret-token"`
AuthTokenSecret string `help:"secret used to sign auth tokens" releaseDefault:"" devDefault:"my-suppa-secret-key"`
AuthCookieDomain string `help:"optional domain for cookies to use" default:""`
ContactInfoURL string `help:"url link to contacts page" default:"https://forum.storj.io"`
FrameAncestors string `help:"allow domains to embed the satellite in a frame, space separated" default:"tardigrade.io storj.io"`
@ -109,6 +110,7 @@ type Config struct {
NewUploadModalEnabled bool `help:"whether to show new upload modal" default:"false"`
GalleryViewEnabled bool `help:"whether to show new gallery view" default:"false"`
UseVuetifyProject bool `help:"whether to use vuetify POC project" default:"false"`
VuetifyHost string `help:"the subdomain the vuetify POC project should be hosted on" default:""`
OauthCodeExpiry time.Duration `help:"how long oauth authorization codes are issued for" default:"10m"`
OauthAccessTokenExpiry time.Duration `help:"how long oauth access tokens are issued for" default:"24h"`
@ -233,7 +235,7 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
server.cookieAuth = consolewebauth.NewCookieAuth(consolewebauth.CookieSettings{
Name: "_tokenKey",
Path: "/",
})
}, server.config.AuthCookieDomain)
if server.config.ExternalAddress != "" {
if !strings.HasSuffix(server.config.ExternalAddress, "/") {
@ -394,7 +396,12 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
router.PathPrefix("/static/").Handler(server.withCORS(server.brotliMiddleware(http.StripPrefix("/static", fs))))
if server.config.UseVuetifyProject {
router.PathPrefix("/vuetifypoc").Handler(server.withCORS(http.HandlerFunc(server.vuetifyAppHandler)))
if server.config.VuetifyHost != "" {
router.Host(server.config.VuetifyHost).Handler(server.withCORS(http.HandlerFunc(server.vuetifyAppHandler)))
} else {
// if not using a custom subdomain for vuetify, use a path prefix on the same domain as the production app
router.PathPrefix("/vuetifypoc").Handler(server.withCORS(http.HandlerFunc(server.vuetifyAppHandler)))
}
}
router.PathPrefix("/").Handler(server.withCORS(http.HandlerFunc(server.appHandler)))
}

View File

@ -181,6 +181,9 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0
# default duration for AS OF SYSTEM TIME
# console.as-of-system-time-duration: -5m0s
# optional domain for cookies to use
# console.auth-cookie-domain: ""
# auth token needed for access to registration token creation endpoint
# console.auth-token: ""
@ -409,6 +412,9 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0
# amount of base units of US micro dollars needed to upgrade user's tier status
# console.user-balance-for-upgrade: 10000000
# the subdomain the vuetify POC project should be hosted on
# console.vuetify-host: ""
# whether to load templates on each request
# console.watch: false

View File

@ -1 +1,2 @@
VITE_ENDPOINT_URL=/api/v0/graphql
VITE_VUETIFY_PREFIX=vuetifypoc

View File

@ -7,7 +7,7 @@ import { useAppStore } from '@poc/store/appStore';
const routes: RouteRecordRaw[] = [
{
path: '/vuetifypoc',
path: '/',
redirect: { path: '/projects' }, // redirect
},
{
@ -77,7 +77,7 @@ const routes: RouteRecordRaw[] = [
];
const router = createRouter({
history: createWebHistory(),
history: createWebHistory(import.meta.env.VITE_VUETIFY_PREFIX),
routes,
});