diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 7952d3c464..85903d023b 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -153,6 +153,15 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { Optional: false, SessionTokenFunc: nil, // Default behavior }) + // Same as above but it redirects to the login page. + apiKeyMiddlewareRedirect := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ + DB: options.Database, + OAuth2Configs: oauthConfigs, + RedirectToLogin: true, + DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), + Optional: false, + SessionTokenFunc: nil, // Default behavior + }) apiKeyMiddlewareOptional := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ DB: options.Database, OAuth2Configs: oauthConfigs, @@ -168,7 +177,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { } api.AGPL.RootHandler.Group(func(r chi.Router) { - // Oauth2 linking routes do not make sense under the /api/v2 path. + // OAuth2 linking routes do not make sense under the /api/v2 path. r.Route("/oauth2", func(r chi.Router) { r.Use( api.oAuth2ProviderMiddleware, @@ -176,17 +185,22 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { // authenticated user. httpmw.AsAuthzSystem(httpmw.ExtractOAuth2ProviderApp(options.Database)), ) - r.Group(func(r chi.Router) { - r.Use(apiKeyMiddleware) - r.Get("/authorize", api.postOAuth2ProviderAppAuthorize()) - // DELETE on /tokens is not part of the OAuth2 spec. It is our own - // route used to revoke permissions from an application. It is here for - // parity with POST on /tokens. - r.Delete("/tokens", api.deleteOAuth2ProviderAppTokens()) + r.Route("/authorize", func(r chi.Router) { + r.Use(apiKeyMiddlewareRedirect) + r.Get("/", api.getOAuth2ProviderAppAuthorize()) + }) + r.Route("/tokens", func(r chi.Router) { + r.Group(func(r chi.Router) { + r.Use(apiKeyMiddleware) + // DELETE on /tokens is not part of the OAuth2 spec. It is our own + // route used to revoke permissions from an application. It is here for + // parity with POST on /tokens. + r.Delete("/", api.deleteOAuth2ProviderAppTokens()) + }) + // The POST /tokens endpoint will be called from an unauthorized client so we + // cannot require an API key. + r.Post("/", api.postOAuth2ProviderAppToken()) }) - // The /tokens endpoint will be called from an unauthorized client so we - // cannot require an API key. - r.Post("/tokens", api.postOAuth2ProviderAppToken()) }) }) diff --git a/enterprise/coderd/oauth2.go b/enterprise/coderd/oauth2.go index 9455e0bdfa..9c75b0b7a6 100644 --- a/enterprise/coderd/oauth2.go +++ b/enterprise/coderd/oauth2.go @@ -292,7 +292,7 @@ func (api *API) deleteOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Re // @Param scope query string false "Token scopes (currently ignored)" // @Success 302 // @Router /oauth2/authorize [post] -func (api *API) postOAuth2ProviderAppAuthorize() http.HandlerFunc { +func (api *API) getOAuth2ProviderAppAuthorize() http.HandlerFunc { return identityprovider.Authorize(api.Database, api.AccessURL) } diff --git a/site/src/pages/LoginPage/LoginPage.tsx b/site/src/pages/LoginPage/LoginPage.tsx index 5b7ba35624..dd34ff9b3a 100644 --- a/site/src/pages/LoginPage/LoginPage.tsx +++ b/site/src/pages/LoginPage/LoginPage.tsx @@ -25,7 +25,8 @@ export const LoginPage: FC = () => { // If the redirect is going to a workspace application, and we // are missing authentication, then we need to change the href location // to trigger a HTTP request. This allows the BE to generate the auth - // cookie required. + // cookie required. Similarly for the OAuth2 exchange as the authorization + // page is served by the backend. // If no redirect is present, then ignore this branched logic. if (redirectTo !== "" && redirectTo !== "/") { try { @@ -39,8 +40,8 @@ export const LoginPage: FC = () => { } catch { // Do nothing } - // Path based apps. - if (redirectTo.includes("/apps/")) { + // Path based apps and OAuth2. + if (redirectTo.includes("/apps/") || redirectTo.includes("/oauth2/")) { window.location.href = redirectTo; return null; }