Skip to content

Instantly share code, notes, and snippets.

@henkman
Created July 17, 2023 19:39
Show Gist options
  • Save henkman/2dc9731247a23e0ca2b2c5bd58487d9c to your computer and use it in GitHub Desktop.
Save henkman/2dc9731247a23e0ca2b2c5bd58487d9c to your computer and use it in GitHub Desktop.
go + fiber + jwt keycloak
module gojwtkeycloak
go 1.20
require (
github.com/coreos/go-oidc/v3 v3.6.0
github.com/gofiber/fiber/v2 v2.48.0
github.com/golang-jwt/jwt/v4 v4.5.0
)
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.48.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.6.0 // indirect
golang.org/x/sys v0.10.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
package main
import (
"context"
"fmt"
"github.com/golang-jwt/jwt/v4"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
"github.com/coreos/go-oidc/v3/oidc"
)
type Claims struct {
jwt.RegisteredClaims
Username string `json:"preferred_username"`
Name string `json:"name"`
GivenName string `json:"given_name"`
FamilyName string `json:"family_name"`
}
func main() {
validator, err := NewKeycloakJWTValidator("http://localhost:8080/realms/myrealm", "myclient")
if err != nil {
panic(err)
}
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
profile := app.Group("profile", keyauth.New(keyauth.Config{
Validator: validator,
}))
profile.Get("name", func(c *fiber.Ctx) error {
claims := c.Locals("claims").(*Claims)
return c.SendString(claims.Username)
})
app.Listen(":3000")
}
func NewKeycloakJWTValidator(issuerUrl, clientId string) (func(*fiber.Ctx, string) (bool, error), error) {
ctx := context.Background()
provider, err := oidc.NewProvider(ctx, issuerUrl)
if err != nil {
return nil, err
}
verifier := provider.Verifier(&oidc.Config{
ClientID: clientId,
})
return func(c *fiber.Ctx, key string) (bool, error) {
var ctx = c.UserContext()
_, err := verifier.Verify(ctx, key)
if err != nil {
return false, err
}
token, _ := jwt.ParseWithClaims(key, &Claims{},
func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v",
token.Header["alg"])
}
return key, nil
})
c.Locals("claims", token.Claims)
return true, nil
}, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment