| Index: server/auth/auth.go
|
| diff --git a/server/auth/auth.go b/server/auth/auth.go
|
| index 706d7fc9ea716b398442edbab85c25fe40501423..b64842e98017db1e29e6d61be6052d55c3a6510a 100644
|
| --- a/server/auth/auth.go
|
| +++ b/server/auth/auth.go
|
| @@ -36,11 +36,16 @@ var (
|
| ErrIPNotWhitelisted = errors.New("auth: IP is not whitelisted")
|
| )
|
|
|
| -// Method implements particular kind of low level authentication mechanism for
|
| -// incoming requests. It may also optionally implement UsersAPI (if the method
|
| -// support login and logout URLs). Use type sniffing to figure out.
|
| +// Method implements a particular kind of low-level authentication mechanism.
|
| +//
|
| +// It may also optionally implement UsersAPI (if the method support login and
|
| +// logout URLs).
|
| +//
|
| +// Methods are not usually used directly, but passed to Authenticator{...} that
|
| +// knows how to apply them.
|
| type Method interface {
|
| // Authenticate extracts user information from the incoming request.
|
| + //
|
| // It returns:
|
| // * (*User, nil) on success.
|
| // * (nil, nil) if the method is not applicable.
|
| @@ -88,22 +93,25 @@ type User struct {
|
| ClientID string
|
| }
|
|
|
| -// Authenticator perform authentication of incoming requests. It is stateless
|
| -// object that just describes what methods to try when authenticating current
|
| -// request. It is fine to create it on per-request basis.
|
| -type Authenticator []Method
|
| -
|
| -// Authenticate authenticates incoming requests and returns new context.Context
|
| -// with State stored into it. Returns error if credentials are provided, but
|
| -// invalid. If no credentials are provided (i.e. the request is anonymous),
|
| -// finishes successfully, but in that case State.Identity() will return
|
| -// AnonymousIdentity.
|
| -func (a Authenticator) Authenticate(c context.Context, r *http.Request) (context.Context, error) {
|
| - report := durationReporter(c, authenticateDuration)
|
| +// Authenticator perform authentication of incoming requests.
|
| +//
|
| +// It is stateless object configured with a list of methods to try when
|
| +// authenticating incoming requests. It implements Authenticate method that
|
| +// performs high-level authentication logic using the provided list of low-level
|
| +// auth methods.
|
| +//
|
| +// Usually used through Authenticate(...) middelware.
|
| +type Authenticator struct {
|
| + Methods []Method // a list of authentication methods to try
|
| +}
|
|
|
| - // Make it known to handlers what authentication methods are allowed.
|
| - // This is important for LoginURL and LogoutURL functions.
|
| - c = SetAuthenticator(c, a)
|
| +// Authenticate authenticates the requests and adds State into the context.
|
| +//
|
| +// Returns an error if credentials are provided, but invalid. If no credentials
|
| +// are provided (i.e. the request is anonymous), finishes successfully, but in
|
| +// that case State.Identity() returns AnonymousIdentity.
|
| +func (a *Authenticator) Authenticate(c context.Context, r *http.Request) (context.Context, error) {
|
| + report := durationReporter(c, authenticateDuration)
|
|
|
| // We will need working DB factory below to check IP whitelist.
|
| cfg := GetConfig(c)
|
| @@ -113,8 +121,8 @@ func (a Authenticator) Authenticate(c context.Context, r *http.Request) (context
|
| }
|
|
|
| // Pick first authentication method that applies.
|
| - var s state
|
| - for _, m := range a {
|
| + s := state{authenticator: a}
|
| + for _, m := range a.Methods {
|
| var err error
|
| s.user, err = m.Authenticate(c, r)
|
| if err != nil {
|
| @@ -237,10 +245,11 @@ func (a Authenticator) Authenticate(c context.Context, r *http.Request) (context
|
| return WithState(c, &s), nil
|
| }
|
|
|
| -// usersAPI returns implementation of UsersAPI by examining Methods. Returns nil
|
| -// if none of Methods implement UsersAPI.
|
| -func (a Authenticator) usersAPI() UsersAPI {
|
| - for _, m := range a {
|
| +// usersAPI returns implementation of UsersAPI by examining Methods.
|
| +//
|
| +// Returns nil if none of Methods implement UsersAPI.
|
| +func (a *Authenticator) usersAPI() UsersAPI {
|
| + for _, m := range a.Methods {
|
| if api, ok := m.(UsersAPI); ok {
|
| return api
|
| }
|
| @@ -250,16 +259,22 @@ func (a Authenticator) usersAPI() UsersAPI {
|
|
|
| // LoginURL returns a URL that, when visited, prompts the user to sign in,
|
| // then redirects the user to the URL specified by dest.
|
| -func (a Authenticator) LoginURL(c context.Context, dest string) (string, error) {
|
| +//
|
| +// Returns ErrNoUsersAPI if none of the authentication methods support login
|
| +// URLs.
|
| +func (a *Authenticator) LoginURL(c context.Context, dest string) (string, error) {
|
| if api := a.usersAPI(); api != nil {
|
| return api.LoginURL(c, dest)
|
| }
|
| return "", ErrNoUsersAPI
|
| }
|
|
|
| -// LogoutURL returns a URL that, when visited, signs the user out,
|
| -// then redirects the user to the URL specified by dest.
|
| -func (a Authenticator) LogoutURL(c context.Context, dest string) (string, error) {
|
| +// LogoutURL returns a URL that, when visited, signs the user out, then
|
| +// redirects the user to the URL specified by dest.
|
| +//
|
| +// Returns ErrNoUsersAPI if none of the authentication methods support login
|
| +// URLs.
|
| +func (a *Authenticator) LogoutURL(c context.Context, dest string) (string, error) {
|
| if api := a.usersAPI(); api != nil {
|
| return api.LogoutURL(c, dest)
|
| }
|
|
|