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

Fix nil dereference in RequestMiddleware #5033

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .make-lint-expect
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ pkg/api/event/hook_response.go cannot import github.com/authgear/authgear-server

exit status 1
pkg/lib/deps/deps_common.go cannot import github.com/authgear/authgear-server/pkg/auth/handler/webapp/authflowv2
pkg/lib/deps/middleware_request.go cannot import github.com/authgear/authgear-server/pkg/auth/handler/webapp/viewmodels

exit status 1
pkg/admin/graphql/audit_log.go cannot import github.com/authgear/authgear-server/pkg/graphqlgo/relay
Expand Down
36 changes: 20 additions & 16 deletions .vettedpositions
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
/pkg/auth/handler/oauth/app_session_token.go:69:27: requestcontext
/pkg/auth/handler/oauth/authorize.go:52:26: requestcontext
/pkg/auth/handler/oauth/challenge.go:91:27: requestcontext
/pkg/auth/handler/oauth/consent.go:85:27: requestcontext
/pkg/auth/handler/oauth/consent.go:105:28: requestcontext
/pkg/auth/handler/oauth/consent.go:114:28: requestcontext
/pkg/auth/handler/oauth/consent.go:85:27: requestcontext
/pkg/auth/handler/oauth/end_session.go:48:26: requestcontext
/pkg/auth/handler/oauth/revoke.go:47:26: requestcontext
/pkg/auth/handler/oauth/token.go:50:26: requestcontext
Expand All @@ -37,6 +37,7 @@
/pkg/auth/handler/saml/login_finish.go:41:9: requestcontext
/pkg/auth/handler/saml/logout.go:86:9: requestcontext
/pkg/auth/handler/webapp/account_status.go:48:27: requestcontext
/pkg/auth/handler/webapp/app_static_assets.go:39:33: requestcontext
/pkg/auth/handler/webapp/auth_entry_point_middleware.go:31:31: requestcontext
/pkg/auth/handler/webapp/auth_entry_point_middleware.go:32:35: requestcontext
/pkg/auth/handler/webapp/authflow_change_password.go:96:26: requestcontext
Expand Down Expand Up @@ -146,8 +147,8 @@
/pkg/auth/handler/webapp/change_password.go:72:27: requestcontext
/pkg/auth/handler/webapp/change_secondary_password.go:71:27: requestcontext
/pkg/auth/handler/webapp/confirm_terminate_other_sessions.go:66:27: requestcontext
/pkg/auth/handler/webapp/confirm_web3_account.go:104:28: requestcontext
/pkg/auth/handler/webapp/confirm_web3_account.go:96:27: requestcontext
/pkg/auth/handler/webapp/confirm_web3_account.go:104:28: requestcontext
/pkg/auth/handler/webapp/create_passkey.go:53:27: requestcontext
/pkg/auth/handler/webapp/create_password.go:107:27: requestcontext
/pkg/auth/handler/webapp/csrf_error_instruction.go:49:33: requestcontext
Expand All @@ -172,8 +173,8 @@
/pkg/auth/handler/webapp/panic_middleware.go:68:61: requestcontext
/pkg/auth/handler/webapp/passkey_creation_options.go:43:28: requestcontext
/pkg/auth/handler/webapp/passkey_request_options.go:52:28: requestcontext
/pkg/auth/handler/webapp/promote.go:110:28: requestcontext
/pkg/auth/handler/webapp/promote.go:98:27: requestcontext
/pkg/auth/handler/webapp/promote.go:110:28: requestcontext
/pkg/auth/handler/webapp/prompt_create_passkey.go:47:27: requestcontext
/pkg/auth/handler/webapp/reauth.go:29:27: requestcontext
/pkg/auth/handler/webapp/reauth.go:31:34: requestcontext
Expand Down Expand Up @@ -218,8 +219,8 @@
/pkg/auth/handler/webapp/setup_recovery_code.go:76:27: requestcontext
/pkg/auth/handler/webapp/setup_totp.go:139:27: requestcontext
/pkg/auth/handler/webapp/setup_whatsapp_otp.go:62:27: requestcontext
/pkg/auth/handler/webapp/signup.go:101:28: requestcontext
/pkg/auth/handler/webapp/signup.go:90:27: requestcontext
/pkg/auth/handler/webapp/signup.go:101:28: requestcontext
/pkg/auth/handler/webapp/sso_callback.go:42:53: requestcontext
/pkg/auth/handler/webapp/sso_callback.go:48:26: requestcontext
/pkg/auth/handler/webapp/sso_callback.go:56:58: requestcontext
Expand Down Expand Up @@ -258,12 +259,18 @@
/pkg/auth/webapp/ui_param.go:65:42: requestcontext
/pkg/auth/webapp/ui_param.go:86:10: requestcontext
/pkg/auth/webapp/visitor_id_middleware.go:26:24: requestcontext
/pkg/auth/webapp/wechat_redirect_uri_middleware.go:115:39: requestcontext
/pkg/auth/webapp/wechat_redirect_uri_middleware.go:59:31: requestcontext
/pkg/auth/webapp/wechat_redirect_uri_middleware.go:115:39: requestcontext
/pkg/auth/webapp/x_color_scheme.go:74:27: requestcontext
/pkg/auth/webapp_request_middleware.go:44:40: requestcontext
/pkg/auth/webapp_request_middleware.go:47:40: requestcontext
/pkg/auth/webapp_request_middleware.go:48:43: requestcontext
/pkg/auth/webapp_request_middleware.go:50:30: requestcontext
/pkg/images/deps/context.go:23:10: requestcontext
/pkg/auth/handler/webapp/app_static_assets.go:39:33: requestcontext
/pkg/portal/transport/system_config_handler.go:28:10: requestcontext
/pkg/images/deps/middleware_request.go:29:40: requestcontext
/pkg/images/deps/middleware_request.go:32:40: requestcontext
/pkg/images/deps/middleware_request.go:33:35: requestcontext
/pkg/images/deps/middleware_request.go:35:30: requestcontext
/pkg/images/handler/post.go:67:9: requestcontext
/pkg/lib/accountmanagement/rate_limit_middleware.go:41:10: requestcontext
/pkg/lib/admin/authz/middleware.go:85:18: requestcontext
Expand All @@ -275,6 +282,10 @@
/pkg/lib/config/contextbackground.go:11:52: contextbackground
/pkg/lib/deps/context.go:23:10: requestcontext
/pkg/lib/deps/contextbackground.go:10:28: contextbackground
/pkg/lib/deps/middleware_request.go:29:40: requestcontext
/pkg/lib/deps/middleware_request.go:32:40: requestcontext
/pkg/lib/deps/middleware_request.go:33:38: requestcontext
/pkg/lib/deps/middleware_request.go:35:30: requestcontext
/pkg/lib/deps/providers.go:179:25: requestcontext
/pkg/lib/dpop/middleware.go:45:35: requestcontext
/pkg/lib/healthz/healthz.go:27:23: requestcontext
Expand Down Expand Up @@ -302,23 +313,16 @@
/pkg/portal/transport/stripe_webhook_handler.go:85:4: requestcontext
/pkg/portal/transport/stripe_webhook_handler.go:91:4: requestcontext
/pkg/portal/transport/stripe_webhook_handler.go:96:4: requestcontext
/pkg/portal/transport/system_config_handler.go:28:10: requestcontext
/pkg/resolver/handler/resolve.go:45:9: requestcontext
/pkg/util/graphqlutil/graphiql.go:27:32: requestcontext
/pkg/util/httproute/httproute.go:128:38: requestcontext
/pkg/util/httputil/csp.go:158:42: requestcontext
/pkg/util/httputil/csp.go:164:42: requestcontext
/pkg/util/httputil/file_server.go:116:11: requestcontext
/pkg/util/httputil/json.go:96:9: requestcontext
/pkg/util/jwkutil/contextbackground.go:11:52: contextbackground
/pkg/util/otelutil/nethttp.go:68:45: requestcontext
/pkg/util/pubsub/http_handler.go:51:40: requestcontext
/pkg/util/sentry/request.go:25:9: requestcontext
/pkg/util/template/engine.go:308:9: requestcontext
/pkg/util/httputil/json.go:96:9: requestcontext
/pkg/lib/deps/middleware_request.go:41:40: requestcontext
/pkg/lib/deps/middleware_request.go:44:40: requestcontext
/pkg/lib/deps/middleware_request.go:45:35: requestcontext
/pkg/lib/deps/middleware_request.go:47:30: requestcontext
/pkg/images/deps/middleware_request.go:29:40: requestcontext
/pkg/images/deps/middleware_request.go:32:40: requestcontext
/pkg/images/deps/middleware_request.go:33:35: requestcontext
/pkg/images/deps/middleware_request.go:35:30: requestcontext
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ lint:
sort-translations:
go run ./devtools/translationsorter

.PHONY: sort-vettedpositions
sort-vettedpositions:
./scripts/python/sort_vettedpositions.py ./.vettedpositions

.PHONY: fmt
fmt:
# Ignore generated files, such as wire_gen.go and *_mock_test.go
Expand All @@ -101,6 +105,7 @@ binary:
check-tidy:
# For some unknown reason, `make generate` will somehow format the files again (but with a different rule).
# So `make fmt` has to be run after `make generate`.
$(MAKE) sort-vettedpositions
$(MAKE) generate
$(MAKE) fmt
$(MAKE) html-email
Expand Down
5 changes: 3 additions & 2 deletions pkg/auth/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,6 @@ var RequestMiddlewareDependencySet = wire.NewSet(

viewmodelswebapp.NewBaseLogger,
wire.Struct(new(viewmodelswebapp.BaseViewModeler), "*"),
wire.Struct(new(deps.RequestMiddleware), "*"),

wire.Bind(new(template.ResourceManager), new(*resource.Manager)),
wire.Bind(new(web.ResourceManager), new(*resource.Manager)),
Expand All @@ -376,9 +375,11 @@ var RequestMiddlewareDependencySet = wire.NewSet(

oauthclient.DependencySet,
wire.Bind(new(viewmodelswebapp.WebappOAuthClientResolver), new(*oauthclient.Resolver)),

wire.Struct(new(WebAppRequestMiddleware), "*"),
)

func RequestMiddleware(p *deps.RootProvider, configSource *configsource.ConfigSource, factory func(http.ResponseWriter, *http.Request, *deps.RootProvider, *configsource.ConfigSource) httproute.Middleware) httproute.Middleware {
func MakeWebAppRequestMiddleware(p *deps.RootProvider, configSource *configsource.ConfigSource, factory func(http.ResponseWriter, *http.Request, *deps.RootProvider, *configsource.ConfigSource) httproute.Middleware) httproute.Middleware {
return httproute.MiddlewareFunc(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
m := factory(w, r, p, configSource)
Expand Down
2 changes: 1 addition & 1 deletion pkg/auth/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewRouter(p *deps.RootProvider, configSource *configsource.ConfigSource) ht
httproute.MiddlewareFunc(httputil.XContentTypeOptionsNosniff),
httproute.MiddlewareFunc(httputil.PermissionsPolicyHeader),
httproute.MiddlewareFunc(httputil.XRobotsTag),
RequestMiddleware(p, configSource, newRequestMiddleware),
MakeWebAppRequestMiddleware(p, configSource, newWebAppRequestMiddleware),
p.Middleware(newContextHolderMiddleware),
)

Expand Down
69 changes: 69 additions & 0 deletions pkg/auth/webapp_request_middleware.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package auth

import (
"context"
"errors"
"net/http"

"github.com/authgear/authgear-server/pkg/auth/handler/webapp/viewmodels"
"github.com/authgear/authgear-server/pkg/lib/config"
"github.com/authgear/authgear-server/pkg/lib/config/configsource"
"github.com/authgear/authgear-server/pkg/lib/deps"
"github.com/authgear/authgear-server/pkg/lib/otelauthgear"
"github.com/authgear/authgear-server/pkg/lib/web"
"github.com/authgear/authgear-server/pkg/util/httputil"
"github.com/authgear/authgear-server/pkg/util/template"
)

var TemplateWebAppNotFoundHTML = template.RegisterHTML(
"web/app_not_found.html",
web.ComponentsHTML...,
)

// WebAppRequestMiddleware is placed at /pkg/auth because it depends on /pkg/auth/handler/webapp/viewmodels
// So it CANNOT be replaced at /pkg/auth/webapp.
type WebAppRequestMiddleware struct {
HTTPHost httputil.HTTPHost
RootProvider *deps.RootProvider
ConfigSource *configsource.ConfigSource
TemplateEngine *template.Engine
BaseViewModeler *viewmodels.BaseViewModeler
}

func (m *WebAppRequestMiddleware) Handle(next http.Handler) http.Handler {
logger := m.RootProvider.LoggerFactory.New("request")

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logger.WithFields(map[string]interface{}{
"request.host": r.Host,
"request.url": r.URL.String(),
"request.header.host": r.Header.Get("Host"),
"request.header.x-forwarded-host": r.Header.Get("X-Forwarded-Host"),
"request.header.x-original-host": r.Header.Get("X-Original-Host"),
}).Debug("serving request")
err := m.ConfigSource.ProvideContext(r.Context(), r, func(ctx context.Context, appCtx *config.AppContext) error {
r = r.WithContext(ctx)

ap := m.RootProvider.NewAppProvider(r.Context(), appCtx)
r = r.WithContext(deps.WithAppProvider(r.Context(), ap))

otelauthgear.SetProjectID(r.Context(), string(appCtx.Config.AppConfig.ID))
next.ServeHTTP(w, r)
return nil
})
if err != nil {
if errors.Is(err, configsource.ErrAppNotFound) {
data := map[string]interface{}{
"HTTPHost": string(m.HTTPHost),
}
baseViewModel := m.BaseViewModeler.ViewModel(r, w)
viewmodels.Embed(data, baseViewModel)
m.TemplateEngine.RenderStatus(w, r, http.StatusNotFound, TemplateWebAppNotFoundHTML, data)
} else {
logger.WithError(err).Error("failed to resolve config")
http.Error(w, "internal server error", http.StatusInternalServerError)
}
return
}
})
}
6 changes: 3 additions & 3 deletions pkg/auth/wire_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -180843,7 +180843,7 @@ func newWebAppAuthflowV2SettingsIdentityListOAuthHandler(p *deps.RequestProvider

// Injectors from wire_middleware.go:

func newRequestMiddleware(w http.ResponseWriter, r *http.Request, p *deps.RootProvider, configSource *configsource.ConfigSource) httproute.Middleware {
func newWebAppRequestMiddleware(w http.ResponseWriter, r *http.Request, p *deps.RootProvider, configSource *configsource.ConfigSource) httproute.Middleware {
environmentConfig := p.EnvironmentConfig
trustProxy := environmentConfig.TrustProxy
httpHost := deps.ProvideHTTPHost(r, trustProxy)
Expand Down Expand Up @@ -180929,14 +180929,14 @@ func newRequestMiddleware(w http.ResponseWriter, r *http.Request, p *deps.RootPr
OAuthClientResolver: oauthclientResolver,
Logger: baseLogger,
}
requestMiddleware := &deps.RequestMiddleware{
webAppRequestMiddleware := &WebAppRequestMiddleware{
HTTPHost: httpHost,
RootProvider: p,
ConfigSource: configSource,
TemplateEngine: engine,
BaseViewModeler: baseViewModeler,
}
return requestMiddleware
return webAppRequestMiddleware
}

var (
Expand Down
4 changes: 2 additions & 2 deletions pkg/auth/wire_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
"github.com/authgear/authgear-server/pkg/util/httproute"
)

func newRequestMiddleware(w http.ResponseWriter, r *http.Request, p *deps.RootProvider, configSource *configsource.ConfigSource) httproute.Middleware {
func newWebAppRequestMiddleware(w http.ResponseWriter, r *http.Request, p *deps.RootProvider, configSource *configsource.ConfigSource) httproute.Middleware {
panic(wire.Build(
RequestMiddlewareDependencySet,
wire.Bind(new(httproute.Middleware), new(*deps.RequestMiddleware)),
wire.Bind(new(httproute.Middleware), new(*WebAppRequestMiddleware)),
))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/lib/deps/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type providerContext struct {
p *AppProvider
}

func withProvider(ctx context.Context, p *AppProvider) context.Context {
func WithAppProvider(ctx context.Context, p *AppProvider) context.Context {
return context.WithValue(ctx, providerContextKey, &providerContext{
p: p,
})
Expand Down
25 changes: 4 additions & 21 deletions pkg/lib/deps/middleware_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,14 @@ import (
"errors"
"net/http"

"github.com/authgear/authgear-server/pkg/auth/handler/webapp/viewmodels"
"github.com/authgear/authgear-server/pkg/lib/config"
"github.com/authgear/authgear-server/pkg/lib/config/configsource"
"github.com/authgear/authgear-server/pkg/lib/otelauthgear"
"github.com/authgear/authgear-server/pkg/lib/web"
"github.com/authgear/authgear-server/pkg/util/httputil"
"github.com/authgear/authgear-server/pkg/util/template"
)

var TemplateWebAppNotFoundHTML = template.RegisterHTML(
"web/app_not_found.html",
web.ComponentsHTML...,
)

type RequestMiddleware struct {
HTTPHost httputil.HTTPHost
RootProvider *RootProvider
ConfigSource *configsource.ConfigSource
TemplateEngine *template.Engine
BaseViewModeler *viewmodels.BaseViewModeler
RootProvider *RootProvider
ConfigSource *configsource.ConfigSource
}

func (m *RequestMiddleware) Handle(next http.Handler) http.Handler {
Expand All @@ -42,20 +30,15 @@ func (m *RequestMiddleware) Handle(next http.Handler) http.Handler {
r = r.WithContext(ctx)

ap := m.RootProvider.NewAppProvider(r.Context(), appCtx)
r = r.WithContext(withProvider(r.Context(), ap))
r = r.WithContext(WithAppProvider(r.Context(), ap))

otelauthgear.SetProjectID(r.Context(), string(appCtx.Config.AppConfig.ID))
next.ServeHTTP(w, r)
return nil
})
if err != nil {
if errors.Is(err, configsource.ErrAppNotFound) {
data := map[string]interface{}{
"HTTPHost": string(m.HTTPHost),
}
baseViewModel := m.BaseViewModeler.ViewModel(r, w)
viewmodels.Embed(data, baseViewModel)
m.TemplateEngine.RenderStatus(w, r, http.StatusNotFound, TemplateWebAppNotFoundHTML, data)
http.Error(w, configsource.ErrAppNotFound.Error(), http.StatusNotFound)
} else {
logger.WithError(err).Error("failed to resolve config")
http.Error(w, "internal server error", http.StatusInternalServerError)
Expand Down
46 changes: 46 additions & 0 deletions scripts/python/sort_vettedpositions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
import sys
import dataclasses
import functools


@dataclasses.dataclass
@functools.total_ordering
class Line:
path: str
line: int
column: int
contents: str

def __init__(self, line: str):
parts = line.split(":")
if len(parts) < 4:
raise ValueError(line)
self.path = parts[0]
self.line = int(parts[1])
self.column = int(parts[2])
self.contents = parts[3].strip()

def __str__(self) -> str:
return f"{self.path}:{self.line}:{self.column}: {self.contents}"

def __lt__(self, other):
return (self.path, self.line, self.column, self.contents) < (other.path, other.line, other.column, other.contents)

def __eq__(self, other):
return (self.path, self.line, self.column, self.contents) == (other.path, other.line, other.column, other.contents)


def main():
path_to_file = sys.argv[1]
lines = []
with open(path_to_file) as f:
for line in f:
lines.append(Line(line.strip()))
lines = sorted(lines)
with open(path_to_file, "w") as f:
for line in lines:
print(line, file=f)

if __name__ == "__main__":
main()
Loading