Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: server/auth/context_test.go

Issue 2830443003: auth: Refactor how authentication methods are passed to server/auth library. (Closed)
Patch Set: fix test Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « server/auth/context.go ('k') | server/auth/middleware.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package auth
6
7 import (
8 "fmt"
9 "net/http"
10 "net/http/httptest"
11 "net/url"
12 "testing"
13
14 "golang.org/x/net/context"
15
16 "github.com/luci/luci-go/common/errors"
17 "github.com/luci/luci-go/server/auth/identity"
18 "github.com/luci/luci-go/server/router"
19 . "github.com/smartystreets/goconvey/convey"
20 )
21
22 func TestContext(t *testing.T) {
23 t.Parallel()
24
25 Convey("Works", t, func() {
26 c := context.Background()
27
28 So(getAuthenticator(c), ShouldBeNil)
29 _, err := LoginURL(c, "dest")
30 So(err, ShouldEqual, ErrNoUsersAPI)
31 _, err = LogoutURL(c, "dest")
32 So(err, ShouldEqual, ErrNoUsersAPI)
33
34 // Authenticator without UsersAPI.
35 c = SetAuthenticator(c, Authenticator{noUserAPI{}})
36
37 So(getAuthenticator(c), ShouldNotBeNil)
38 _, err = LoginURL(c, "dest")
39 So(err, ShouldEqual, ErrNoUsersAPI)
40 _, err = LogoutURL(c, "dest")
41 So(err, ShouldEqual, ErrNoUsersAPI)
42
43 // Authenticator with UsersAPI.
44 c = SetAuthenticator(c, Authenticator{fakeMethod{}})
45
46 So(getAuthenticator(c), ShouldNotBeNil)
47 dest, err := LoginURL(c, "dest")
48 So(err, ShouldBeNil)
49 So(dest, ShouldEqual, "http://login_url?r=dest")
50 dest, err = LogoutURL(c, "dest")
51 So(err, ShouldBeNil)
52 So(dest, ShouldEqual, "http://logout_url?r=dest")
53 })
54
55 }
56
57 func TestContextAuthenticate(t *testing.T) {
58 t.Parallel()
59
60 call := func(c context.Context, m router.MiddlewareChain, h router.Handl er) *httptest.ResponseRecorder {
61 req, err := http.NewRequest("GET", "http://example.com/foo", nil )
62 So(err, ShouldBeNil)
63 w := httptest.NewRecorder()
64 router.RunMiddleware(&router.Context{
65 Context: c,
66 Writer: w,
67 Request: req,
68 }, m, h)
69 return w
70 }
71
72 handler := func(c *router.Context) {
73 fmt.Fprintf(c.Writer, "%s", CurrentIdentity(c.Context))
74 }
75
76 Convey("Not configured", t, func() {
77 rr := call(context.Background(), router.NewMiddlewareChain(Authe nticate), handler)
78 So(rr.Code, ShouldEqual, 500)
79 So(rr.Body.String(), ShouldEqual, "Authentication middleware is not configured\n")
80 })
81
82 Convey("Transient error", t, func() {
83 c := prepareCtx(fakeMethod{authError: errors.WrapTransient(error s.New("boo"))})
84 rr := call(c, router.NewMiddlewareChain(Authenticate), handler)
85 So(rr.Code, ShouldEqual, 500)
86 So(rr.Body.String(), ShouldEqual, "Transient error during authen tication - boo\n")
87 })
88
89 Convey("Fatal error", t, func() {
90 c := prepareCtx(fakeMethod{authError: errors.New("boo")})
91 rr := call(c, router.NewMiddlewareChain(Authenticate), handler)
92 So(rr.Code, ShouldEqual, 401)
93 So(rr.Body.String(), ShouldEqual, "Authentication error - boo\n" )
94 })
95
96 Convey("Works", t, func() {
97 c := prepareCtx(fakeMethod{userID: "user:abc@example.com"})
98 rr := call(c, router.NewMiddlewareChain(Authenticate), handler)
99 So(rr.Code, ShouldEqual, 200)
100 So(rr.Body.String(), ShouldEqual, "user:abc@example.com")
101 })
102
103 Convey("Anonymous works", t, func() {
104 c := prepareCtx(fakeMethod{anon: true})
105 rr := call(c, router.NewMiddlewareChain(Authenticate), handler)
106 So(rr.Code, ShouldEqual, 200)
107 So(rr.Body.String(), ShouldEqual, "anonymous:anonymous")
108 })
109
110 Convey("Broken ID is rejected", t, func() {
111 c := prepareCtx(fakeMethod{userID: "???"})
112 rr := call(c, router.NewMiddlewareChain(Authenticate), handler)
113 So(rr.Code, ShouldEqual, 401)
114 So(rr.Body.String(), ShouldEqual, "Authentication error - auth: bad identity string \"???\"\n")
115 })
116 }
117
118 func TestAutologin(t *testing.T) {
119 t.Parallel()
120
121 call := func(c context.Context, m router.MiddlewareChain, h router.Handl er) *httptest.ResponseRecorder {
122 req, err := http.NewRequest("GET", "http://example.com/foo", nil )
123 So(err, ShouldBeNil)
124 w := httptest.NewRecorder()
125 router.RunMiddleware(&router.Context{
126 Context: c,
127 Writer: w,
128 Request: req,
129 }, m, h)
130 return w
131 }
132
133 handler := func(c *router.Context) {
134 fmt.Fprintf(c.Writer, "%s", CurrentIdentity(c.Context))
135 }
136
137 Convey("Not configured", t, func() {
138 rr := call(context.Background(), router.NewMiddlewareChain(Autol ogin), handler)
139 So(rr.Code, ShouldEqual, 500)
140 So(rr.Body.String(), ShouldEqual, "Authentication middleware is not configured\n")
141 })
142
143 Convey("Transient error", t, func() {
144 c := prepareCtx(fakeMethod{authError: errors.WrapTransient(error s.New("boo"))})
145 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
146 So(rr.Code, ShouldEqual, 500)
147 So(rr.Body.String(), ShouldEqual, "Transient error during authen tication - boo\n")
148 })
149
150 Convey("Fatal error", t, func() {
151 c := prepareCtx(fakeMethod{authError: errors.New("boo")})
152 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
153 So(rr.Code, ShouldEqual, 401)
154 })
155
156 Convey("Anonymous is redirected to login if has UsersAPI", t, func() {
157 c := prepareCtx(fakeMethod{anon: true})
158 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
159 So(rr.Code, ShouldEqual, 302)
160 So(rr.Header().Get("Location"), ShouldEqual, "http://login_url?r =%2Ffoo")
161 })
162
163 Convey("Anonymous is rejected if no UsersAPI", t, func() {
164 c := prepareCtx(noUserAPI{})
165 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
166 So(rr.Code, ShouldEqual, 401)
167 So(rr.Body.String(), ShouldEqual, "Authentication error - auth: methods do not support login or logout URL\n")
168 })
169
170 Convey("Handles transient error in LoginURL", t, func() {
171 c := prepareCtx(fakeMethod{anon: true, loginURLError: errors.Wra pTransient(errors.New("boo"))})
172 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
173 So(rr.Code, ShouldEqual, 500)
174 So(rr.Body.String(), ShouldEqual, "Transient error during authen tication - boo\n")
175 })
176
177 Convey("Passes authenticated user through", t, func() {
178 c := prepareCtx(fakeMethod{userID: "user:abc@example.com"})
179 rr := call(c, router.NewMiddlewareChain(Autologin), handler)
180 So(rr.Code, ShouldEqual, 200)
181 So(rr.Body.String(), ShouldEqual, "user:abc@example.com")
182 })
183 }
184
185 func prepareCtx(m ...Method) context.Context {
186 c := injectTestDB(context.Background(), &fakeDB{})
187 return SetAuthenticator(c, Authenticator(m))
188 }
189
190 type noUserAPI struct{}
191
192 func (noUserAPI) Authenticate(context.Context, *http.Request) (*User, error) {
193 return nil, nil
194 }
195
196 type fakeMethod struct {
197 authError error
198 loginURLError error
199 userID identity.Identity
200 anon bool
201 }
202
203 func (m fakeMethod) Authenticate(context.Context, *http.Request) (*User, error) {
204 if m.anon {
205 return nil, nil
206 }
207 if m.authError != nil {
208 return nil, m.authError
209 }
210 return &User{Identity: m.userID}, nil
211 }
212
213 func (m fakeMethod) LoginURL(c context.Context, dest string) (string, error) {
214 if m.loginURLError != nil {
215 return "", m.loginURLError
216 }
217 v := url.Values{}
218 v.Set("r", dest)
219 return "http://login_url?" + v.Encode(), nil
220 }
221
222 func (m fakeMethod) LogoutURL(c context.Context, dest string) (string, error) {
223 v := url.Values{}
224 v.Set("r", dest)
225 return "http://logout_url?" + v.Encode(), nil
226 }
OLDNEW
« no previous file with comments | « server/auth/context.go ('k') | server/auth/middleware.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698