@@ -16,6 +16,7 @@ import (
16
16
"github.com/coder/coder/v2/coderd/httpapi"
17
17
"github.com/coder/coder/v2/coderd/httpmw"
18
18
"github.com/coder/coder/v2/codersdk"
19
+ "github.com/coder/coder/v2/site"
19
20
)
20
21
21
22
type authorizeParams struct {
@@ -68,15 +69,46 @@ func extractAuthorizeParams(r *http.Request, callbackURL *url.URL) (authorizePar
68
69
69
70
// ShowAuthorizePage handles GET /oauth2/authorize requests to display the HTML authorization page.
70
71
// It uses authorizeMW which intercepts GET requests to show the authorization form.
71
- func ShowAuthorizePage (db database.Store ,accessURL * url.URL ) http.HandlerFunc {
72
- handler := authorizeMW (accessURL )(ProcessAuthorize (db ,accessURL ))
73
- return handler .ServeHTTP
72
+ func ShowAuthorizePage (accessURL * url.URL ) http.HandlerFunc {
73
+ return func (rw http.ResponseWriter ,r * http.Request ) {
74
+ app := httpmw .OAuth2ProviderApp (r )
75
+ ua := httpmw .UserAuthorization (r .Context ())
76
+
77
+ callbackURL ,err := url .Parse (app .CallbackURL )
78
+ if err != nil {
79
+ site .RenderStaticErrorPage (rw ,r , site.ErrorPageData {Status :http .StatusInternalServerError ,HideStatus :false ,Title :"Internal Server Error" ,Description :err .Error (),RetryEnabled :false ,DashboardURL :accessURL .String (),Warnings :nil })
80
+ return
81
+ }
82
+
83
+ params ,validationErrs ,err := extractAuthorizeParams (r ,callbackURL )
84
+ if err != nil {
85
+ errStr := make ([]string ,len (validationErrs ))
86
+ for i ,err := range validationErrs {
87
+ errStr [i ]= err .Detail
88
+ }
89
+ site .RenderStaticErrorPage (rw ,r , site.ErrorPageData {Status :http .StatusBadRequest ,HideStatus :false ,Title :"Invalid Query Parameters" ,Description :"One or more query parameters are missing or invalid." ,RetryEnabled :false ,DashboardURL :accessURL .String (),Warnings :errStr })
90
+ return
91
+ }
92
+
93
+ cancel := params .redirectURL
94
+ cancelQuery := params .redirectURL .Query ()
95
+ cancelQuery .Add ("error" ,"access_denied" )
96
+ cancel .RawQuery = cancelQuery .Encode ()
97
+
98
+ site .RenderOAuthAllowPage (rw ,r , site.RenderOAuthAllowData {
99
+ AppIcon :app .Icon ,
100
+ AppName :app .Name ,
101
+ CancelURI :cancel .String (),
102
+ RedirectURI :r .URL .String (),
103
+ Username :ua .FriendlyName ,
104
+ })
105
+ }
74
106
}
75
107
76
108
// ProcessAuthorize handles POST /oauth2/authorize requests to process the user's authorization decision
77
109
// and generate an authorization code. GET requests are handled by authorizeMW.
78
- func ProcessAuthorize (db database.Store , accessURL * url. URL ) http.HandlerFunc {
79
- handler := func (rw http.ResponseWriter ,r * http.Request ) {
110
+ func ProcessAuthorize (db database.Store ) http.HandlerFunc {
111
+ return func (rw http.ResponseWriter ,r * http.Request ) {
80
112
ctx := r .Context ()
81
113
apiKey := httpmw .APIKey (r )
82
114
app := httpmw .OAuth2ProviderApp (r )
@@ -159,9 +191,8 @@ func ProcessAuthorize(db database.Store, accessURL *url.URL) http.HandlerFunc {
159
191
}
160
192
params .redirectURL .RawQuery = newQuery .Encode ()
161
193
162
- http .Redirect (rw ,r ,params .redirectURL .String (),http .StatusTemporaryRedirect )
194
+ // (ThomasK33): Use a 302 redirect as some (external) OAuth 2 apps and browsers
195
+ // do not work with the 307.
196
+ http .Redirect (rw ,r ,params .redirectURL .String (),http .StatusFound )
163
197
}
164
-
165
- // Always wrap with its custom mw.
166
- return authorizeMW (accessURL )(http .HandlerFunc (handler )).ServeHTTP
167
198
}