auth

Paddy 2015-01-18 Parent:fa8ee6a4507c Child:23c1a07c8a61

116:e000b1c24fc0 Go to Latest

auth/oauth2_test.go

Make all tests that deal with the store interfaces go through the Context. This is mainly important so that pre- and post- save/retrieval/deletion/whatever transforms can be done without doing them in every single implementation of the store. Change the Endpoint URI property to be a string, not a *url.URL. This makes testing easier, JSON responses cleaner, and is all around just a better strategy. Just because we turn it into a URL every now and then doesn't mean that's how we need to store it. Add JSON tags to the Client type and Endpoint type. Create normalizeURI and normalizeURIString methods to... well, normalize the Endpoint URIs. This makes it so that we can compare them, and forgive some arbitrary user behaviour (like slashes, etc.) Add a NormalizedURI property to the Endpoint type. This is where we store the NormalizedURI, which is what we'll be using when we want to check if an endpoint is valid or not. For the sake of tests and predictability, however, we always want to redirect to the URI, not the NormalizedURI. Add checks to the Client creation API endpoint to give better errors. Now leaving out the Type won't be considered an invalid type, it will be considered a missing parameter. An empty name will be reported as a missing parameter, a name with too few characters will be reported as an insufficient name, and a name with too many characters will be reported as an overflow name. We gather as many of these errors as apply before returning. Check if an Endpoint URI is absolute before adding it as an endpoint, or return an invalid value error if it is not. Always return the errors array when creating a client. We could succeed in creating one or more things and still have errors. We should return anything that's created _as well as_ any errors encountered. Add unit testing for our CreateClientHandler. Fix our oauth2 tests so that if there's an error in the body, it's in the test logs. This should help debugging significantly. Fix our oauth2 tests so that the Profile only requires 1 iteration for its password hashing. This means each time we want to validate a session, it doesn't add a full second to our test runs. This is a big speed improvement for our tests. Add test helper methods for comparing API errors, API responses, and filling in server-generated information in a response that it's impossible to have an expectation around (e.g., IDs) so that we can use our comparison helpers to check if a response is as we expect it. Fix a typo in our Context helpers that was reporting no sessionStore being set _only_ when a sessionStore was set. So yes, the opposite of what we wanted. Oops. This was discovered by passing all our tests through the context. methods instead of operating on the stores themselves.

History
     1.1 --- a/oauth2_test.go	Wed Jan 14 00:23:30 2015 -0500
     1.2 +++ b/oauth2_test.go	Sun Jan 18 01:02:14 2015 -0500
     1.3 @@ -30,7 +30,7 @@
     1.4  	t.Parallel()
     1.5  	store := NewMemstore()
     1.6  	testContext := Context{
     1.7 -		template:  template.Must(template.New(getAuthorizationCodeTemplateName).Parse("Get auth grant")),
     1.8 +		template:  template.Must(template.New(getAuthorizationCodeTemplateName).Parse("{{ if not .error }}Get auth grant{{ else }}{{ .error }}{{ end }}")),
     1.9  		clients:   store,
    1.10  		authCodes: store,
    1.11  		profiles:  store,
    1.12 @@ -46,17 +46,13 @@
    1.13  		Website: "https://secondbit.org",
    1.14  		Type:    "public",
    1.15  	}
    1.16 -	uri, err := url.Parse("https://test.secondbit.org/redirect")
    1.17 -	if err != nil {
    1.18 -		t.Fatal("Can't parse URL:", err)
    1.19 -	}
    1.20  	endpoint := Endpoint{
    1.21  		ID:       uuid.NewID(),
    1.22  		ClientID: client.ID,
    1.23 -		URI:      *uri,
    1.24 +		URI:      "https://test.secondbit.org/redirect",
    1.25  		Added:    time.Now(),
    1.26  	}
    1.27 -	err = testContext.SaveClient(client)
    1.28 +	err := testContext.SaveClient(client)
    1.29  	if err != nil {
    1.30  		t.Fatal("Can't store client:", err)
    1.31  	}
    1.32 @@ -96,7 +92,7 @@
    1.33  		params.Set("response_type", "code")
    1.34  		params.Set("client_id", client.ID.String())
    1.35  		if i&uriSet != 0 {
    1.36 -			params.Set("redirect_uri", endpoint.URI.String())
    1.37 +			params.Set("redirect_uri", endpoint.URI)
    1.38  		}
    1.39  		if i&scopeSet != 0 {
    1.40  			params.Set("scope", "testscope")
    1.41 @@ -110,6 +106,7 @@
    1.42  		req.Header.Del("Content-Type")
    1.43  		GetAuthorizationCodeHandler(w, req, testContext)
    1.44  		if w.Code != http.StatusOK {
    1.45 +			t.Log("Response body:", w.Body.String())
    1.46  			t.Errorf("Expected status code to be %d, got %d for %s", http.StatusOK, w.Code, req.URL.String())
    1.47  		}
    1.48  		if w.Body.String() != "Get auth grant" {
    1.49 @@ -147,8 +144,8 @@
    1.50  			t.Errorf(`Expected state param in redirect URL to be "%s", got "%s" for %s`, params.Get("state"), red.Query().Get("state"), req.URL.String())
    1.51  		}
    1.52  		stripParam("state", red)
    1.53 -		if red.String() != endpoint.URI.String() {
    1.54 -			t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI.String(), red.String())
    1.55 +		if red.String() != endpoint.URI {
    1.56 +			t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI, red.String())
    1.57  		}
    1.58  	}
    1.59  }
    1.60 @@ -244,11 +241,7 @@
    1.61  		Name:    "My test client",
    1.62  		Type:    "public",
    1.63  	}
    1.64 -	uri, err := url.Parse("https://test.secondbit.org/redirect")
    1.65 -	if err != nil {
    1.66 -		t.Fatal("Can't parse URL:", err)
    1.67 -	}
    1.68 -	err = testContext.SaveClient(client)
    1.69 +	err := testContext.SaveClient(client)
    1.70  	if err != nil {
    1.71  		t.Fatal("Can't store client:", err)
    1.72  	}
    1.73 @@ -284,7 +277,7 @@
    1.74  	endpoint := Endpoint{
    1.75  		ID:       uuid.NewID(),
    1.76  		ClientID: client.ID,
    1.77 -		URI:      *uri,
    1.78 +		URI:      "https://test.secondbit.org/redirect",
    1.79  		Added:    time.Now(),
    1.80  	}
    1.81  	err = testContext.AddEndpoints(client.ID, []Endpoint{endpoint})
    1.82 @@ -304,7 +297,7 @@
    1.83  	endpoint2 := Endpoint{
    1.84  		ID:       uuid.NewID(),
    1.85  		ClientID: client.ID,
    1.86 -		URI:      *uri,
    1.87 +		URI:      "https://test.secondbit.org/redirect",
    1.88  		Added:    time.Now(),
    1.89  	}
    1.90  	err = testContext.AddEndpoints(client.ID, []Endpoint{endpoint2})
    1.91 @@ -353,17 +346,13 @@
    1.92  		Website: "https://secondbit.org",
    1.93  		Type:    "public",
    1.94  	}
    1.95 -	uri, err := url.Parse("https://test.secondbit.org/redirect")
    1.96 -	if err != nil {
    1.97 -		t.Fatal("Can't parse URL:", err)
    1.98 -	}
    1.99  	endpoint := Endpoint{
   1.100  		ID:       uuid.NewID(),
   1.101  		ClientID: client.ID,
   1.102 -		URI:      *uri,
   1.103 +		URI:      "https://test.secondbit.org/redirect",
   1.104  		Added:    time.Now(),
   1.105  	}
   1.106 -	err = testContext.SaveClient(client)
   1.107 +	err := testContext.SaveClient(client)
   1.108  	if err != nil {
   1.109  		t.Fatal("Can't store client:", err)
   1.110  	}
   1.111 @@ -391,7 +380,7 @@
   1.112  	params := url.Values{}
   1.113  	params.Set("response_type", "totally not code")
   1.114  	params.Set("client_id", client.ID.String())
   1.115 -	params.Set("redirect_uri", endpoint.URI.String())
   1.116 +	params.Set("redirect_uri", endpoint.URI)
   1.117  	params.Set("scope", "testscope")
   1.118  	params.Set("state", "my super secure state string")
   1.119  	req.URL.RawQuery = params.Encode()
   1.120 @@ -413,8 +402,8 @@
   1.121  		t.Errorf(`Expected state param in redirect URL to be "%s", got "%s"`, params.Get("state"), red.Query().Get("state"))
   1.122  	}
   1.123  	stripParam("state", red)
   1.124 -	if red.String() != endpoint.URI.String() {
   1.125 -		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI.String(), red.String())
   1.126 +	if red.String() != endpoint.URI {
   1.127 +		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI, red.String())
   1.128  	}
   1.129  	stripParam("response_type", req.URL)
   1.130  	w = httptest.NewRecorder()
   1.131 @@ -435,8 +424,8 @@
   1.132  		t.Errorf(`Expected state param in redirect URL to be "%s", got "%s"`, params.Get("state"), red.Query().Get("state"))
   1.133  	}
   1.134  	stripParam("state", red)
   1.135 -	if red.String() != endpoint.URI.String() {
   1.136 -		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI.String(), red.String())
   1.137 +	if red.String() != endpoint.URI {
   1.138 +		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI, red.String())
   1.139  	}
   1.140  }
   1.141  
   1.142 @@ -460,17 +449,13 @@
   1.143  		Website: "https://secondbit.org",
   1.144  		Type:    "public",
   1.145  	}
   1.146 -	uri, err := url.Parse("https://test.secondbit.org/redirect")
   1.147 -	if err != nil {
   1.148 -		t.Fatal("Can't parse URL:", err)
   1.149 -	}
   1.150  	endpoint := Endpoint{
   1.151  		ID:       uuid.NewID(),
   1.152  		ClientID: client.ID,
   1.153 -		URI:      *uri,
   1.154 +		URI:      "https://test.secondbit.org/redirect",
   1.155  		Added:    time.Now(),
   1.156  	}
   1.157 -	err = testContext.SaveClient(client)
   1.158 +	err := testContext.SaveClient(client)
   1.159  	if err != nil {
   1.160  		t.Fatal("Can't store client:", err)
   1.161  	}
   1.162 @@ -498,7 +483,7 @@
   1.163  	params := url.Values{}
   1.164  	params.Set("response_type", "code")
   1.165  	params.Set("client_id", client.ID.String())
   1.166 -	params.Set("redirect_uri", endpoint.URI.String())
   1.167 +	params.Set("redirect_uri", endpoint.URI)
   1.168  	params.Set("scope", "testscope")
   1.169  	params.Set("state", "my super secure state string")
   1.170  	data := url.Values{}
   1.171 @@ -524,8 +509,8 @@
   1.172  		t.Errorf(`Expected state param in redirect URL to be "%s", got "%s"`, params.Get("state"), red.Query().Get("state"))
   1.173  	}
   1.174  	stripParam("state", red)
   1.175 -	if red.String() != endpoint.URI.String() {
   1.176 -		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI.String(), red.String())
   1.177 +	if red.String() != endpoint.URI {
   1.178 +		t.Errorf(`Expected redirect URL to be "%s", got "%s"`, endpoint.URI, red.String())
   1.179  	}
   1.180  }
   1.181  
   1.182 @@ -690,9 +675,9 @@
   1.183  	profile := Profile{
   1.184  		ID:                     uuid.NewID(),
   1.185  		Name:                   "Test User",
   1.186 -		Passphrase:             "febcbe74b9555ab3dd0135bdc3aa86d2ee5c38dd7fd44f7b6e2ea908e93b1362",
   1.187 -		Iterations:             1048576,
   1.188 -		Salt:                   "c0feab6ae682e7f7d14343b669b8afaa3b17ed72e9bb18a73f002be4c6b21686",
   1.189 +		Passphrase:             "f3a4ac4f1d657b2e6e776d24213e39406d50a87a52691a2a78891425af1271d0",
   1.190 +		Iterations:             1,
   1.191 +		Salt:                   "d82d92cfa8bfb5a08270ebbf39a3710d24b352b937fcc8959ebcb40384cc616b",
   1.192  		PassphraseScheme:       1,
   1.193  		Compromised:            false,
   1.194  		LockedUntil:            time.Time{},