@@ -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 {
@@ -67,16 +68,46 @@ func extractAuthorizeParams(r *http.Request, callbackURL *url.URL) (authorizePar
67
68
}
68
69
69
70
// ShowAuthorizePage handles GET /oauth2/authorize requests to display the HTML authorization page.
70
- // 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
71
+ func ShowAuthorizePage (accessURL * url.URL ) http.HandlerFunc {
72
+ return func (rw http.ResponseWriter ,r * http.Request ) {
73
+ app := httpmw .OAuth2ProviderApp (r )
74
+ ua := httpmw .UserAuthorization (r .Context ())
75
+
76
+ callbackURL ,err := url .Parse (app .CallbackURL )
77
+ if err != nil {
78
+ 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 })
79
+ return
80
+ }
81
+
82
+ params ,validationErrs ,err := extractAuthorizeParams (r ,callbackURL )
83
+ if err != nil {
84
+ errStr := make ([]string ,len (validationErrs ))
85
+ for i ,err := range validationErrs {
86
+ errStr [i ]= err .Detail
87
+ }
88
+ 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 })
89
+ return
90
+ }
91
+
92
+ cancel := params .redirectURL
93
+ cancelQuery := params .redirectURL .Query ()
94
+ cancelQuery .Add ("error" ,"access_denied" )
95
+ cancel .RawQuery = cancelQuery .Encode ()
96
+
97
+ site .RenderOAuthAllowPage (rw ,r , site.RenderOAuthAllowData {
98
+ AppIcon :app .Icon ,
99
+ AppName :app .Name ,
100
+ CancelURI :cancel .String (),
101
+ RedirectURI :r .URL .String (),
102
+ Username :ua .FriendlyName ,
103
+ })
104
+ }
74
105
}
75
106
76
107
// ProcessAuthorize handles POST /oauth2/authorize requests to process the user's authorization decision
77
- // 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 ) {
108
+ // and generate an authorization code.
109
+ func ProcessAuthorize (db database.Store ) http.HandlerFunc {
110
+ return func (rw http.ResponseWriter ,r * http.Request ) {
80
111
ctx := r .Context ()
81
112
apiKey := httpmw .APIKey (r )
82
113
app := httpmw .OAuth2ProviderApp (r )
@@ -159,9 +190,8 @@ func ProcessAuthorize(db database.Store, accessURL *url.URL) http.HandlerFunc {
159
190
}
160
191
params .redirectURL .RawQuery = newQuery .Encode ()
161
192
162
- http .Redirect (rw ,r ,params .redirectURL .String (),http .StatusTemporaryRedirect )
193
+ // (ThomasK33): Use a 302 redirect as some (external) OAuth 2 apps and browsers
194
+ // do not work with the 307.
195
+ http .Redirect (rw ,r ,params .redirectURL .String (),http .StatusFound )
163
196
}
164
-
165
- // Always wrap with its custom mw.
166
- return authorizeMW (accessURL )(http .HandlerFunc (handler )).ServeHTTP
167
197
}