Skip to content

Commit

Permalink
Use strategy pattern-like switch to select vendor-specific handler
Browse files Browse the repository at this point in the history
  • Loading branch information
eikehartmann committed Feb 9, 2020
1 parent 34bbcff commit 6ba3136
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 37 deletions.
4 changes: 3 additions & 1 deletion handlers/adfs/adfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"strings"
)

type Handler struct{}

type adfsTokenRes struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
Expand All @@ -26,7 +28,7 @@ var (
)

// More info: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-scenarios-for-developers#supported-scenarios
func GetUserInfoFromADFS(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
code := r.URL.Query().Get("code")
log.Debugf("code: %s", code)

Expand Down
8 changes: 6 additions & 2 deletions handlers/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@ import (
"strings"
)

type Handler struct {
PrepareTokensAndClient func(*http.Request, *structs.PTokens, bool) (error, *http.Client, *oauth2.Token)
}

var (
log = cfg.Cfg.Logger
)

// github
// https://developer.github.com/apps/building-integrations/setting-up-and-registering-oauth-apps/about-authorization-options-for-oauth-apps/
func GetUserInfoFromGitHub(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, client, ptoken := common.PrepareTokensAndClient(r, ptokens, true)
func (me Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, client, ptoken := me.PrepareTokensAndClient(r, ptokens, true)
if err != nil {
// http.Error(w, err.Error(), http.StatusBadRequest)
return err
Expand Down
12 changes: 7 additions & 5 deletions handlers/github/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ package github

import (
"encoding/json"
mockhttp "github.com/karupanerura/go-mock-http-response"
"github.com/stretchr/testify/assert"
"github.com/vouch/vouch-proxy/pkg/cfg"
"github.com/vouch/vouch-proxy/pkg/domains"
"github.com/vouch/vouch-proxy/pkg/structs"
"golang.org/x/oauth2"
"net/http"
"regexp"

mockhttp "github.com/karupanerura/go-mock-http-response"
"github.com/stretchr/testify/assert"
"testing"
)

Expand Down Expand Up @@ -156,7 +155,7 @@ func TestGetOrgMembershipStateFromGitHubNoOrgAccess(t *testing.T) {
assertUrlCalled(t, expectedOrgPublicMembershipUrl)
}

func TestGetUserInfoFromGitHub(t *testing.T) {
func TestGetUserInfo(t *testing.T) {
setUp()

userInfoContent, _ := json.Marshal(structs.GitHubUser{
Expand All @@ -178,7 +177,10 @@ func TestGetUserInfoFromGitHub(t *testing.T) {
mockResponse(regexMatcher(".*teams.*"), http.StatusOK, map[string]string{}, []byte("{\"state\": \"active\"}"))
mockResponse(regexMatcher(".*members.*"), http.StatusNoContent, map[string]string{}, []byte(""))

err := GetUserInfoFromGitHub(client, user, &structs.CustomClaims{}, token)
handler := Handler{PrepareTokensAndClient: func(_ *http.Request, _ *structs.PTokens, _ bool) (error, *http.Client, *oauth2.Token) {
return nil, client, token
}}
err := handler.GetUserInfo(nil, user, &structs.CustomClaims{}, &structs.PTokens{})

assert.Nil(t, err)
assert.Equal(t, "myusername", user.Username)
Expand Down
4 changes: 3 additions & 1 deletion handlers/google/google.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"net/http"
)

type Handler struct{}

var (
log = cfg.Cfg.Logger
)

func GetUserInfoFromGoogle(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, client, _ := common.PrepareTokensAndClient(r, ptokens, true)
if err != nil {
return err
Expand Down
49 changes: 26 additions & 23 deletions handlers/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers
import (
"fmt"
"github.com/vouch/vouch-proxy/handlers/adfs"
"github.com/vouch/vouch-proxy/handlers/common"
"github.com/vouch/vouch-proxy/handlers/github"
"github.com/vouch/vouch-proxy/handlers/google"
"github.com/vouch/vouch-proxy/handlers/homeassistant"
Expand Down Expand Up @@ -43,6 +44,10 @@ type AuthError struct {
JWT string
}

type Handler interface {
GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) error
}

const (
base64Bytes = 32
)
Expand Down Expand Up @@ -527,32 +532,30 @@ func CallbackHandler(w http.ResponseWriter, r *http.Request) {
renderIndex(w, "/auth "+tokenstring)
}

// TODO: put all getUserInfo logic into its own pkg

func getUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) error {
return getHandler().GetUserInfo(r, user, customClaims, ptokens)
}

// indieauth sends the "me" setting in json back to the callback, so just pluck it from the callback
if cfg.GenOAuth.Provider == cfg.Providers.IndieAuth {
return indieauth.GetUserInfoFromIndieAuth(r, user, customClaims, ptokens)
} else if cfg.GenOAuth.Provider == cfg.Providers.ADFS {
return adfs.GetUserInfoFromADFS(r, user, customClaims, ptokens)
}
if cfg.GenOAuth.Provider == cfg.Providers.HomeAssistant {
return homeassistant.GetUserInfoFromHomeAssistant(r, user, customClaims, ptokens)
}
if cfg.GenOAuth.Provider == cfg.Providers.OpenStax {
return openstax.GetUserInfoFromOpenStax(r, user, customClaims, ptokens)
}

if cfg.GenOAuth.Provider == cfg.Providers.Google {
return google.GetUserInfoFromGoogle(r, user, customClaims, ptokens)
} else if cfg.GenOAuth.Provider == cfg.Providers.GitHub {
return github.GetUserInfoFromGitHub(r, user, customClaims, ptokens)
} else if cfg.GenOAuth.Provider == cfg.Providers.OIDC {
return openid.GetUserInfoFromOpenID(r, user, customClaims, ptokens)
func getHandler() Handler {
switch cfg.GenOAuth.Provider {
case cfg.Providers.IndieAuth:
return indieauth.Handler{}
case cfg.Providers.ADFS:
return adfs.Handler{}
case cfg.Providers.HomeAssistant:
return homeassistant.Handler{}
case cfg.Providers.OpenStax:
return openstax.Handler{}
case cfg.Providers.Google:
return google.Handler{}
case cfg.Providers.GitHub:
return github.Handler{common.PrepareTokensAndClient}
case cfg.Providers.OIDC:
return openid.Handler{}
default:
log.Error("we don't know how to look up the user info")
return nil
}
log.Error("we don't know how to look up the user info")
return nil
}

// the standard error
Expand Down
4 changes: 3 additions & 1 deletion handlers/homeassistant/homeassistant.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"net/http"
)

type Handler struct{}

// More info: https://developers.home-assistant.io/docs/en/auth_api.html
func GetUserInfoFromHomeAssistant(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, _, providerToken := common.PrepareTokensAndClient(r, ptokens, false)
if err != nil {
return err
Expand Down
6 changes: 4 additions & 2 deletions handlers/indieauth/indieauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import (
"net/http"
)

type Handler struct{}

var (
log = cfg.Cfg.Logger
)

func GetUserInfoFromIndieAuth(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {

func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
// indieauth sends the "me" setting in json back to the callback, so just pluck it from the callback
code := r.URL.Query().Get("code")
log.Errorf("ptoken.AccessToken: %s", code)
var b bytes.Buffer
Expand Down
4 changes: 3 additions & 1 deletion handlers/openid/openid.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"net/http"
)

type Handler struct{}

var (
log = cfg.Cfg.Logger
)

func GetUserInfoFromOpenID(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, client, _ := common.PrepareTokensAndClient(r, ptokens, true)
if err != nil {
return err
Expand Down
4 changes: 3 additions & 1 deletion handlers/openstax/openstax.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import (
"net/http"
)

type Handler struct{}

var (
log = cfg.Cfg.Logger
)

func GetUserInfoFromOpenStax(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
func (Handler) GetUserInfo(r *http.Request, user *structs.User, customClaims *structs.CustomClaims, ptokens *structs.PTokens) (rerr error) {
err, client, _ := common.PrepareTokensAndClient(r, ptokens, false)
if err != nil {
return err
Expand Down

0 comments on commit 6ba3136

Please sign in to comment.