mcp: handle and pass upstream oauth2 tokens (#5595)

This commit is contained in:
Denis Mishin 2025-05-01 12:42:31 -04:00 committed by GitHub
parent 561b6040b5
commit 9d66f762e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 337 additions and 80 deletions

View file

@ -4,15 +4,13 @@ import (
"fmt"
"net/http"
"github.com/bufbuild/protovalidate-go"
"github.com/pomerium/pomerium/internal/oauth21/gen"
)
// ParseCodeGrantAuthorizeRequest parses the authorization request for the code grant flow.
// see https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-4.1.1
// scopes are ignored
func ParseCodeGrantAuthorizeRequest(r *http.Request, sessionID string) (*gen.AuthorizationRequest, error) {
func ParseCodeGrantAuthorizeRequest(r *http.Request) (*gen.AuthorizationRequest, error) {
if err := r.ParseForm(); err != nil {
return nil, fmt.Errorf("failed to parse form: %w", err)
}
@ -24,11 +22,6 @@ func ParseCodeGrantAuthorizeRequest(r *http.Request, sessionID string) (*gen.Aut
State: optionalFormParam(r, "state"),
CodeChallenge: r.Form.Get("code_challenge"),
CodeChallengeMethod: optionalFormParam(r, "code_challenge_method"),
SessionId: sessionID,
}
if err := protovalidate.Validate(v); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
return v, nil

View file

@ -50,7 +50,10 @@ type AuthorizationRequest struct {
CodeChallengeMethod *string `protobuf:"bytes,7,opt,name=code_challenge_method,json=codeChallengeMethod,proto3,oneof" json:"code_challenge_method,omitempty"`
// session this authorization request is associated with.
// This is a Pomerium implementation specific field.
SessionId string `protobuf:"bytes,8,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
SessionId string `protobuf:"bytes,8,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
// user id this authorization request is associated with.
// This is a Pomerium implementation specific field.
UserId string `protobuf:"bytes,9,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -141,6 +144,13 @@ func (x *AuthorizationRequest) GetSessionId() string {
return ""
}
func (x *AuthorizationRequest) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
var File_authorization_request_proto protoreflect.FileDescriptor
var file_authorization_request_proto_rawDesc = string([]byte{
@ -148,7 +158,7 @@ var file_authorization_request_proto_rawDesc = string([]byte{
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6f,
0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xaa, 0x03, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x6f, 0x74, 0x6f, 0x22, 0xcb, 0x03, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x09,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
@ -171,21 +181,23 @@ var file_authorization_request_proto_rawDesc = string([]byte{
0x64, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f,
0x64, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d, 0x5f,
0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x08, 0x0a, 0x06,
0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f,
0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
0x42, 0x97, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31,
0x42, 0x19, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69,
0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x2f, 0x67, 0x65, 0x6e,
0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31,
0xca, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0xe2, 0x02, 0x13, 0x4f, 0x61, 0x75,
0x74, 0x68, 0x32, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0xea, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x07, 0x75,
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48,
0x03, 0xc8, 0x01, 0x01, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d,
0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x08, 0x0a,
0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x63, 0x6f, 0x64, 0x65,
0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f,
0x64, 0x42, 0x97, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32,
0x31, 0x42, 0x19, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72,
0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x2f, 0x67, 0x65,
0x6e, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32,
0x31, 0xca, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0xe2, 0x02, 0x13, 0x4f, 0x61,
0x75, 0x74, 0x68, 0x32, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0xea, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
})
var (

View file

@ -10,7 +10,7 @@ option go_package = "github.com/pomerium/pomerium/internal/oauth21/gen";
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-4.1.1
message AuthorizationRequest {
// The client identifier as described in Section 2.2.
string client_id = 1 [ (buf.validate.field).required = true ];
string client_id = 1 [(buf.validate.field).required = true];
// OPTIONAL if only one redirect URI is registered for this client. REQUIRED
// if multiple redirict URIs are registered for this client.
@ -23,7 +23,7 @@ message AuthorizationRequest {
// code flow.
string response_type = 3 [
(buf.validate.field).required = true,
(buf.validate.field).string = {in : [ "code" ]}
(buf.validate.field).string = {in: ["code"]}
];
// OPTIONAL. An opaque value used by the client to maintain state between the
@ -37,15 +37,17 @@ message AuthorizationRequest {
// REQUIRED, assumes https://www.rfc-editor.org/rfc/rfc7636.html#section-4.1
string code_challenge = 6 [
(buf.validate.field).required = true,
(buf.validate.field).string = {min_len : 43, max_len : 128}
(buf.validate.field).string = {min_len: 43, max_len: 128}
];
// OPTIONAL, defaults to plain if not present in the request. Code verifier
// transformation method is S256 or plain.
optional string code_challenge_method = 7
[ (buf.validate.field).string = {in : [ "S256", "plain" ]} ];
optional string code_challenge_method = 7 [(buf.validate.field).string = {in: ["S256", "plain"]}];
// session this authorization request is associated with.
// This is a Pomerium implementation specific field.
string session_id = 8 [ (buf.validate.field).required = true ];
string session_id = 8 [(buf.validate.field).required = true];
// user id this authorization request is associated with.
// This is a Pomerium implementation specific field.
string user_id = 9 [(buf.validate.field).required = true];
}