Skip to content

Commit 9cc5f28

Browse files
authored
fix: advertise support for response_mode=form_post in OIDC discovery document (#3861)
1 parent e278b40 commit 9cc5f28

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

cmd/cmd_perform_authorization_code.go

+29-15
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,21 @@ import (
1414
"html/template"
1515
"io"
1616
"net/http"
17+
"net/url"
1718
"os"
1819
"strconv"
1920
"strings"
2021
"time"
2122

22-
openapi "github.com/ory/hydra-client-go/v2"
23-
"github.com/ory/hydra/v2/cmd/cliclient"
24-
25-
"github.com/pkg/errors"
26-
27-
"github.com/ory/graceful"
28-
2923
"github.com/julienschmidt/httprouter"
24+
"github.com/pkg/errors"
3025
"github.com/spf13/cobra"
3126
"github.com/toqueteos/webbrowser"
3227
"golang.org/x/oauth2"
3328

29+
"github.com/ory/graceful"
30+
openapi "github.com/ory/hydra-client-go/v2"
31+
"github.com/ory/hydra/v2/cmd/cliclient"
3432
"github.com/ory/x/cmdx"
3533
"github.com/ory/x/flagx"
3634
"github.com/ory/x/pointerx"
@@ -132,7 +130,7 @@ var tokenUserResult = template.Must(template.New("").Parse(`<html>
132130
<ul>
133131
<li>Access Token: <code>{{ .AccessToken }}</code></li>
134132
<li>Refresh Token: <code>{{ .RefreshToken }}</code></li>
135-
<li>Expires in: <code>{{ .Expiry }}</code></li>
133+
<li>Expires at: <code>{{ .Expiry }}</code></li>
136134
<li>ID Token: <code>{{ .IDToken }}</code></li>
137135
</ul>
138136
{{ if .DisplayBackButton }}
@@ -170,6 +168,7 @@ and success, unless if the --no-shutdown flag is provided.`,
170168
audience := flagx.MustGetStringSlice(cmd, "audience")
171169
noShutdown := flagx.MustGetBool(cmd, "no-shutdown")
172170
skip := flagx.MustGetBool(cmd, "skip")
171+
responseMode := flagx.MustGetString(cmd, "response-mode")
173172

174173
clientID := flagx.MustGetString(cmd, "client-id")
175174
if clientID == "" {
@@ -229,6 +228,9 @@ and success, unless if the --no-shutdown flag is provided.`,
229228
if maxAge >= 0 {
230229
opts = append(opts, oauth2.SetAuthURLParam("max_age", strconv.Itoa(maxAge)))
231230
}
231+
if responseMode != "" {
232+
opts = append(opts, oauth2.SetAuthURLParam("response_mode", responseMode))
233+
}
232234

233235
authCodeURL := conf.AuthCodeURL(state, opts...)
234236
return authCodeURL, state
@@ -293,6 +295,7 @@ and success, unless if the --no-shutdown flag is provided.`,
293295
r.GET("/consent", rt.consentGET)
294296
r.POST("/consent", rt.consentPOST)
295297
r.GET("/callback", rt.callback)
298+
r.POST("/callback", rt.callbackPOSTForm)
296299

297300
if !flagx.MustGetBool(cmd, "no-open") {
298301
_ = webbrowser.Open(serverLocation) // ignore errors
@@ -336,6 +339,7 @@ and success, unless if the --no-shutdown flag is provided.`,
336339
cmd.Flags().String("token-url", "", "Usually it is enough to specify the `endpoint` flag, but if you want to force the token url, use this flag")
337340
cmd.Flags().Bool("https", false, "Sets up HTTPS for the endpoint using a self-signed certificate which is re-generated every time you start this command")
338341
cmd.Flags().Bool("skip", false, "Skip login and/or consent steps if possible. Only effective if you have configured the Login and Consent UI URLs to point to this server.")
342+
cmd.Flags().String("response-mode", "", "Set the response mode. Can be query (default) or form_post.")
339343

340344
return cmd
341345
}
@@ -566,6 +570,8 @@ func (rt *router) consentPOST(w http.ResponseWriter, r *http.Request, _ httprout
566570
}
567571

568572
func (rt *router) callback(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
573+
defer rt.onDone()
574+
569575
if len(r.URL.Query().Get("error")) > 0 {
570576
_, _ = fmt.Fprintf(rt.cmd.ErrOrStderr(), "Got error: %s\n", r.URL.Query().Get("error_description"))
571577

@@ -576,20 +582,18 @@ func (rt *router) callback(w http.ResponseWriter, r *http.Request, _ httprouter.
576582
Hint: r.URL.Query().Get("error_hint"),
577583
Debug: r.URL.Query().Get("error_debug"),
578584
})
579-
580-
rt.onDone()
581585
return
582586
}
583587

584588
if r.URL.Query().Get("state") != *rt.state {
585-
_, _ = fmt.Fprintf(rt.cmd.ErrOrStderr(), "States do not match. Expected %s, got %s\n", *rt.state, r.URL.Query().Get("state"))
589+
descr := fmt.Sprintf("States do not match. Expected %q, got %q.", *rt.state, r.URL.Query().Get("state"))
590+
_, _ = fmt.Fprintln(rt.cmd.ErrOrStderr(), descr)
586591

587592
w.WriteHeader(http.StatusInternalServerError)
588593
_ = tokenUserError.Execute(w, &ed{
589594
Name: "States do not match",
590-
Description: "Expected state " + *rt.state + " but got " + r.URL.Query().Get("state"),
595+
Description: descr,
591596
})
592-
rt.onDone()
593597
return
594598
}
595599

@@ -603,7 +607,6 @@ func (rt *router) callback(w http.ResponseWriter, r *http.Request, _ httprouter.
603607
_ = tokenUserError.Execute(w, &ed{
604608
Name: err.Error(),
605609
})
606-
rt.onDone()
607610
return
608611
}
609612

@@ -623,7 +626,18 @@ func (rt *router) callback(w http.ResponseWriter, r *http.Request, _ httprouter.
623626
BackURL: rt.serverLocation,
624627
DisplayBackButton: rt.noShutdown,
625628
})
626-
rt.onDone()
629+
}
630+
631+
func (rt *router) callbackPOSTForm(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
632+
if err := r.ParseForm(); err != nil {
633+
http.Error(w, err.Error(), http.StatusBadRequest)
634+
return
635+
}
636+
u := url.URL{
637+
Path: r.URL.Path,
638+
RawQuery: r.PostForm.Encode(),
639+
}
640+
http.Redirect(w, r, u.String(), http.StatusFound)
627641
}
628642

629643
type ed struct {

oauth2/handler.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func (h *Handler) discoverOidcConfiguration(w http.ResponseWriter, r *http.Reque
497497
IDTokenSignedResponseAlg: []string{key.Algorithm},
498498
UserinfoSignedResponseAlg: []string{key.Algorithm},
499499
GrantTypesSupported: []string{"authorization_code", "implicit", "client_credentials", "refresh_token"},
500-
ResponseModesSupported: []string{"query", "fragment"},
500+
ResponseModesSupported: []string{"query", "fragment", "form_post"},
501501
UserinfoSigningAlgValuesSupported: []string{"none", key.Algorithm},
502502
RequestParameterSupported: true,
503503
RequestURIParameterSupported: true,

0 commit comments

Comments
 (0)