Skip to content

Commit

Permalink
fix routing and auth handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Aschwanden committed Sep 16, 2023
1 parent 76c06bf commit 4d63917
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 9 deletions.
11 changes: 7 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@ go 1.19
require (
github.com/99designs/gqlgen v0.17.24
github.com/TJM/gin-gonic-oidcauth v0.3.0
github.com/franela/goblin v0.0.0-20210113153425-413781f5e6c8
github.com/gin-contrib/sessions v0.0.5
github.com/gin-contrib/static v0.0.1
github.com/gin-gonic/gin v1.8.2
github.com/google/uuid v1.3.0
github.com/onsi/gomega v1.5.0
github.com/spf13/cobra v1.6.1
github.com/spf13/viper v1.15.0
github.com/vektah/gqlparser/v2 v2.5.1
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157
)

require (
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/coreos/go-oidc/v3 v3.5.0 // indirect
github.com/coreos/go-oidc/v3 v3.5.0
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand All @@ -40,7 +43,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/letsencrypt/boulder v0.0.0-20230130081212-d2d9078213db // indirect
github.com/letsencrypt/boulder v0.0.0-20230130081212-d2d9078213db
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
Expand Down Expand Up @@ -69,8 +72,8 @@ require (
go.opentelemetry.io/otel/trace v1.13.0
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.3.0 // indirect
golang.org/x/net v0.7.0
golang.org/x/oauth2 v0.3.0
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/tools v0.2.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down Expand Up @@ -326,6 +327,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
Expand Down Expand Up @@ -478,6 +480,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157 h1:fiNkyhJPUvxbRPbCqY/D9qdjmPzfHcpK3P4bM4gioSY=
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
Expand Down Expand Up @@ -817,13 +821,15 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
154 changes: 154 additions & 0 deletions pkg/auth/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package auth

import (
"errors"
"log"
"os"

"github.com/coreos/go-oidc/v3/oidc"
)

// Config represents available options for oidcauth.
type Config struct {
// ClientID is the OAUTH2 Client ID
// Default value is: (read from OS ENV: OAUTH2_CLIENT_ID)
ClientID string

// ClientSecret is the OAUTH2 Client Secret
// Default value is: (read from OS ENV: OAUTH2_CLIENT_SECRET)
ClientSecret string

// IssuerURL is the root URL to theIdentity Provider
// Default value is: (read from OS ENV: OIDC_ISSUER_URL)
IssuerURL string

// RedirectURL is the path that the Identity Provider will redirect clients to
// Default value is: (read from OS ENV: OIDC_REDIRECT_URL)
RedirectURL string

// Scopes is a list of OIDC Scopes to request.
// Default value is: []string{oidc.ScopeOpenID, "profile", "email"}
Scopes []string

// LoginClaim is the OIDC claim to map to the user's login (username)
// Default value is: "email"
LoginClaim string

// SessionClaims is the list of OIDC claims to add to the user's session (in addition to LoginClaim)
// Example []string{"email", "givenName", "name"}
// NOTE: This can be set to ["*"] to load *all* claims. (nonce will be excluded)
// Default value is: ["*"]
SessionClaims []string

// SessionPrefix is an optional prefix string to prefix to the claims (i.e. google: or corp:) to prevent
// clashes in the session namespace
// Default value is: ""
SessionPrefix string

// DefaultAuthenticatedURL is the URL to redirect a user to after successful authentication. By default, we will
// try to determine where they were when they requested to login and send them back there.
// Default value is: "/"
DefaultAuthenticatedURL string

// LogoutURL is the URL to redirect a user to after logging out.
// NOTE: If you require / to be authenticated, setting this to / will start the login process immediately, which may not be desirable.
// Default value is: "/"
LogoutURL string
}

// DefaultConfig will create a new config object with defaults
// NOTE: This matches the examples on https://github.com/coreos/go-oidc/tree/v3/example
func DefaultConfig() (c *Config) {
c = &Config{
ClientID: os.Getenv("OIDC_CLIENT_ID"),
ClientSecret: os.Getenv("OIDC_CLIENT_SECRET"),
IssuerURL: os.Getenv("OIDC_ISSUER_URL"),
RedirectURL: os.Getenv("OIDC_REDIRECT_URL"),
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
LoginClaim: "email",
SessionClaims: []string{"*"},
DefaultAuthenticatedURL: "/",
LogoutURL: "/",
}
return
}

// ExampleConfigDex will return the config for a default DEX IdP example-app
// DEX: https://github.com/dexidp/dex
func ExampleConfigDex() (c *Config) {
c = DefaultConfig()
c.ClientID = "example-app"
c.ClientSecret = "ZXhhbXBsZS1hcHAtc2VjcmV0"
c.IssuerURL = "http://127.0.0.1:5556/dex"
c.RedirectURL = "http://127.0.0.1:5555/callback"
return
}

// ExampleConfigGoogle will return the config for the Google Accounts IdP like the go-oidc examples
// go-oidc google example: https://github.com/coreos/go-oidc/tree/v3/example
func ExampleConfigGoogle() (c *Config) {
c = DefaultConfig()
c.ClientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
c.ClientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
c.IssuerURL = "https://accounts.google.com"
c.RedirectURL = "http://127.0.0.1:5556/auth/google/callback"
return
}

// Validate will validate the Config
func (c Config) Validate() (err error) {

if c.ClientID == "" {
err = errors.New("ClientID is required")
return
}

if c.ClientSecret == "" {
err = errors.New("ClientSecret is required")
return
}

if c.IssuerURL == "" { // TODO: Validate that its a properly formed URL
err = errors.New("IssuerURL is required")
return
}

if c.RedirectURL == "" { // TODO: Validate that its a properly formed URL
err = errors.New("RedirectURL is required")
return
}

return
}

// GetOidcAuth returns the configured OIDC authentication controller
func GetOidcAuth(c *Config) (o *OidcAuth, err error) {
return c.GetOidcAuth()
}

// GetOidcAuth returns the configured OIDC authentication controller
func (c *Config) GetOidcAuth() (o *OidcAuth, err error) {
err = c.Validate()
if err != nil {
log.Fatal(err)
}
return newOidcAuth(c)
}

// The methods below can be used to return the middleware, but currently do
// not handle the routes. They are of limited use, for now.
//
// // Default returns the location middleware with default configuration.
// func Default() gin.HandlerFunc {
// config := DefaultConfig()
// return New(config)
// }

// // New returns the location middleware with user-defined custom configuration.
// func New(c *Config) gin.HandlerFunc {
// auth, err := c.GetOidcAuth()
// if err != nil {
// log.Fatal("[oidcauth] Error getting auth handler")
// }
// return auth.AuthRequired()
// }
104 changes: 104 additions & 0 deletions pkg/auth/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package auth

import (
"os"
"testing"

goblin "github.com/franela/goblin"
. "github.com/onsi/gomega"
)

func TestConfig(t *testing.T) {
g := goblin.Goblin(t)

//special hook for gomega
RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

g.Describe("TestConfig", func() {

g.Describe("DefaultConfig", func() {
os.Setenv("OIDC_CLIENT_ID", "client-id")
os.Setenv("OIDC_CLIENT_SECRET", "client-secret")
os.Setenv("OIDC_ISSUER_URL", "issuer-url")
os.Setenv("OIDC_REDIRECT_URL", "redirect-url")
c := DefaultConfig()

g.It("should retrieve values from env", func() {
Expect(c.ClientID).To(BeEquivalentTo("client-id"))
Expect(c.ClientSecret).To(BeEquivalentTo("client-secret"))
Expect(c.IssuerURL).To(BeEquivalentTo("issuer-url"))
Expect(c.RedirectURL).To(BeEquivalentTo("redirect-url"))
})
})

g.Describe("ExampleConfigDex", func() {
c := ExampleConfigDex()

g.It("should match dex example-app config", func() {
Expect(c.ClientID).To(BeEquivalentTo("example-app"))
Expect(c.ClientSecret).To(BeEquivalentTo("ZXhhbXBsZS1hcHAtc2VjcmV0"))
Expect(c.IssuerURL).To(BeEquivalentTo("http://127.0.0.1:5556/dex"))
Expect(c.RedirectURL).To(BeEquivalentTo("http://127.0.0.1:5555/callback"))
})
})

g.Describe("ExampleConfigGoogle", func() {
os.Setenv("GOOGLE_OAUTH2_CLIENT_ID", "client-id")
os.Setenv("GOOGLE_OAUTH2_CLIENT_SECRET", "client-secret")
c := ExampleConfigGoogle()

g.It("should match example google config", func() {
Expect(c.ClientID).To(BeEquivalentTo("client-id"))
Expect(c.ClientSecret).To(BeEquivalentTo("client-secret"))
Expect(c.IssuerURL).To(BeEquivalentTo("https://accounts.google.com"))
Expect(c.RedirectURL).To(BeEquivalentTo("http://127.0.0.1:5556/auth/google/callback"))
})
})

g.Describe("Validate", func() {
c := ExampleConfigDex()
c.ClientID = ""
g.It("should error on empty ClientID", func() {
Expect(c.Validate()).ToNot(BeNil())
})

c = ExampleConfigDex()
c.ClientSecret = ""
g.It("should error on empty ClientSecret", func() {
Expect(c.Validate()).ToNot(BeNil())
})

c = ExampleConfigDex()
c.IssuerURL = ""
g.It("should error on empty IssuerURL", func() {
Expect(c.Validate()).ToNot(BeNil())
})

c = ExampleConfigDex()
c.RedirectURL = ""
g.It("should error on empty RedirectURL", func() {
Expect(c.Validate()).ToNot(BeNil())
})
})

// g.Describe("GetOidcAuth", func() {
// auth, err := GetOidcAuth(ExampleConfigDex())

// g.It("should work", func() {
// Expect(auth).NotTo(BeNil())
// Expect(err).To(BeNil())
// })
// })

// g.Describe("c.GetOidcAuth", func() {
// c := ExampleConfigDex()
// auth, err := c.GetOidcAuth()

// g.It("should work", func() {
// Expect(auth).NotTo(BeNil())
// Expect(err).To(BeNil())
// })
// })

})
}
Loading

0 comments on commit 4d63917

Please sign in to comment.