forked from ory/fosite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pushed_authorize_request_handler.go
78 lines (63 loc) · 2.93 KB
/
pushed_authorize_request_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright © 2024 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package fosite
import (
"context"
"errors"
"net/http"
"github.com/ory/fosite/i18n"
"github.com/ory/x/errorsx"
"github.com/ory/x/otelx"
"go.opentelemetry.io/otel/trace"
)
const (
ErrorPARNotSupported = "The OAuth 2.0 provider does not support Pushed Authorization Requests"
DebugPARStorageInvalid = "'PARStorage' not implemented"
DebugPARConfigMissing = "'PushedAuthorizeRequestConfigProvider' not implemented"
DebugPARRequestsHandlerMissing = "'PushedAuthorizeRequestHandlersProvider' not implemented"
)
// NewPushedAuthorizeRequest validates the request and produces an AuthorizeRequester object that can be stored
func (f *Fosite) NewPushedAuthorizeRequest(ctx context.Context, r *http.Request) (_ AuthorizeRequester, err error) {
ctx, span := trace.SpanFromContext(ctx).TracerProvider().Tracer("github.com/ory/fosite").Start(ctx, "Fosite.NewPushedAuthorizeRequest")
defer otelx.End(span, &err)
request := NewAuthorizeRequest()
request.Request.Lang = i18n.GetLangFromRequest(f.Config.GetMessageCatalog(ctx), r)
if r.Method != "POST" {
return request, errorsx.WithStack(ErrInvalidRequest.WithHintf("HTTP method is '%s', expected 'POST'.", r.Method))
}
if err := r.ParseMultipartForm(1 << 20); err != nil && err != http.ErrNotMultipart {
return request, errorsx.WithStack(ErrInvalidRequest.WithHint("Unable to parse HTTP body, make sure to send a properly formatted form request body.").WithWrap(err).WithDebug(err.Error()))
}
request.Form = r.Form
request.State = request.Form.Get("state")
// Authenticate the client in the same way as at the token endpoint
// (Section 2.3 of [RFC6749]).
client, err := f.AuthenticateClient(ctx, r, r.Form)
if err != nil {
var rfcerr *RFC6749Error
if errors.As(err, &rfcerr) && rfcerr.ErrorField != ErrInvalidClient.ErrorField {
return request, errorsx.WithStack(ErrInvalidClient.WithHint("The requested OAuth 2.0 Client could not be authenticated.").WithWrap(err).WithDebug(err.Error()))
}
return request, err
}
request.Client = client
// Reject the request if the "request_uri" authorization request
// parameter is provided.
if r.Form.Get("request_uri") != "" {
return request, errorsx.WithStack(ErrInvalidRequest.WithHint("The request must not contain 'request_uri'."))
}
// For private_key_jwt or basic auth client authentication, "client_id" may not inside the form
// However this is required by NewAuthorizeRequest implementation
if len(r.Form.Get("client_id")) == 0 {
r.Form.Set("client_id", client.GetID())
}
// Validate as if this is a new authorize request
fr, err := f.newAuthorizeRequest(ctx, r, true)
if err != nil {
return fr, err
}
if fr.GetRequestedScopes().Has("openid") && r.Form.Get("redirect_uri") == "" {
return fr, errorsx.WithStack(ErrInvalidRequest.WithHint("Query parameter 'redirect_uri' is required when performing an OpenID Connect flow."))
}
return fr, nil
}