github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/goauth2/oauth/oauth_test.go (about) 1 // Copyright 2011 The goauth2 Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package oauth 6 7 import ( 8 "io" 9 "io/ioutil" 10 "net/http" 11 "net/http/httptest" 12 "net/url" 13 "os" 14 "path/filepath" 15 "runtime" 16 "testing" 17 "time" 18 ) 19 20 var requests = []struct { 21 path, query, auth string // request 22 contenttype, body string // response 23 }{ 24 { 25 path: "/token", 26 query: "grant_type=authorization_code&code=c0d3&client_id=cl13nt1d", 27 contenttype: "application/json", 28 body: ` 29 { 30 "access_token":"token1", 31 "refresh_token":"refreshtoken1", 32 "id_token":"idtoken1", 33 "expires_in":3600 34 } 35 `, 36 }, 37 {path: "/secure", auth: "Bearer token1", body: "first payload"}, 38 { 39 path: "/token", 40 query: "grant_type=refresh_token&refresh_token=refreshtoken1&client_id=cl13nt1d", 41 contenttype: "application/json", 42 body: ` 43 { 44 "access_token":"token2", 45 "refresh_token":"refreshtoken2", 46 "id_token":"idtoken2", 47 "expires_in":3600 48 } 49 `, 50 }, 51 {path: "/secure", auth: "Bearer token2", body: "second payload"}, 52 { 53 path: "/token", 54 query: "grant_type=refresh_token&refresh_token=refreshtoken2&client_id=cl13nt1d", 55 contenttype: "application/x-www-form-urlencoded", 56 body: "access_token=token3&refresh_token=refreshtoken3&id_token=idtoken3&expires_in=3600", 57 }, 58 {path: "/secure", auth: "Bearer token3", body: "third payload"}, 59 } 60 61 func TestOAuth(t *testing.T) { 62 // Set up test server. 63 n := 0 64 handler := func(w http.ResponseWriter, r *http.Request) { 65 if n >= len(requests) { 66 t.Errorf("too many requests: %d", n) 67 return 68 } 69 req := requests[n] 70 n++ 71 72 // Check request. 73 if g, w := r.URL.Path, req.path; g != w { 74 t.Errorf("request[%d] got path %s, want %s", n, g, w) 75 } 76 want, _ := url.ParseQuery(req.query) 77 for k := range want { 78 if g, w := r.FormValue(k), want.Get(k); g != w { 79 t.Errorf("query[%s] = %s, want %s", k, g, w) 80 } 81 } 82 if g, w := r.Header.Get("Authorization"), req.auth; w != "" && g != w { 83 t.Errorf("Authorization: %v, want %v", g, w) 84 } 85 86 // Send response. 87 w.Header().Set("Content-Type", req.contenttype) 88 io.WriteString(w, req.body) 89 } 90 server := httptest.NewServer(http.HandlerFunc(handler)) 91 defer server.Close() 92 93 config := &Config{ 94 ClientId: "cl13nt1d", 95 ClientSecret: "s3cr3t", 96 Scope: "https://example.net/scope", 97 AuthURL: server.URL + "/auth", 98 TokenURL: server.URL + "/token", 99 } 100 101 // TODO(adg): test AuthCodeURL 102 103 transport := &Transport{Config: config} 104 _, err := transport.Exchange("c0d3") 105 if err != nil { 106 t.Fatalf("Exchange: %v", err) 107 } 108 checkToken(t, transport.Token, "token1", "refreshtoken1", "idtoken1") 109 110 c := transport.Client() 111 resp, err := c.Get(server.URL + "/secure") 112 if err != nil { 113 t.Fatalf("Get: %v", err) 114 } 115 checkBody(t, resp, "first payload") 116 117 // test automatic refresh 118 transport.Expiry = time.Now().Add(-time.Hour) 119 resp, err = c.Get(server.URL + "/secure") 120 if err != nil { 121 t.Fatalf("Get: %v", err) 122 } 123 checkBody(t, resp, "second payload") 124 checkToken(t, transport.Token, "token2", "refreshtoken2", "idtoken2") 125 126 // refresh one more time, but get URL-encoded token instead of JSON 127 transport.Expiry = time.Now().Add(-time.Hour) 128 resp, err = c.Get(server.URL + "/secure") 129 if err != nil { 130 t.Fatalf("Get: %v", err) 131 } 132 checkBody(t, resp, "third payload") 133 checkToken(t, transport.Token, "token3", "refreshtoken3", "idtoken3") 134 } 135 136 func checkToken(t *testing.T, tok *Token, access, refresh, id string) { 137 if g, w := tok.AccessToken, access; g != w { 138 t.Errorf("AccessToken = %q, want %q", g, w) 139 } 140 if g, w := tok.RefreshToken, refresh; g != w { 141 t.Errorf("RefreshToken = %q, want %q", g, w) 142 } 143 if g, w := tok.Extra["id_token"], id; g != w { 144 t.Errorf("Extra['id_token'] = %q, want %q", g, w) 145 } 146 exp := tok.Expiry.Sub(time.Now()) 147 if (time.Hour-time.Second) > exp || exp > time.Hour { 148 t.Errorf("Expiry = %v, want ~1 hour", exp) 149 } 150 } 151 152 func checkBody(t *testing.T, r *http.Response, body string) { 153 b, err := ioutil.ReadAll(r.Body) 154 if err != nil { 155 t.Error("reading reponse body: %v, want %q", err, body) 156 } 157 if g, w := string(b), body; g != w { 158 t.Errorf("request body mismatch: got %q, want %q", g, w) 159 } 160 } 161 162 func TestCachePermissions(t *testing.T) { 163 if runtime.GOOS == "windows" { 164 // Windows doesn't support file mode bits. 165 return 166 } 167 168 td, err := ioutil.TempDir("", "oauth-test") 169 if err != nil { 170 t.Fatalf("ioutil.TempDir: %v", err) 171 } 172 defer os.RemoveAll(td) 173 tempFile := filepath.Join(td, "cache-file") 174 175 cf := CacheFile(tempFile) 176 if err := cf.PutToken(new(Token)); err != nil { 177 t.Fatalf("PutToken: %v", err) 178 } 179 fi, err := os.Stat(tempFile) 180 if err != nil { 181 t.Fatalf("os.Stat: %v", err) 182 } 183 if fi.Mode()&0077 != 0 { 184 t.Errorf("Created cache file has mode %#o, want non-accessible to group+other", fi.Mode()) 185 } 186 }