forked from mystiq/dex
a418e1c4e7
adds a client manager to handle business logic, leaving the repo for basic crud operations. Also adds client to the test script
161 lines
4.4 KiB
Go
161 lines
4.4 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/coreos/go-oidc/oauth2"
|
|
"github.com/coreos/go-oidc/oidc"
|
|
"github.com/kylelemons/godebug/pretty"
|
|
)
|
|
|
|
func TestClientRegistration(t *testing.T) {
|
|
tests := []struct {
|
|
body string
|
|
code int
|
|
}{
|
|
{"", http.StatusBadRequest},
|
|
{
|
|
`{
|
|
"redirect_uris": [
|
|
"https://client.example.org/callback",
|
|
"https://client.example.org/callback2"
|
|
]
|
|
}`,
|
|
http.StatusCreated,
|
|
},
|
|
{
|
|
// Requesting unsupported client metadata fields (user_info_encrypted).
|
|
`{
|
|
"application_type": "web",
|
|
"redirect_uris":[
|
|
"https://client.example.org/callback",
|
|
"https://client.example.org/callback2"
|
|
],
|
|
"client_name": "My Example",
|
|
"logo_uri": "https://client.example.org/logo.png",
|
|
"subject_type": "pairwise",
|
|
"sector_identifier_uri": "https://other.example.net/file_of_redirect_uris.json",
|
|
"token_endpoint_auth_method": "client_secret_basic",
|
|
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
|
|
"userinfo_encrypted_response_alg": "RSA1_5",
|
|
"userinfo_encrypted_response_enc": "A128CBC-HS256",
|
|
"contacts": ["ve7jtb@example.org", "mary@example.org"],
|
|
"request_uris": [
|
|
"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA" ]
|
|
}`,
|
|
http.StatusBadRequest,
|
|
},
|
|
{
|
|
`{
|
|
"application_type": "web",
|
|
"redirect_uris":[
|
|
"https://client.example.org/callback",
|
|
"https://client.example.org/callback2"
|
|
],
|
|
"client_name": "My Example",
|
|
"logo_uri": "https://client.example.org/logo.png",
|
|
"subject_type": "pairwise",
|
|
"sector_identifier_uri": "https://other.example.net/file_of_redirect_uris.json",
|
|
"token_endpoint_auth_method": "client_secret_basic",
|
|
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
|
|
"contacts": ["ve7jtb@example.org", "mary@example.org"],
|
|
"request_uris": [
|
|
"https://client.example.org/rf.txt#qpXaRLh_n93TTR9F252ValdatUQvQiJi5BDub2BeznA" ]
|
|
}`,
|
|
http.StatusCreated,
|
|
},
|
|
}
|
|
|
|
var handler http.Handler
|
|
f := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
handler.ServeHTTP(w, r)
|
|
})
|
|
testServer := httptest.NewServer(f)
|
|
|
|
issuerURL, err := url.Parse(testServer.URL)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer testServer.Close()
|
|
|
|
for i, tt := range tests {
|
|
fixtures, err := makeTestFixtures()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
fixtures.srv.IssuerURL = *issuerURL
|
|
fixtures.srv.EnableClientRegistration = true
|
|
|
|
handler = fixtures.srv.HTTPHandler()
|
|
|
|
err = func() error {
|
|
// GET provider config through discovery URL.
|
|
resp, err := http.Get(testServer.URL + "/.well-known/openid-configuration")
|
|
if err != nil {
|
|
return fmt.Errorf("GET config: %v", err)
|
|
}
|
|
var cfg oidc.ProviderConfig
|
|
err = json.NewDecoder(resp.Body).Decode(&cfg)
|
|
resp.Body.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("decode resp: %v", err)
|
|
}
|
|
|
|
if cfg.RegistrationEndpoint == nil {
|
|
return errors.New("registration endpoint not available")
|
|
}
|
|
|
|
// POST registration request to registration endpoint.
|
|
body := strings.NewReader(tt.body)
|
|
resp, err = http.Post(cfg.RegistrationEndpoint.String(), "application/json", body)
|
|
if err != nil {
|
|
return fmt.Errorf("POSTing client metadata: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != tt.code {
|
|
return fmt.Errorf("expected status code=%d, got=%d", tt.code, resp.StatusCode)
|
|
}
|
|
|
|
if resp.StatusCode != http.StatusCreated {
|
|
var oauthErr oauth2.Error
|
|
if err := json.NewDecoder(resp.Body).Decode(&oauthErr); err != nil {
|
|
return fmt.Errorf("failed to decode oauth2 error: %v", err)
|
|
}
|
|
if oauthErr.Type == "" {
|
|
return fmt.Errorf("got oauth2 error with no 'error' field")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Read registration response.
|
|
var r oidc.ClientRegistrationResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
|
|
return fmt.Errorf("decode response: %v", err)
|
|
}
|
|
if r.ClientID == "" {
|
|
return fmt.Errorf("no client id in registration response")
|
|
}
|
|
|
|
metadata, err := fixtures.clientManager.Metadata(r.ClientID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to lookup client id after creation")
|
|
}
|
|
|
|
if diff := pretty.Compare(&metadata, &r.ClientMetadata); diff != "" {
|
|
return fmt.Errorf("metadata in response did not match metadata in db: %s", diff)
|
|
}
|
|
|
|
return nil
|
|
}()
|
|
if err != nil {
|
|
t.Errorf("case %d: %v", i, err)
|
|
}
|
|
}
|
|
}
|