callback_handler.go: initial API/test shape with 1 test

Signed-off-by: Andrew Keesler <akeesler@vmware.com>
This commit is contained in:
Andrew Keesler 2020-11-13 12:31:39 -05:00
parent d351ef430c
commit 81b9a48437
No known key found for this signature in database
GPG Key ID: 27CE0444346F9413
2 changed files with 100 additions and 0 deletions

View File

@ -0,0 +1,21 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package callback provides a handler for the OIDC callback endpoint.
package callback
import (
"net/http"
"go.pinniped.dev/internal/httputil/httperr"
)
func NewHandler() http.Handler {
return httperr.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
if r.Method != http.MethodGet {
return httperr.Newf(http.StatusMethodNotAllowed, "%s (try GET)", r.Method)
}
return nil
})
}

View File

@ -0,0 +1,79 @@
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package callback
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
)
func TestCallbackEndpoint(t *testing.T) {
tests := []struct {
name string
method string
wantStatus int
wantBody string
}{
// Happy path
// TODO: GET with good state and cookie and successful upstream token exchange and 302 to downstream client callback with its state and code
// Pre-upstream-exchange verification
{
name: "PUT method is invalid",
method: http.MethodPut,
wantStatus: http.StatusMethodNotAllowed,
wantBody: "Method Not Allowed: PUT (try GET)\n",
},
// TODO: POST/PATCH/DELETE is invalid
// TODO: request has body? maybe we don't need to do anything...
// TODO: code does not exist
// TODO: we got called twice with the same state and cookie...is this bad? might be ok if the client's first roundtrip failed
// TODO: we got called twice with the same state and cookie and the UpstreamOIDCProvider CRD has been deleted
// TODO: state does not exist
// TODO: invalid signature on state
// TODO: state is expired (the expiration is encoded in the state itself)
// TODO: state csrf value does not match csrf cookie
// TODO: cookie does not exist
// TODO: invalid signature on cookie
// TODO: state version does not match what we want
// Upstream exchange
// TODO: we can't figure out what the upstream token endpoint is (do we get this UpstreamOIDCProvider name from the path?)
// TODO: network call to upstream token endpoint fails
// TODO: the upstream token endpoint returns an error
// Post-upstream-exchange verification
// TODO: returned tokens are invalid (all the stuff from the spec...)
// TODO: there
// TODO: are
// TODO: probably
// TODO: a
// TODO: lot
// TODO: of
// TODO: test
// TODO: cases
// TODO: here (e.g., id jwt cannot be verified, nonce is wrong, we didn't get refresh token, we didn't get access token, we didn't get id token, access token expires too quickly)
// Downstream redirect
// TODO: cannot generate auth code
// TODO: cannot persist downstream state
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
subject := NewHandler()
req := httptest.NewRequest(test.method, "/path-is-not-yet-tested", nil /* body not yet tested */)
rsp := httptest.NewRecorder()
subject.ServeHTTP(rsp, req)
require.Equal(t, test.wantStatus, rsp.Code)
require.Equal(t, test.wantBody, rsp.Body.String())
})
}
}