mirror of
https://github.com/pomerium/pomerium.git
synced 2025-07-19 17:50:17 +02:00
mcp: token: handle authorization_code request (pt1)
This commit is contained in:
parent
9e4947c62f
commit
625c9d4014
11 changed files with 740 additions and 25 deletions
|
@ -2,9 +2,64 @@ package mcp
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/log"
|
||||
"github.com/pomerium/pomerium/internal/oauth21"
|
||||
oauth21proto "github.com/pomerium/pomerium/internal/oauth21/gen"
|
||||
)
|
||||
|
||||
// Token handles the /token endpoint.
|
||||
func (srv *Handler) Token(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
func (srv *Handler) Token(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
req, err := oauth21.ParseTokenRequest(r)
|
||||
if err != nil {
|
||||
log.Ctx(r.Context()).Error().Err(err).Msg("failed to parse token request")
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidRequest)
|
||||
return
|
||||
}
|
||||
|
||||
switch req.GrantType {
|
||||
case "authorization_code":
|
||||
srv.handleAuthorizationCodeToken(w, r, req)
|
||||
default:
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.UnsupportedGrantType)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.Request, req *oauth21proto.TokenRequest) {
|
||||
ctx := r.Context()
|
||||
|
||||
if req.ClientId == nil {
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidClient)
|
||||
return
|
||||
}
|
||||
if req.Code == nil {
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||
return
|
||||
}
|
||||
code, err := DecryptCode(*req.Code, srv.cipher, *req.ClientId, time.Now())
|
||||
if err != nil {
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||
return
|
||||
}
|
||||
|
||||
authReq, err := srv.storage.GetAuthorizationRequest(ctx, code.Id)
|
||||
if err != nil {
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||
return
|
||||
}
|
||||
|
||||
err = AuthorizeTokenRequest(req, authReq)
|
||||
if err != nil {
|
||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "Not Implemented", http.StatusNotImplemented)
|
||||
}
|
||||
|
|
37
internal/mcp/token.go
Normal file
37
internal/mcp/token.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package mcp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/oauth21"
|
||||
"github.com/pomerium/pomerium/internal/oauth21/gen"
|
||||
)
|
||||
|
||||
func AuthorizeTokenRequest(
|
||||
tokReq *gen.TokenRequest,
|
||||
authReq *gen.AuthorizationRequest,
|
||||
) error {
|
||||
if tokReq.GrantType != "authorization_code" {
|
||||
return fmt.Errorf("unexpected grant type: %s", tokReq.GrantType)
|
||||
}
|
||||
|
||||
if tokReq.ClientId == nil {
|
||||
return fmt.Errorf("token request: missing client_id")
|
||||
} else if *tokReq.ClientId != authReq.ClientId {
|
||||
return fmt.Errorf("token request: client_id does not match authorization request")
|
||||
}
|
||||
|
||||
if authReq.CodeChallengeMethod == nil || *authReq.CodeChallengeMethod == "plain" {
|
||||
if !oauth21.VerifyPKCEPlain(*tokReq.CodeVerifier, authReq.CodeChallenge) {
|
||||
return fmt.Errorf("plain: code verifier does not match code challenge")
|
||||
}
|
||||
} else if *authReq.CodeChallengeMethod == "S256" {
|
||||
if !oauth21.VerifyPKCES256(*tokReq.CodeVerifier, authReq.CodeChallenge) {
|
||||
return fmt.Errorf("S256: code verifier does not match code challenge")
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("unsupported code challenge method: %s", *authReq.CodeChallengeMethod)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue