diff --git a/internal/client/delivery/http/client_http.go b/internal/client/delivery/http/client_http.go index 479dd8c..5bc3e89 100644 --- a/internal/client/delivery/http/client_http.go +++ b/internal/client/delivery/http/client_http.go @@ -1,7 +1,7 @@ package http import ( - "fmt" + "errors" "strings" "github.com/fasthttp/router" @@ -19,9 +19,11 @@ import ( type ( CallbackRequest struct { - Code string `form:"code"` - State string `form:"state"` - Iss *domain.ClientID `form:"iss"` + Iss *domain.ClientID `form:"iss"` + Code string `form:"code"` + Error string `form:"error"` + ErrorDescription string `form:"error_description"` + State string `form:"state"` } NewRequestHandlerOptions struct { @@ -92,6 +94,12 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) { return } + if req.Error != "" { + ctx.Error(req.ErrorDescription, http.StatusUnauthorized) + + return + } + // TODO(toby3d): load and check state if req.Iss.String() != h.client.ID.String() { @@ -100,7 +108,7 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) { return } - token, err := h.tokens.Exchange(ctx, token.ExchangeOptions{ + token, _, err := h.tokens.Exchange(ctx, token.ExchangeOptions{ ClientID: h.client.ID, RedirectURI: h.client.RedirectURI[0], Code: req.Code, @@ -127,8 +135,14 @@ func (h *RequestHandler) handleCallback(ctx *http.RequestCtx) { } func (req *CallbackRequest) bind(ctx *http.RequestCtx) error { + indieAuthError := new(domain.Error) + if err := form.Unmarshal(ctx.QueryArgs(), req); err != nil { - return fmt.Errorf("cannot unmarshal request: %w", err) + if errors.As(err, indieAuthError) { + return indieAuthError + } + + return domain.NewError(domain.ErrorCodeInvalidRequest, err.Error(), "") } return nil diff --git a/internal/client/repository.go b/internal/client/repository.go index 2a66256..797f110 100644 --- a/internal/client/repository.go +++ b/internal/client/repository.go @@ -2,7 +2,6 @@ package client import ( "context" - "errors" "source.toby3d.me/website/indieauth/internal/domain" ) @@ -11,4 +10,4 @@ type Repository interface { Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) } -var ErrNotExist = errors.New("client with the specified ID does not exist") +var ErrNotExist error = domain.NewError(domain.ErrorCodeInvalidClient, "client with the specified ID does not exist", "") diff --git a/internal/client/repository/http/http_client.go b/internal/client/repository/http/http_client.go index 07392e4..fe61056 100644 --- a/internal/client/repository/http/http_client.go +++ b/internal/client/repository/http/http_client.go @@ -15,17 +15,15 @@ type httpClientRepository struct { client *http.Client } -const DefaultMaxRedirectsCount int = 10 - const ( + DefaultMaxRedirectsCount int = 10 + + hApp string = "h-app" + hXApp string = "h-x-app" + propertyLogo string = "logo" + propertyName string = "name" + propertyURL string = "url" relRedirectURI string = "redirect_uri" - - hApp string = "h-app" - hXApp string = "h-x-app" - - propertyLogo string = "logo" - propertyName string = "name" - propertyURL string = "url" ) func NewHTTPClientRepository(c *http.Client) client.Repository { @@ -48,7 +46,7 @@ func (repo *httpClientRepository) Get(ctx context.Context, id *domain.ClientID) } if resp.StatusCode() == http.StatusNotFound { - return nil, client.ErrNotExist + return nil, fmt.Errorf("%w: status on client page is not 200", client.ErrNotExist) } client := &domain.Client{ diff --git a/internal/client/repository/memory/memory_client.go b/internal/client/repository/memory/memory_client.go index 9ed6892..6fc08e5 100644 --- a/internal/client/repository/memory/memory_client.go +++ b/internal/client/repository/memory/memory_client.go @@ -2,6 +2,7 @@ package memory import ( "context" + "fmt" "path" "sync" @@ -30,12 +31,12 @@ func (repo *memoryClientRepository) Create(ctx context.Context, client *domain.C func (repo *memoryClientRepository) Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) { src, ok := repo.store.Load(path.Join(DefaultPathPrefix, id.String())) if !ok { - return nil, client.ErrNotExist + return nil, fmt.Errorf("cannot find client in store: %w", client.ErrNotExist) } c, ok := src.(*domain.Client) if !ok { - return nil, client.ErrNotExist + return nil, fmt.Errorf("cannot decode client from store: %w", client.ErrNotExist) } return c, nil diff --git a/internal/client/usecase.go b/internal/client/usecase.go index 305caa1..b214624 100644 --- a/internal/client/usecase.go +++ b/internal/client/usecase.go @@ -2,7 +2,6 @@ package client import ( "context" - "errors" "source.toby3d.me/website/indieauth/internal/domain" ) @@ -12,4 +11,8 @@ type UseCase interface { Discovery(ctx context.Context, id *domain.ClientID) (*domain.Client, error) } -var ErrInvalidMe = errors.New("invalid me") +var ErrInvalidMe error = domain.NewError( + domain.ErrorCodeInvalidRequest, + "cannot fetch client endpoints on provided me", + "", +)