2021-06-15 16:27:30 +00:00
|
|
|
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
2020-12-01 19:01:23 +00:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
package pkce
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2020-12-10 22:47:58 +00:00
|
|
|
"time"
|
2020-12-01 19:01:23 +00:00
|
|
|
|
|
|
|
"github.com/ory/fosite"
|
|
|
|
"github.com/ory/fosite/handler/pkce"
|
2020-12-01 22:53:22 +00:00
|
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
2020-12-01 19:01:23 +00:00
|
|
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
|
|
|
|
|
|
|
"go.pinniped.dev/internal/constable"
|
|
|
|
"go.pinniped.dev/internal/crud"
|
2020-12-01 22:53:22 +00:00
|
|
|
"go.pinniped.dev/internal/fositestorage"
|
2021-06-15 16:27:30 +00:00
|
|
|
"go.pinniped.dev/internal/oidc/clientregistry"
|
2021-10-06 22:28:13 +00:00
|
|
|
"go.pinniped.dev/internal/psession"
|
2020-12-01 19:01:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2020-12-04 23:40:17 +00:00
|
|
|
TypeLabelValue = "pkce"
|
|
|
|
|
2020-12-01 22:53:22 +00:00
|
|
|
ErrInvalidPKCERequestVersion = constable.Error("pkce request data has wrong version")
|
|
|
|
ErrInvalidPKCERequestData = constable.Error("pkce request data must be present")
|
2020-12-01 19:01:23 +00:00
|
|
|
|
2021-10-06 22:28:13 +00:00
|
|
|
pkceStorageVersion = "2"
|
2020-12-01 19:01:23 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var _ pkce.PKCERequestStorage = &pkceStorage{}
|
|
|
|
|
|
|
|
type pkceStorage struct {
|
|
|
|
storage crud.Storage
|
|
|
|
}
|
|
|
|
|
|
|
|
type session struct {
|
|
|
|
Request *fosite.Request `json:"request"`
|
|
|
|
Version string `json:"version"`
|
|
|
|
}
|
|
|
|
|
2020-12-10 22:47:58 +00:00
|
|
|
func New(secrets corev1client.SecretInterface, clock func() time.Time, sessionStorageLifetime time.Duration) pkce.PKCERequestStorage {
|
|
|
|
return &pkceStorage{storage: crud.New(TypeLabelValue, secrets, clock, sessionStorageLifetime)}
|
2020-12-01 19:01:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *pkceStorage) CreatePKCERequestSession(ctx context.Context, signature string, requester fosite.Requester) error {
|
2020-12-01 22:53:22 +00:00
|
|
|
request, err := fositestorage.ValidateAndExtractAuthorizeRequest(requester)
|
2020-12-01 19:01:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-04 22:31:06 +00:00
|
|
|
_, err = a.storage.Create(ctx, signature, &session{Request: request, Version: pkceStorageVersion}, nil)
|
2020-12-01 19:01:23 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *pkceStorage) GetPKCERequestSession(ctx context.Context, signature string, _ fosite.Session) (fosite.Requester, error) {
|
|
|
|
session, _, err := a.getSession(ctx, signature)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return session.Request, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *pkceStorage) DeletePKCERequestSession(ctx context.Context, signature string) error {
|
|
|
|
return a.storage.Delete(ctx, signature)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *pkceStorage) getSession(ctx context.Context, signature string) (*session, string, error) {
|
|
|
|
session := newValidEmptyPKCESession()
|
|
|
|
rv, err := a.storage.Get(ctx, signature, session)
|
|
|
|
|
2020-12-01 22:53:22 +00:00
|
|
|
if errors.IsNotFound(err) {
|
2020-12-17 20:09:19 +00:00
|
|
|
return nil, "", fosite.ErrNotFound.WithWrap(err).WithDebug(err.Error())
|
2020-12-01 22:53:22 +00:00
|
|
|
}
|
2020-12-01 19:01:23 +00:00
|
|
|
|
|
|
|
if err != nil {
|
2020-12-01 22:53:22 +00:00
|
|
|
return nil, "", fmt.Errorf("failed to get pkce session for %s: %w", signature, err)
|
2020-12-01 19:01:23 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 22:53:22 +00:00
|
|
|
if version := session.Version; version != pkceStorageVersion {
|
|
|
|
return nil, "", fmt.Errorf("%w: pkce session for %s has version %s instead of %s",
|
|
|
|
ErrInvalidPKCERequestVersion, signature, version, pkceStorageVersion)
|
|
|
|
}
|
2020-12-01 19:01:23 +00:00
|
|
|
|
2020-12-01 22:53:22 +00:00
|
|
|
if session.Request.ID == "" {
|
|
|
|
return nil, "", fmt.Errorf("malformed pkce session for %s: %w", signature, ErrInvalidPKCERequestData)
|
|
|
|
}
|
2020-12-01 19:01:23 +00:00
|
|
|
|
|
|
|
return session, rv, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func newValidEmptyPKCESession() *session {
|
|
|
|
return &session{
|
|
|
|
Request: &fosite.Request{
|
2021-06-15 16:27:30 +00:00
|
|
|
Client: &clientregistry.Client{},
|
2021-10-06 22:28:13 +00:00
|
|
|
Session: &psession.PinnipedSession{},
|
2020-12-01 19:01:23 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|