auth
auth/http_test.go
Actually validate grant requests. Write the logic to validate grant requests and stub out the rendering/error handling/redirecting locations. Finally, we get to the good stuff: implementing the specification. Write some tests to verify that granting requests works the way we think it does.
| paddy@52 | 1 package auth |
| paddy@52 | 2 |
| paddy@52 | 3 import ( |
| paddy@52 | 4 "html/template" |
| paddy@52 | 5 "net/http" |
| paddy@52 | 6 "net/http/httptest" |
| paddy@53 | 7 "net/url" |
| paddy@52 | 8 "testing" |
| paddy@56 | 9 "time" |
| paddy@56 | 10 |
| paddy@56 | 11 "code.secondbit.org/uuid" |
| paddy@52 | 12 ) |
| paddy@52 | 13 |
| paddy@53 | 14 const ( |
| paddy@53 | 15 scopeSet = 1 << iota |
| paddy@53 | 16 stateSet |
| paddy@53 | 17 uriSet |
| paddy@56 | 18 uriExact |
| paddy@53 | 19 ) |
| paddy@53 | 20 |
| paddy@52 | 21 func TestGetGrantCodeSuccess(t *testing.T) { |
| paddy@52 | 22 t.Parallel() |
| paddy@52 | 23 store := NewMemstore() |
| paddy@52 | 24 testContext := Context{ |
| paddy@52 | 25 template: template.Must(template.New(getGrantTemplateName).Parse("Get auth grant")), |
| paddy@52 | 26 clients: store, |
| paddy@52 | 27 grants: store, |
| paddy@52 | 28 profiles: store, |
| paddy@52 | 29 tokens: store, |
| paddy@52 | 30 } |
| paddy@56 | 31 client := Client{ |
| paddy@56 | 32 ID: uuid.NewID(), |
| paddy@56 | 33 Secret: "super secret!", |
| paddy@56 | 34 OwnerID: uuid.NewID(), |
| paddy@56 | 35 Name: "My test client", |
| paddy@56 | 36 Logo: "https://secondbit.org/logo.png", |
| paddy@56 | 37 Website: "https://secondbit.org", |
| paddy@56 | 38 Type: "public", |
| paddy@56 | 39 } |
| paddy@56 | 40 uri, err := url.Parse("https://test.secondbit.org/redirect") |
| paddy@56 | 41 if err != nil { |
| paddy@56 | 42 t.Fatal("Can't parse URL:", err) |
| paddy@56 | 43 } |
| paddy@56 | 44 endpoint := Endpoint{ |
| paddy@56 | 45 ID: uuid.NewID(), |
| paddy@56 | 46 ClientID: client.ID, |
| paddy@56 | 47 URI: *uri, |
| paddy@56 | 48 Added: time.Now(), |
| paddy@56 | 49 } |
| paddy@56 | 50 err = testContext.SaveClient(client) |
| paddy@56 | 51 if err != nil { |
| paddy@56 | 52 t.Fatal("Can't store client:", err) |
| paddy@56 | 53 } |
| paddy@56 | 54 err = testContext.AddEndpoint(client.ID, endpoint) |
| paddy@56 | 55 if err != nil { |
| paddy@56 | 56 t.Fatal("Can't store endpoint:", err) |
| paddy@56 | 57 } |
| paddy@52 | 58 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@52 | 59 if err != nil { |
| paddy@52 | 60 t.Fatal("Can't build request:", err) |
| paddy@52 | 61 } |
| paddy@56 | 62 for i := 0; i < 1<<4; i++ { |
| paddy@53 | 63 w := httptest.NewRecorder() |
| paddy@53 | 64 params := url.Values{} |
| paddy@53 | 65 // see OAuth 2.0 spec, section 4.1.1 |
| paddy@53 | 66 params.Set("response_type", "code") |
| paddy@56 | 67 params.Set("client_id", client.ID.String()) |
| paddy@53 | 68 if i&uriSet != 0 { |
| paddy@56 | 69 if i&uriExact != 0 { |
| paddy@56 | 70 params.Set("redirect_uri", endpoint.URI.String()) |
| paddy@56 | 71 } else { |
| paddy@56 | 72 params.Set("redirect_uri", endpoint.URI.String()+"/inexact") |
| paddy@56 | 73 } |
| paddy@53 | 74 } |
| paddy@53 | 75 if i&scopeSet != 0 { |
| paddy@53 | 76 params.Set("scope", "testscope") |
| paddy@53 | 77 } |
| paddy@53 | 78 if i&stateSet != 0 { |
| paddy@53 | 79 params.Set("state", "my super secure state string") |
| paddy@53 | 80 } |
| paddy@53 | 81 req.URL.RawQuery = params.Encode() |
| paddy@53 | 82 GetGrantHandler(w, req, testContext) |
| paddy@53 | 83 if w.Code != http.StatusOK { |
| paddy@53 | 84 t.Errorf("Expected status code to be %d, got %d for %s", http.StatusOK, w.Code, req.URL.String()) |
| paddy@53 | 85 } |
| paddy@53 | 86 if w.Body.String() != "Get auth grant" { |
| paddy@53 | 87 t.Errorf("Expected body to be `%s`, got `%s` for %s", "Get auth grant", w.Body.String(), req.URL.String()) |
| paddy@53 | 88 } |
| paddy@52 | 89 } |
| paddy@52 | 90 } |
| paddy@56 | 91 |
| paddy@56 | 92 func TestGetGrantCodeInvalidURI(t *testing.T) { |
| paddy@56 | 93 t.Parallel() |
| paddy@56 | 94 store := NewMemstore() |
| paddy@56 | 95 testContext := Context{ |
| paddy@56 | 96 template: template.Must(template.New(getGrantTemplateName).Parse("{{ .error }}")), |
| paddy@56 | 97 clients: store, |
| paddy@56 | 98 grants: store, |
| paddy@56 | 99 profiles: store, |
| paddy@56 | 100 tokens: store, |
| paddy@56 | 101 } |
| paddy@56 | 102 client := Client{ |
| paddy@56 | 103 ID: uuid.NewID(), |
| paddy@56 | 104 Secret: "super secret!", |
| paddy@56 | 105 OwnerID: uuid.NewID(), |
| paddy@56 | 106 Name: "My test client", |
| paddy@56 | 107 Type: "public", |
| paddy@56 | 108 } |
| paddy@56 | 109 uri, err := url.Parse("https://test.secondbit.org/redirect") |
| paddy@56 | 110 if err != nil { |
| paddy@56 | 111 t.Fatal("Can't parse URL:", err) |
| paddy@56 | 112 } |
| paddy@56 | 113 endpoint := Endpoint{ |
| paddy@56 | 114 ID: uuid.NewID(), |
| paddy@56 | 115 ClientID: client.ID, |
| paddy@56 | 116 URI: *uri, |
| paddy@56 | 117 Added: time.Now(), |
| paddy@56 | 118 } |
| paddy@56 | 119 err = testContext.SaveClient(client) |
| paddy@56 | 120 if err != nil { |
| paddy@56 | 121 t.Fatal("Can't store client:", err) |
| paddy@56 | 122 } |
| paddy@56 | 123 err = testContext.AddEndpoint(client.ID, endpoint) |
| paddy@56 | 124 if err != nil { |
| paddy@56 | 125 t.Fatal("Can't store endpoint:", err) |
| paddy@56 | 126 } |
| paddy@56 | 127 req, err := http.NewRequest("GET", "https://test.auth.secondbit.org/oauth2/grant", nil) |
| paddy@56 | 128 if err != nil { |
| paddy@56 | 129 t.Fatal("Can't build request:", err) |
| paddy@56 | 130 } |
| paddy@56 | 131 w := httptest.NewRecorder() |
| paddy@56 | 132 params := url.Values{} |
| paddy@56 | 133 params.Set("response_type", "code") |
| paddy@56 | 134 params.Set("client_id", client.ID.String()) |
| paddy@56 | 135 params.Set("redirect_uri", "https://test.secondbit.org/wrong") |
| paddy@56 | 136 req.URL.RawQuery = params.Encode() |
| paddy@56 | 137 GetGrantHandler(w, req, testContext) |
| paddy@56 | 138 if w.Code != http.StatusBadRequest { |
| paddy@56 | 139 t.Errorf("Expected status code to be %d, got %d", http.StatusBadRequest, w.Code) |
| paddy@56 | 140 } |
| paddy@56 | 141 if w.Body.String() != "The redirect_uri specified is not valid." { |
| paddy@56 | 142 t.Errorf(`Expected output to be "%s", got "%s" instead.`, "The redirect_uri specified is not valid.", w.Body.String()) |
| paddy@56 | 143 } |
| paddy@56 | 144 } |