Skip to content

Commit

Permalink
feat: dex example and improved readme
Browse files Browse the repository at this point in the history
  • Loading branch information
TJM committed Feb 2, 2021
1 parent 2415f4f commit 6590067
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 77 deletions.
136 changes: 68 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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: <http://127.0.0.1:5555/>
* Attempt to access something "private" <http://127.0.0.1:5555/private>
* Login: <http://127.0.0.1:5555/login>
* Logout: <http://127.0.0.1:5555/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: <http://127.0.0.1:5556/>
* Attempt to access something "private" <http://127.0.0.1:5556/private>
* Login: <http://127.0.0.1:5556/login>
* Logout: <http://127.0.0.1:5556/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).
34 changes: 28 additions & 6 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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{"*"},
Expand All @@ -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) {

Expand Down
66 changes: 66 additions & 0 deletions example/dex/main.go
Original file line number Diff line number Diff line change
@@ -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")
}
6 changes: 3 additions & 3 deletions example/main.go → example/google/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down

0 comments on commit 6590067

Please sign in to comment.