pomerium/internal/oauth21/validate_client_test.go
Denis Mishin 777b3b12d2
mcp: client registration/token fixes (#5649)
## Summary

Fixes to MCP code registration and token requests. 

1. ease some requirements on fields that are RECOMMENDED 
2. fill in defaults
3. store both request and response in the client registration
4. check client secret in the /token request

## Related issues

- Fixes
https://linear.app/pomerium/issue/ENG-2462/mcp-ignore-unknown-grant-types-in-the-client-registration
- Fixes
https://linear.app/pomerium/issue/ENG-2461/mcp-support-client-secret-in-dynamic-client-registration
 
## User Explanation

<!-- How would you explain this change to the user? If this
change doesn't create any user-facing changes, you can leave
this blank. If filled out, add the `docs` label -->

## Checklist

- [x] reference any related issues
- [x] updated unit tests
- [x] add appropriate label (`enhancement`, `bug`, `breaking`,
`dependencies`, `ci`)
- [ ] ready for review
2025-06-11 11:28:24 -04:00

126 lines
3.5 KiB
Go

package oauth21_test
import (
"testing"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/proto"
"github.com/pomerium/pomerium/internal/oauth21"
"github.com/pomerium/pomerium/internal/oauth21/gen"
rfc7591v1 "github.com/pomerium/pomerium/internal/rfc7591"
)
func TestValidateRequest(t *testing.T) {
t.Parallel()
clientBasic := rfc7591v1.TokenEndpointAuthMethodClientSecretBasic
clientNone := rfc7591v1.TokenEndpointAuthMethodNone
for _, tc := range []struct {
name string
client *rfc7591v1.Metadata
req *gen.AuthorizationRequest
err bool
}{
{
"default token auth method, no code challenge",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/callback"),
},
true,
},
{
"none token auth method, no code challenge",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientNone,
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/callback"),
},
true,
},
{
"none token auth method, code challenge is provided",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientNone,
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/callback"),
CodeChallenge: proto.String("challenge"),
},
false,
},
{
"none token auth method, code challenge and method are provided",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientNone,
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/callback"),
CodeChallenge: proto.String("challenge"),
CodeChallengeMethod: proto.String("S256"),
},
false,
},
{
"optional redirect_uri, multiple redirect_uris",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientBasic,
},
&gen.AuthorizationRequest{
RedirectUri: nil,
},
true,
},
{
"optional redirect_uri, single redirect_uri",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback"},
TokenEndpointAuthMethod: &clientBasic,
},
&gen.AuthorizationRequest{
RedirectUri: nil,
},
false,
},
{
"matching redirect_uri",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientBasic,
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/callback"),
},
false,
},
{
"non-matching redirect_uri",
&rfc7591v1.Metadata{
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
TokenEndpointAuthMethod: &clientBasic,
},
&gen.AuthorizationRequest{
RedirectUri: proto.String("https://example.com/invalid-callback"),
},
true,
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
err := oauth21.ValidateAuthorizationRequest(tc.client, tc.req)
if tc.err {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}