2023-01-23 15:45:31 +01:00

129 lines
3.5 KiB
Go

// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.
package oidc
import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"
goidc "github.com/coreos/go-oidc/v3/oidc"
)
func TestRoute_start(t *testing.T) {
// setup fake OIDC service
idpUrl := newFakeIdP(t)
// setup test server with client routes
baseUrl, _, configId := newTestServer(t, testServerParams{
issuer: idpUrl,
returnToURL: "",
})
// go to /start
// don't follow redirect
client := &http.Client{
Timeout: 10 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := client.Get(baseUrl + "/oidc/start?id=" + configId)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
redirectUrl, err := resp.Location()
require.NoError(t, err)
require.Contains(t, redirectUrl.String(), idpUrl, "should redirect to IdP")
}
func TestRoute_callback(t *testing.T) {
// setup fake OIDC service
idpUrl := newFakeIdP(t)
// setup test server with client routes
baseUrl, stateParam, _ := newTestServer(t, testServerParams{
issuer: idpUrl,
returnToURL: "/relative/url/to/some/page",
})
state, err := encodeStateParam(*stateParam)
require.NoError(t, err)
// hit the /callback endpoint
client := &http.Client{
Timeout: 10 * time.Second,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
req, err := http.NewRequest("GET", baseUrl+"/oidc/callback?code=123&state="+state, nil)
require.NoError(t, err)
req.AddCookie(&http.Cookie{
Name: "state", Value: state, MaxAge: 60,
})
req.AddCookie(&http.Cookie{
Name: "nonce", Value: "111", MaxAge: 60,
})
resp, err := client.Do(req)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode, "callback should response with redirect (307)")
require.NotEmpty(t, resp.Cookies(), "missing cookies on redirect")
require.Equal(t, "test-cookie", resp.Cookies()[0].Name, "missing cookie on redirect")
url, err := resp.Location()
require.NoError(t, err)
require.Equal(t, "/relative/url/to/some/page", url.Path, "callback redirects properly")
}
type testServerParams struct {
issuer string
returnToURL string
clientID string
}
func newTestServer(t *testing.T, params testServerParams) (url string, state *StateParam, configId string) {
router := chi.NewRouter()
oidcService, dbConn := setupOIDCServiceForTests(t)
router.Mount("/oidc", Router(oidcService))
ts := httptest.NewServer(router)
url = ts.URL
oidcConfig := &goidc.Config{
ClientID: params.clientID,
SkipClientIDCheck: true,
SkipIssuerCheck: true,
SkipExpiryCheck: true,
InsecureSkipSignatureCheck: true,
}
oauth2Config := &oauth2.Config{
ClientID: params.clientID,
ClientSecret: "secret",
Scopes: []string{goidc.ScopeOpenID, "profile", "email"},
}
clientConfig := &ClientConfig{
Issuer: params.issuer,
OAuth2Config: oauth2Config,
VerifierConfig: oidcConfig,
}
configId = createConfig(t, dbConn, clientConfig)
stateParam := &StateParam{
ClientConfigID: configId,
ReturnToURL: params.returnToURL,
}
return url, stateParam, configId
}