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

Side by Side Diff: server/auth/context.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/authtest/state.go ('k') | server/auth/context_test.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
11 "golang.org/x/net/context"
12
13 "github.com/luci/luci-go/common/errors"
14 "github.com/luci/luci-go/common/logging"
15
16 "github.com/luci/luci-go/server/auth/identity"
17 "github.com/luci/luci-go/server/router"
18 )
19
20 type authenticatorKey int
21
22 // SetAuthenticator injects copy of Authenticator (list of auth methods) into
23 // the context to use by default in LoginURL, LogoutURL and Authenticate.
24 // Usually installed into the context by some base middleware.
25 func SetAuthenticator(c context.Context, a Authenticator) context.Context {
26 return context.WithValue(c, authenticatorKey(0), append(Authenticator(ni l), a...))
27 }
28
29 // Use is a middleware that simply puts given Authenticator into the context.
30 func Use(a Authenticator) router.Middleware {
31 return func(c *router.Context, next router.Handler) {
32 c.Context = SetAuthenticator(c.Context, a)
33 next(c)
34 }
35 }
36
37 // getAuthenticator extracts instance of Authenticator (list of auth methods)
38 // from the context. Returns nil if no authenticator is set.
39 func getAuthenticator(c context.Context) Authenticator {
40 if a, ok := c.Value(authenticatorKey(0)).(Authenticator); ok {
41 return a
42 }
43 return nil
44 }
45
46 // LoginURL returns a URL that, when visited, prompts the user to sign in,
47 // then redirects the user to the URL specified by dest. It is wrapper around
48 // LoginURL method of Authenticator in the context.
49 func LoginURL(c context.Context, dest string) (string, error) {
50 return getAuthenticator(c).LoginURL(c, dest)
51 }
52
53 // LogoutURL returns a URL that, when visited, signs the user out,
54 // then redirects the user to the URL specified by dest. It is wrapper around
55 // LogoutURL method of Authenticator in the context.
56 func LogoutURL(c context.Context, dest string) (string, error) {
57 return getAuthenticator(c).LogoutURL(c, dest)
58 }
59
60 // Authenticate is a middleware that performs authentication (using Authenticato r
61 // in the context) and calls next handler.
62 func Authenticate(c *router.Context, next router.Handler) {
63 a := getAuthenticator(c.Context)
64 if a == nil {
65 replyError(c.Context, c.Writer, 500, "Authentication middleware is not configured")
66 return
67 }
68 ctx, err := a.Authenticate(c.Context, c.Request)
69 switch {
70 case errors.IsTransient(err):
71 replyError(c.Context, c.Writer, 500, fmt.Sprintf("Transient erro r during authentication - %s", err))
72 case err != nil:
73 replyError(c.Context, c.Writer, 401, fmt.Sprintf("Authentication error - %s", err))
74 default:
75 c.Context = ctx
76 next(c)
77 }
78 }
79
80 // Autologin is a middleware that redirects the user to login page if the user
81 // is not signed in yet or authentication methods do not recognize user
82 // credentials. Uses Authenticator instance in the context.
83 func Autologin(c *router.Context, next router.Handler) {
84 a := getAuthenticator(c.Context)
85 if a == nil {
86 replyError(c.Context, c.Writer, 500, "Authentication middleware is not configured")
87 return
88 }
89 ctx, err := a.Authenticate(c.Context, c.Request)
90
91 switch {
92 case errors.IsTransient(err):
93 replyError(c.Context, c.Writer, 500, fmt.Sprintf("Transient erro r during authentication - %s", err))
94
95 case err != nil:
96 replyError(c.Context, c.Writer, 401, fmt.Sprintf("Authentication error - %s", err))
97
98 case CurrentIdentity(ctx).Kind() == identity.Anonymous:
99 dest := c.Request.RequestURI
100 if dest == "" {
101 // Make r.URL relative.
102 destURL := *c.Request.URL
103 destURL.Host = ""
104 destURL.Scheme = ""
105 dest = destURL.String()
106 }
107 url, err := a.LoginURL(c.Context, dest)
108 if err != nil {
109 if errors.IsTransient(err) {
110 replyError(c.Context, c.Writer, 500, fmt.Sprintf ("Transient error during authentication - %s", err))
111 } else {
112 replyError(c.Context, c.Writer, 401, fmt.Sprintf ("Authentication error - %s", err))
113 }
114 return
115 }
116 http.Redirect(c.Writer, c.Request, url, 302)
117
118 default:
119 c.Context = ctx
120 next(c)
121 }
122 }
123
124 // replyError logs the error and writes it to ResponseWriter.
125 func replyError(c context.Context, rw http.ResponseWriter, code int, msg string) {
126 logging.Errorf(c, "HTTP %d: %s", code, msg)
127 http.Error(rw, msg, code)
128 }
OLDNEW
« no previous file with comments | « server/auth/authtest/state.go ('k') | server/auth/context_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698