Skip to main content
Sign in
Snippets Groups Projects
Commit 7d2ffed0 authored by Niall Sheridan's avatar Niall Sheridan
Browse files

WIP: Add Microsoft Azure oauth support

First pass at adding MS Azure OAuth2. This works (an access token is issued) but needs way mor work.

Cashier configuration:
oauth_client_id: This is the Application ID assigned when you register the app in Azure AD
oauth_client_secret: This is created when you create a new key in the application
provider_opts: Set "tenant" to an AD domain name (e.g. blabbedy.onmicrosoft.com)

TODO:
Users whitelist is untested currently.
Valid() is unimplemented.
Revoke() is unimplemented. Not checked if an API exists on the MS side.
Email() is unimplemented. Should be pretty simple using the graph API.
Needs tests.

Oh and last but by no means least MS issue INSANELY LONG (> 1800 chars!) access tokens which are too long for my shell. This represents a significant issue :/
parent de6d2c52
Branches azure_auth
No related tags found
No related merge requests found
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]
}
// 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",
}
}
...@@ -958,6 +958,12 @@ ...@@ -958,6 +958,12 @@
"revision": "ef147856a6ddbb60760db74283d2424e98c87bff", "revision": "ef147856a6ddbb60760db74283d2424e98c87bff",
"revisionTime": "2018-06-20T17:47:24Z" "revisionTime": "2018-06-20T17:47:24Z"
}, },
{
"checksumSHA1": "91mzAbqHQ6AAK65DzB4IkLOcvtk=",
"path": "golang.org/x/oauth2/microsoft",
"revision": "ef147856a6ddbb60760db74283d2424e98c87bff",
"revisionTime": "2018-06-20T17:47:24Z"
},
{ {
"checksumSHA1": "USMsFbKZrNd1b9oRFbjevPr6PmI=", "checksumSHA1": "USMsFbKZrNd1b9oRFbjevPr6PmI=",
"path": "golang.org/x/sys/unix", "path": "golang.org/x/sys/unix",
... ...
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment