diff --git a/README.md b/README.md
index 67c7aa3..f0ce0e4 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,32 @@ Import it in your code:
import oidcauth "github.com/TJM/gin-gonic-oidcauth"
```
-## Example
+Use it: (see complete [examples](example))
+
+```go
+ // NOTE: oidcauth *requires* sessions *before* oidcauth
+ // SEE Examples to see how.
+
+ // Authentication Config
+ auth, err := oidcauth.GetOidcAuth(oidcauth.DefaultConfig())
+ if err != nil {
+ panic("auth setup failed")
+ }
+ router.GET("/login", auth.Login) // Unnecessary, as requesting a "AuthRequired" resource will initiate login, but potentially convenient
+ router.GET("/callback", auth.AuthCallback)
+ router.GET("/logout", auth.Logout)
+
+ // Private Route Group...
+ private := r.Group("/private", auth.AuthRequired())
+ {
+ private.GET("", func(c *gin.Context) {
+ c.String(http.StatusOK, "Private!")
+ }
+ // ...
+ }
+```
+
+## Examples
Prerequisites:
@@ -30,85 +55,60 @@ Prerequisites:
* [Google](https://developers.google.com/identity/protocols/oauth2/openid-connect)
* [GitHub](https://plugins.miniorange.com/oauth-openid-login-using-github)
* etc
-
-The examples below will use Google Accounts. See: [go-oidc examples readme](https://github.com/coreos/go-oidc/tree/v3/example)
-* Sessions example: [example/main.go](example/main.go)
+### DEX Identity Provider
-```go
-package main
+The example below will use [DEX IdP](https://dexidp.io/). Please clone their repo and start DEX in a separate window.
+
+* Start DEX IdP:
+
+```console
+./bin/dex serve examples/config-dev.yaml
+```
-import (
- "fmt"
- "net/http"
- "os"
+* Start [DEX ExampleApp(example/dex/main.go)]:
- oidcauth "github.com/TJM/gin-gonic-oidcauth"
- "github.com/gin-contrib/sessions"
- "github.com/gin-contrib/sessions/cookie"
- "github.com/gin-gonic/gin"
-)
+```console
+go run example/dex/main.go
+```
-func main() {
- r := gin.Default()
+* Visit:
+ * Attempt to access something "private"
+ * Login:
+ * Logout:
- // Session Config (Basic cookies)
- store := cookie.NewStore([]byte("secret"), nil) // Do not use "secret", nil in production. This sets the keypairs for auth, encryption of the cookies.
- r.Use(sessions.Sessions("mysession", store)) // Sessions must be Use(d) before oidcauth, as oidcauth requires sessions
+### Google Accounts Identity Provider
- // NOTE: DefaultConfig uses Google Accounts
- // - See https://github.com/coreos/go-oidc/blob/v3/example/README.md
- auth, err := oidcauth.GetOidcAuth(oidcauth.DefaultConfig())
- if err != nil {
- panic("auth setup failed")
- }
- if os.Getenv("DEBUG") != "" {
- auth.Debug = true
- }
+The example below will use Google Accounts. See: [go-oidc examples readme](https://github.com/coreos/go-oidc/tree/v3/example).
- r.GET("/login", auth.Login) // Unnecessary, as requesting a "AuthRequired" resource will initiate login, but potentially convenient
- r.GET("/auth/google/callback", auth.AuthCallback)
- r.GET("/logout", auth.Logout)
-
- // Allow access to / for unauthenticated users, but authenticated users will be greated by name.
- r.GET("/", func(c *gin.Context) {
- session := sessions.Default(c)
- name := "world"
- n := session.Get("name")
- if n != nil {
- name = n.(string)
- }
- // session.Save() // if it has been changed, which it has not
- c.String(http.StatusOK, fmt.Sprintf("Hello, %s.", name))
- })
+NOTE: This example used port `5556` to be compatible with the other go-oidc examples, but it will clash with "dex" which runs on the same port by default.
- private := r.Group("/private", auth.AuthRequired())
- {
- private.GET("", func(c *gin.Context) {
- var name, email, out string
- login := c.GetString(oidcauth.AuthUserKey)
- session := sessions.Default(c)
- n := session.Get("name")
- if n == nil {
- name = "Someone without a name?"
- } else {
- name = n.(string)
- }
- e := session.Get("email")
- if e != nil {
- email = e.(string)
- }
- out = fmt.Sprintf("Hello, %s <%s>.\nLogin: %s\n", name, email, login)
- // session.Save() // if it has been changed, which it has not
- c.String(http.StatusOK, out)
- return
- })
- }
+* Setup Google
+
+ 1. Visit your [Google Developer Console][google-developer-console].
+ 2. Click "Credentials" on the left column.
+ 3. Click the "Create credentials" button followed by "OAuth client ID".
+ 4. Select "Web application" and add "http://127.0.0.1:5556/auth/google/callback" as an authorized redirect URI.
+ 5. Click create and add the printed client ID and secret to your environment using the following variables:
- r.Run(":5556")
-}
+ ```bash
+ export GOOGLE_OAUTH2_CLIENT_ID=
+ export GOOGLE_OAUTH2_CLIENT_SECRET=
+ ```
+
+* Start Google Example [example/google/main.go](example/google/main.go):
+
+```console
+go run example/google/main.go
```
+* Visit:
+ * Attempt to access something "private"
+ * Login:
+ * Logout:
+
+[google-developer-console]: https://console.developers.google.com/apis/dashboard
+
## License
Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
diff --git a/config.go b/config.go
index ffee646..c9c91b2 100644
--- a/config.go
+++ b/config.go
@@ -19,11 +19,11 @@ type Config struct {
ClientSecret string
// IssuerURL is the root URL to theIdentity Provider
- // Default value is: "https://accounts.google.com"
+ // 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: "http://127.0.0.1:5556/auth/google/callback"
+ // Default value is: (read from OS ENV: OIDC_REDIRECT_URL)
RedirectURL string
// Scopes is a list of OIDC Scopes to request.
@@ -60,10 +60,10 @@ type Config struct {
// NOTE: This matches the examples on https://github.com/coreos/go-oidc/tree/v3/example
func DefaultConfig() (c *Config) {
c = &Config{
- ClientID: os.Getenv("GOOGLE_OAUTH2_CLIENT_ID"),
- ClientSecret: os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET"),
- IssuerURL: "https://accounts.google.com",
- RedirectURL: "http://127.0.0.1:5556/auth/google/callback",
+ 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{"*"},
@@ -73,6 +73,28 @@ func DefaultConfig() (c *Config) {
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.RedirectURL = "http://127.0.0.1:5555/callback"
+ c.IssuerURL = "http://127.0.0.1:5556/dex"
+ 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.RedirectURL = "http://127.0.0.1:5556/auth/google/callback"
+ c.IssuerURL = "https://accounts.google.com"
+ return
+}
+
// Validate will validate the Config
func (c Config) Validate() (err error) {
diff --git a/example/dex/main.go b/example/dex/main.go
new file mode 100644
index 0000000..d36dd02
--- /dev/null
+++ b/example/dex/main.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+ "fmt"
+ "net/http"
+
+ oidcauth "github.com/TJM/gin-gonic-oidcauth"
+ "github.com/gin-contrib/sessions"
+ "github.com/gin-contrib/sessions/cookie"
+ "github.com/gin-gonic/gin"
+)
+
+func main() {
+ r := gin.Default()
+
+ // Session Config (Basic cookies)
+ store := cookie.NewStore([]byte("secret"), nil) // Do not use "secret", nil in production. This sets the keypairs for auth, encryption of the cookies.
+ r.Use(sessions.Sessions("oidcauth-example", store)) // Sessions must be Use(d) before oidcauth, as oidcauth requires sessions
+
+ // Authentication Config - Uses example dex config
+ // - https://dexidp.io/docs/getting-started/
+ auth, err := oidcauth.GetOidcAuth(oidcauth.ExampleConfigDex())
+ if err != nil {
+ panic("auth setup failed")
+ }
+ r.GET("/login", auth.Login) // Unnecessary, as requesting a "AuthRequired" resource will initiate login, but potentially convenient
+ r.GET("/callback", auth.AuthCallback)
+ r.GET("/logout", auth.Logout)
+
+ // Allow access to / for unauthenticated users, but authenticated users will be greated by name.
+ r.GET("/", func(c *gin.Context) {
+ session := sessions.Default(c)
+ name := "world"
+ n := session.Get("name")
+ if n != nil {
+ name = n.(string)
+ }
+ // session.Save() // if it has been changed, which it has not
+ c.String(http.StatusOK, fmt.Sprintf("Hello, %s.", name))
+ })
+
+ private := r.Group("/private", auth.AuthRequired())
+ {
+ private.GET("", func(c *gin.Context) {
+ var name, email, out string
+ login := c.GetString(oidcauth.AuthUserKey)
+ session := sessions.Default(c)
+ n := session.Get("name")
+ if n == nil {
+ name = "Someone without a name?"
+ } else {
+ name = n.(string)
+ }
+ e := session.Get("email")
+ if e != nil {
+ email = e.(string)
+ }
+ out = fmt.Sprintf("Hello, %s <%s>.\nLogin: %s\n", name, email, login)
+ // session.Save() // if it has been changed, which it has not
+ c.String(http.StatusOK, out)
+ return
+ })
+ }
+
+ r.Run(":5555")
+}
diff --git a/example/main.go b/example/google/main.go
similarity index 82%
rename from example/main.go
rename to example/google/main.go
index 84c6e86..e2fcfea 100644
--- a/example/main.go
+++ b/example/google/main.go
@@ -15,12 +15,12 @@ func main() {
r := gin.Default()
// Session Config (Basic cookies)
- store := cookie.NewStore([]byte("secret"), nil) // Do not use "secret", nil in production. This sets the keypairs for auth, encryption of the cookies.
- r.Use(sessions.Sessions("mysession", store)) // Sessions must be Use(d) before oidcauth, as oidcauth requires sessions
+ store := cookie.NewStore([]byte("secret"), nil) // Do not use "secret", nil in production. This sets the keypairs for auth, encryption of the cookies.
+ r.Use(sessions.Sessions("oidcauth-example", store)) // Sessions must be Use(d) before oidcauth, as oidcauth requires sessions
// NOTE: DefaultConfig uses Google Accounts
// - See https://github.com/coreos/go-oidc/blob/v3/example/README.md
- auth, err := oidcauth.GetOidcAuth(oidcauth.DefaultConfig())
+ auth, err := oidcauth.GetOidcAuth(oidcauth.ExampleConfigGoogle())
if err != nil {
panic("auth setup failed")
}