Skip to content

Commit

Permalink
Merge pull request #8 from TJM/feat/expire
Browse files Browse the repository at this point in the history
Feat/expire
  • Loading branch information
Tommy McNeely authored Feb 4, 2021
2 parents 6590067 + f5e818d commit 21a4493
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 15 deletions.
12 changes: 6 additions & 6 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func ExampleConfigDex() (c *Config) {
c = DefaultConfig()
c.ClientID = "example-app"
c.ClientSecret = "ZXhhbXBsZS1hcHAtc2VjcmV0"
c.RedirectURL = "http://127.0.0.1:5555/callback"
c.IssuerURL = "http://127.0.0.1:5556/dex"
c.RedirectURL = "http://127.0.0.1:5555/callback"
return
}

Expand All @@ -90,31 +90,31 @@ func ExampleConfigGoogle() (c *Config) {
c = DefaultConfig()
c.ClientID = os.Getenv("GOOGLE_OAUTH2_CLIENT_ID")
c.ClientSecret = os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET")
c.RedirectURL = "http://127.0.0.1:5556/auth/google/callback"
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")
err = errors.New("ClientID is required")
return
}

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

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

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

Expand Down
104 changes: 104 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package oidcauth

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())
// })
// })

})
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ go 1.15

require (
github.com/coreos/go-oidc/v3 v3.0.0
github.com/franela/goblin v0.0.0-20210113153425-413781f5e6c8
github.com/gin-contrib/sessions v0.0.3
github.com/gin-gonic/gin v1.6.3
github.com/gorilla/sessions v1.2.1 // indirect
github.com/letsencrypt/boulder v0.0.0-20210130012035-2a8f0fe6ac7e
github.com/onsi/gomega v1.5.0
github.com/sirupsen/logrus v1.4.2
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/franela/goblin v0.0.0-20210113153425-413781f5e6c8 h1:QVPknD9yAYAmmmERIxdPFY6yf8d7xqoieNs/1C9ieCk=
github.com/franela/goblin v0.0.0-20210113153425-413781f5e6c8/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/getsentry/raven-go v0.0.0-20180121060056-563b81fc02b7/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/gin-contrib/sessions v0.0.3 h1:PoBXki+44XdJdlgDqDrY5nDVe3Wk7wDV/UCOuLP6fBI=
Expand Down Expand Up @@ -232,6 +234,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
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/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=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
Expand Down
35 changes: 26 additions & 9 deletions oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package oidcauth
import (
"errors"
"net/http"
"time"

log "github.com/sirupsen/logrus"

Expand All @@ -29,6 +30,9 @@ const (
// loginSessionKey is the session key to hold the "login" (username)
loginSessionKey string = "oidcauth:login"

// expirationSessionKey is the when the session is expired (in unixtime as an uint)
expirationSessionKey string = "oidcauth:sessionExpiration"

// AuthUserKey stores the authenticated user's login (username or email) in this context key
AuthUserKey string = "user"
)
Expand Down Expand Up @@ -85,21 +89,29 @@ func newOidcAuth(c *Config) (o *OidcAuth, err error) {
func (o *OidcAuth) AuthRequired() gin.HandlerFunc {
return func(c *gin.Context) {
session := sessions.Default(c)
token := session.Get(accessTokenSessionKey)
if token == nil {
e := session.Get(expirationSessionKey)
l := session.Get(loginSessionKey)
if l == nil || e == nil {
o.doAuthentication(c)
c.Abort()
return
}
// TODO: Valdate Token / Expiration? / Extension?
l := session.Get(loginSessionKey)
if l == nil {

login := l.(string)
exp := time.Unix(int64(e.(float64)), 0) // e (float64) -> int64 -> unixtime -> time.Time
now := time.Now()

if now.After(exp) {
log.WithFields(log.Fields{
"login": login,
"exp": exp,
"now": now,
}).Info("Session Expired")
o.doAuthentication(c)
c.Abort()
return
}
login := l.(string)
// The user credentials was found, set user's id to key AuthUserKey in this context, the user's id can be read later using
// The user credentials was found, set user's loginClaim to key AuthUserKey in this context, the user's id can be read later using
// c.MustGet(oidcauth.AuthUserKey).
c.Set(AuthUserKey, login)
c.Next()
Expand All @@ -125,7 +137,7 @@ func (o *OidcAuth) Login(c *gin.Context) {
func (o *OidcAuth) Logout(c *gin.Context) {
session := sessions.Default(c)
// These Sets will mark the session as "written" and clear the values (jic)
session.Set(accessTokenSessionKey, nil)
// session.Set(accessTokenSessionKey, nil)
session.Set(loginSessionKey, nil)
session.Clear()
session.Options(sessions.Options{Path: "/", MaxAge: -1}) // this sets the cookie as expired
Expand Down Expand Up @@ -183,7 +195,7 @@ func (o *OidcAuth) AuthCallback(c *gin.Context) {
session.AddFlash("Authentication Successful!")

// Process Results - just dump everything into the session for now (probably not a good idea)
session.Set(accessTokenSessionKey, oauth2Token.AccessToken)
// session.Set(accessTokenSessionKey, oauth2Token.AccessToken) // sessions doesn't like very long AccessToken
// session.Set("TokenType", oauth2Token.TokenType) // Not Needed?
// session.Set("Expiry", oauth2Token.Expiry) // sessions doesn't like time.Time
delete(claims, "nonce") // No longer useful
Expand All @@ -210,6 +222,11 @@ func (o *OidcAuth) AuthCallback(c *gin.Context) {
session.Set(loginSessionKey, login)
}

// Set expiration in session
if exp, ok := claims["exp"]; ok {
session.Set(expirationSessionKey, exp)
}

redirectURL := o.config.DefaultAuthenticatedURL
u := session.Get(previousURLSessionKey)
if u != nil {
Expand Down

0 comments on commit 21a4493

Please sign in to comment.