Skip to content

Conversation

@ardaguclu
Copy link
Member

This PR is revamped version of #172.

If Authorization URL is set, that means MCP Server is asked to validate the tokens from the given issuer url.

This PR adds support this. Currently, the expectation is to get one token regardless of the authorization url is specified or not. And this token is used against API Server after validated.

return s.k.GetAPIServerHost()
}

func (s *Server) GetOIDCProvider() *oidc.Provider {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OIDCProvider is exported. Maybe we don't need this function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can clean up everything in a follow-up PR once usage is clarified

}

// Scopes are likely to be used for authorization.
scopes := claims.GetScopes()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the foundational work for scoped based authorization. This can also be used for logging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will probably need clarification and an enumeration of different scenarios in a specific issue or user story

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Once we have a clear picture about the role of the scopes, we'll need this ^^

@ardaguclu ardaguclu force-pushed the oidc-verification-2 branch from da2486a to e96cda1 Compare July 14, 2025 13:18
@ardaguclu
Copy link
Member Author

ardaguclu commented Jul 14, 2025

Just a summary of what the flow looks like if --require-oauth is enabled;

  • If authorization url is empty, that means our source of truth is the API Server defined in MCP Server. Every token will be validated against it.
  • If authorization url is not empty and one token is passed in Authorization header, that means our source of truth is Authorization URL and API Server defined in MCP Server. This token will be validated in Authorization url and API Server.
  • If authorization url is not empty and two tokens are passed in different headers, that means the token in the Authorization header will be validated via authorization url and the other will be validated via API Server.

// validateJWTToken validates basic JWT claims without signature verification
func validateJWTToken(token, audience string) error {
func (c *JWTClaims) ContainsAudience(audience string) bool {
switch aud := c.Audience.(type) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

audience is relatively arbitrary fields. So that we have to support different data structures.

@ardaguclu
Copy link
Member Author

@manusa this PR is ready for review. Regardless of the ways we decide to support in terms of auth, the changes in this PR will likely be relevant to keep us OAuth compliant.

Comment on lines +249 to +256
var oidcProvider *oidc.Provider
if m.StaticConfig.AuthorizationURL != "" {
provider, err := oidc.NewProvider(context.TODO(), m.StaticConfig.AuthorizationURL)
if err != nil {
return fmt.Errorf("unable to setup OIDC provider: %w", err)
}
oidcProvider = provider
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that oidc.Provider is basically passed along to the mcp.Server instance and in turn is then passed on to the http AuthorizationMiddleware function.

Eventually there's also a call to VerifyToken which in turn performs a call to the Kubernetes VerifyToken function.

There seems to be a lot of coupling here that might be possible to extract.

Since the http package is providing auth, IMO mcp should have nothing else to do in this area.

Anyway, this should be done after merging this PR and only if it's possible.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that is correct that there are a couple of tight couplings. I'm open to improve this.

Maybe we can directly pass oidcprovider instead of carrying via McpServer. That would be better. VerifyToken needs to access kubernetes which is managed in McpServer, this one might be difficult.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this #179?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With respect to VerifyToken, I'm open to suggestions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this #179?

Not sure yet, but it's a good start.

I'll be creating some more tests for further clarification of the auth flows.
I'll try to provide an alternate proposal (or incremental to #179) once I have a clearer picture.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate it. Thank you.

@manusa manusa added this to the 0.1.0 milestone Jul 16, 2025 — with automated-tasks
Copy link
Member

@manusa manusa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thx!

@manusa manusa merged commit 7767161 into containers:main Jul 16, 2025
9 of 10 checks passed
@ardaguclu ardaguclu deleted the oidc-verification-2 branch July 16, 2025 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants