diff --git a/server/auth/microsoft/microsoft.go b/server/auth/microsoft/microsoft.go new file mode 100644 index 0000000000000000000000000000000000000000..fa2028e24e63aade371a3ca5f8e2064dd6a0a5b4 --- /dev/null +++ b/server/auth/microsoft/microsoft.go @@ -0,0 +1,110 @@ +package microsoft + +import ( + "errors" + "net/http" + "strings" + + "github.com/nsheridan/cashier/server/auth" + "github.com/nsheridan/cashier/server/config" + "github.com/nsheridan/cashier/server/metrics" + + "golang.org/x/oauth2" + "golang.org/x/oauth2/microsoft" +) + +//XXX: This is a work-in-progress! DO NOT USE! +// MS issue INSANELY LONG access tokens that exceed shell line length + +const ( + //FIXME: + // revokeURL = "" + name = "microsoft" +) + +// Config is an implementation of `auth.Provider` for authenticating using a +// Microsoft Azure AD account. +type Config struct { + config *oauth2.Config + tenant string + whitelist map[string]bool +} + +var _ auth.Provider = (*Config)(nil) + +// New creates a new Google provider from a configuration. +func New(c *config.Auth) (*Config, error) { + uw := make(map[string]bool) + for _, u := range c.UsersWhitelist { + uw[u] = true + } + if c.ProviderOpts["tenant"] == "" && len(uw) == 0 { + return nil, errors.New("either AD tenant or users whitelist must be specified") + } + + return &Config{ + config: &oauth2.Config{ + ClientID: c.OauthClientID, + ClientSecret: c.OauthClientSecret, + RedirectURL: c.OauthCallbackURL, + Endpoint: microsoft.AzureADEndpoint(c.ProviderOpts["tenant"]), + Scopes: []string{"user.Read"}, + }, + whitelist: uw, + }, nil +} + +// A new oauth2 http client. +func (c *Config) newClient(token *oauth2.Token) *http.Client { + return c.config.Client(oauth2.NoContext, token) +} + +// Name returns the name of the provider. +func (c *Config) Name() string { + return name +} + +// Valid validates the oauth token. +func (c *Config) Valid(token *oauth2.Token) bool { + // FIXME: Validate harder + if !token.Valid() { + return false + } + metrics.M.AuthValid.WithLabelValues("microsoft").Inc() + return true +} + +// Revoke disables the access token. +func (c *Config) Revoke(token *oauth2.Token) error { + //FIXME + return nil +} + +// StartSession retrieves an authentication endpoint from Google. +func (c *Config) StartSession(state string) *auth.Session { + return &auth.Session{ + AuthURL: c.config.AuthCodeURL(state), + } +} + +// Exchange authorizes the session and returns an access token. +func (c *Config) Exchange(code string) (*oauth2.Token, error) { + t, err := c.config.Exchange(oauth2.NoContext, code) + if err == nil { + metrics.M.AuthExchange.WithLabelValues("google").Inc() + } + return t, err +} + +// Email retrieves the email address of the user. +func (c *Config) Email(token *oauth2.Token) string { + // TODO: Given an access token, request the current user profile from + // `https://graph.microsoft.com/v1.0/me`. Parse out whatever passes for an + // email address from the response. + return "" +} + +// Username retrieves the username portion of the user's email address. +func (c *Config) Username(token *oauth2.Token) string { + return strings.Split(c.Email(token), "@")[0] +} diff --git a/vendor/golang.org/x/oauth2/microsoft/microsoft.go b/vendor/golang.org/x/oauth2/microsoft/microsoft.go new file mode 100644 index 0000000000000000000000000000000000000000..3ffbc57a6906ca8e8fa9d49960e97e45efd5df54 --- /dev/null +++ b/vendor/golang.org/x/oauth2/microsoft/microsoft.go @@ -0,0 +1,31 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package microsoft provides constants for using OAuth2 to access Windows Live ID. +package microsoft // import "golang.org/x/oauth2/microsoft" + +import ( + "golang.org/x/oauth2" +) + +// LiveConnectEndpoint is Windows's Live ID OAuth 2.0 endpoint. +var LiveConnectEndpoint = oauth2.Endpoint{ + AuthURL: "https://login.live.com/oauth20_authorize.srf", + TokenURL: "https://login.live.com/oauth20_token.srf", +} + +// AzureADEndpoint returns a new oauth2.Endpoint for the given tenant at Azure Active Directory. +// If tenant is empty, it uses the tenant called `common`. +// +// For more information see: +// https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints +func AzureADEndpoint(tenant string) oauth2.Endpoint { + if tenant == "" { + tenant = "common" + } + return oauth2.Endpoint{ + AuthURL: "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/authorize", + TokenURL: "https://login.microsoftonline.com/" + tenant + "/oauth2/v2.0/token", + } +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 01e666ceb8604eb201d1038671346e8c24381aad..0f7a2bab33fc88e5559b8bc7b3072e81f6412154 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -958,6 +958,12 @@ "revision": "ef147856a6ddbb60760db74283d2424e98c87bff", "revisionTime": "2018-06-20T17:47:24Z" }, + { + "checksumSHA1": "91mzAbqHQ6AAK65DzB4IkLOcvtk=", + "path": "golang.org/x/oauth2/microsoft", + "revision": "ef147856a6ddbb60760db74283d2424e98c87bff", + "revisionTime": "2018-06-20T17:47:24Z" + }, { "checksumSHA1": "USMsFbKZrNd1b9oRFbjevPr6PmI=", "path": "golang.org/x/sys/unix",