From 741e638c78e696126fa095d2bb329c0466805fdc Mon Sep 17 00:00:00 2001 From: Melora Hugues Date: Sat, 17 Aug 2024 15:22:37 +0200 Subject: [PATCH] Add basic support to store auth_requests (#48) --- polyculeconnect/internal/middlewares/test.go | 6 + polyculeconnect/internal/model/authrequest.go | 116 ++++++++++++++++++ polyculeconnect/internal/model/client.go | 10 +- polyculeconnect/internal/storage/storage.go | 8 +- 4 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 polyculeconnect/internal/model/authrequest.go diff --git a/polyculeconnect/internal/middlewares/test.go b/polyculeconnect/internal/middlewares/test.go index 548714b..1f83086 100644 --- a/polyculeconnect/internal/middlewares/test.go +++ b/polyculeconnect/internal/middlewares/test.go @@ -3,6 +3,7 @@ package middlewares import ( "context" "net/http" + "strings" ) const ( @@ -15,6 +16,11 @@ type BackendFromRequestMiddleware struct { } func (m *BackendFromRequestMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(r.RequestURI, "/authorize") { + m.h.ServeHTTP(w, r) + return + } + if err := r.ParseForm(); err != nil { // TODO: handle this better w.WriteHeader(http.StatusBadRequest) diff --git a/polyculeconnect/internal/model/authrequest.go b/polyculeconnect/internal/model/authrequest.go new file mode 100644 index 0000000..71c5f8e --- /dev/null +++ b/polyculeconnect/internal/model/authrequest.go @@ -0,0 +1,116 @@ +package model + +import ( + "fmt" + "strings" + "time" + + "github.com/google/uuid" + "github.com/zitadel/oidc/v3/pkg/oidc" +) + +// AuthRequest also implements the op.AuthRequest interface +type AuthRequest struct { + ID uuid.UUID + ClientID string + Scopes []string + RedirectURI string + State string + Nonce string + + ResponseType string + + CreationDate time.Time + AuthTime time.Time + + // TODO mapping to claims to be added I guess + + CodeChallenge string + CodeChallengeMethod string + + BackendID uuid.UUID + UserID uuid.UUID + done bool +} + +func (a AuthRequest) GetID() string { + return a.ID.String() +} + +func (a AuthRequest) GetACR() string { + return "" // TODO: the hell is ACR??? +} + +func (a AuthRequest) GetAMR() []string { + return []string{} // TODO: the hell is this??? +} + +func (a AuthRequest) GetAudience() []string { + return []string{a.ID.String()} // TODO: check if we need to return something else +} + +func (a AuthRequest) GetAuthTime() time.Time { + return a.AuthTime +} + +func (a AuthRequest) GetClientID() string { + return a.ClientID +} + +func (a AuthRequest) GetCodeChallenge() *oidc.CodeChallenge { + return &oidc.CodeChallenge{ + Challenge: a.CodeChallenge, + Method: oidc.CodeChallengeMethod(a.CodeChallengeMethod), + } +} + +func (a AuthRequest) GetNonce() string { + return a.Nonce +} + +func (a AuthRequest) GetRedirectURI() string { + return a.RedirectURI +} + +func (a AuthRequest) GetResponseType() oidc.ResponseType { + return oidc.ResponseType(a.ResponseType) +} + +func (a AuthRequest) GetResponseMode() oidc.ResponseMode { + return oidc.ResponseModeQuery // TODO: check if this is good +} + +func (a AuthRequest) GetScopes() []string { + return a.Scopes +} + +func (a AuthRequest) GetState() string { + return a.State +} + +func (a AuthRequest) GetSubject() string { + return a.UserID.String() +} + +func (a AuthRequest) Done() bool { + return a.done +} + +func (a *AuthRequest) FromOIDCAuthRequest(req *oidc.AuthRequest, backendID uuid.UUID) { + fmt.Println(req) + + a.ID = uuid.New() + a.ClientID = req.ClientID + a.Scopes = strings.Split(req.Scopes.String(), " ") + a.RedirectURI = req.RedirectURI + a.State = req.State + a.Nonce = req.Nonce + a.ResponseType = string(req.ResponseType) + a.CreationDate = time.Now().UTC() + a.CodeChallenge = req.CodeChallenge + a.CodeChallengeMethod = string(req.CodeChallengeMethod) + a.BackendID = backendID + + fmt.Println(a) + +} diff --git a/polyculeconnect/internal/model/client.go b/polyculeconnect/internal/model/client.go index 179bdaa..661aefb 100644 --- a/polyculeconnect/internal/model/client.go +++ b/polyculeconnect/internal/model/client.go @@ -13,6 +13,7 @@ type ClientConfig struct { RedirectURIs []string TrustedPeers []string Name string + AuthRequest *AuthRequest } type Client struct { @@ -47,8 +48,13 @@ func (c Client) GrantTypes() []oidc.GrantType { return []oidc.GrantType{oidc.GrantTypeCode} } -func (c Client) LoginURL(id string) string { - return id +func (c Client) LoginURL(authRequestID string) string { + // here we have the requestID, meaning we should: + // - get the request from its ID + // - get the associated backend + // - build the correct URI to use as a redirection, which is from the backend + // - afterwards would should basically handle it as a OIDC client + return authRequestID } func (c Client) AccessTokenType() op.AccessTokenType { diff --git a/polyculeconnect/internal/storage/storage.go b/polyculeconnect/internal/storage/storage.go index 22aa245..f0c9c84 100644 --- a/polyculeconnect/internal/storage/storage.go +++ b/polyculeconnect/internal/storage/storage.go @@ -7,6 +7,7 @@ import ( "time" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/db" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/model" "github.com/go-jose/go-jose/v4" "github.com/zitadel/oidc/v3/pkg/oidc" "github.com/zitadel/oidc/v3/pkg/op" @@ -30,12 +31,15 @@ func (s *Storage) CreateAuthRequest(ctx context.Context, req *oidc.AuthRequest, if !ok { return nil, errors.New("no backend name provided") } - _, err := s.LocalStorage.BackendStorage().GetBackendByName(ctx, backendName) + selectedBackend, err := s.LocalStorage.BackendStorage().GetBackendByName(ctx, backendName) if err != nil { return nil, fmt.Errorf("failed to get backend: %w", err) } - return nil, ErrNotImplemented("CreateAuthRequest") + var opReq model.AuthRequest + opReq.FromOIDCAuthRequest(req, selectedBackend.ID) + + return opReq, nil } func (s *Storage) AuthRequestByID(ctx context.Context, requestID string) (op.AuthRequest, error) {