modulepackage
0.0.0-20240617094136-141af4fdf00d
Repository: https://github.com/bitrise-io/go-auth0.git
Documentation: pkg.go.dev
# README
auth0
auth0 is a package helping to authenticate using the Auth0 service.
Installation
go get github.com/auth0-community/go-auth0
Client Credentials - HS256
Using HS256, the validation key is the secret you retrieve in the dashboard.
// Creates a configuration with the Auth0 information
secret, _ := base64.URLEncoding.DecodeString(os.Getenv("AUTH0_CLIENT_SECRET"))
secretProvider := auth0.NewKeyProvider(secret)
audience := os.Getenv("AUTH0_CLIENT_ID")
configuration := auth0.NewConfiguration(secretProvider, []string{audience}, "https://mydomain.eu.auth0.com/", jose.HS256)
validator := auth0.NewValidator(configuration, nil)
token, err := validator.ValidateRequest(r)
if err != nil {
fmt.Println("Token is not valid:", token)
}
Client Credentials - RS256
Using RS256, the validation key is the certificate you find in advanced settings
// Extracted from https://github.com/square/go-jose/blob/master/utils.go
// LoadPublicKey loads a public key from PEM/DER-encoded data.
// You can download the Auth0 pem file from `applications -> your_app -> scroll down -> Advanced Settings -> certificates -> download`
func LoadPublicKey(data []byte) (interface{}, error) {
input := data
block, _ := pem.Decode(data)
if block != nil {
input = block.Bytes
}
// Try to load SubjectPublicKeyInfo
pub, err0 := x509.ParsePKIXPublicKey(input)
if err0 == nil {
return pub, nil
}
cert, err1 := x509.ParseCertificate(input)
if err1 == nil {
return cert.PublicKey, nil
}
return nil, fmt.Errorf("go-jose/go-jose: parse error, got '%s' and '%s'", err0, err1)
}
// Create a configuration with the Auth0 information
pem, err := ioutil.ReadFile("path/to/your/cert.pem")
if err != nil {
panic(err)
}
secret, err := LoadPublicKey(sharedKey)
if err != nil {
panic(err)
}
secretProvider := auth0.NewKeyProvider(secret)
audience := os.Getenv("AUTH0_CLIENT_ID")
configuration := auth0.NewConfiguration(secretProvider, []string{audience}, "https://mydomain.eu.auth0.com/", jose.RS256)
validator := auth0.NewValidator(configuration, nil)
token, err := validator.ValidateRequest(r)
if err != nil {
fmt.Println("Token is not valid:", token)
}
API with JWK
client := NewJWKClient(JWKClientOptions{URI: "https://mydomain.eu.auth0.com/.well-known/jwks.json"}, nil)
audience := os.Getenv("AUTH0_CLIENT_ID")
configuration := NewConfiguration(client, []string{audience}, "https://mydomain.eu.auth0.com/", jose.RS256)
validator := NewValidator(configuration, nil)
token, err := validator.ValidateRequest(r)
if err != nil {
fmt.Println("Token is not valid:", token)
}
Support interface for configurable key cacher
opts := JWKClientOptions{URI: "https://mydomain.eu.auth0.com/.well-known/jwks.json"}
// Creating key cacher with max age of 100sec and max size of 5 entries.
// Defaults to persistent key cacher if not specified when creating a client.
keyCacher := NewMemoryKeyCacher(time.Duration(100) * time.Second, 5)
client := NewJWKClientWithCache(opts, nil, keyCacher)
searchedKey, err := client.GetKey("KEY_ID")
if err != nil {
fmt.Println("Cannot get key because of", err)
}
Example
Gin
Using Gin and the Auth0 Authorization Extension, you may want to implement the authentication auth like the following:
var auth.AdminGroup string = "my_admin_group"
// Access Control Helper function.
func shouldAccess(wantedGroups []string, groups []interface{}) bool {
/* Fill depending on your needs */
}
// Wrapping a Gin endpoint with Auth0 Groups.
func Auth0Groups(wantedGroups ...string) gin.HandlerFunc {
return gin.HandlerFunc(func(c *gin.Context) {
tok, err := validator.ValidateRequest(c.Request)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
c.Abort()
log.Println("Invalid token:", err)
return
}
claims := map[string]interface{}{}
err = validator.Claims(c.Request, tok, &claims)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid claims"})
c.Abort()
log.Println("Invalid claims:", err)
return
}
metadata, okMetadata := claims["app_metadata"].(map[string]interface{})
authorization, okAuthorization := metadata["authorization"].(map[string]interface{})
groups, hasGroups := authorization["groups"].([]interface{})
if !okMetadata || !okAuthorization || !hasGroups || !shouldAccess(wantedGroups, groups) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "need more privileges"})
c.Abort()
log.Println("Need more provileges")
return
}
c.Next()
})
}
// Use it
r.PUT("/news", auth.Auth0Groups(auth.AdminGroup), api.GetNews)
For a sample usage, take a look inside the example
directory.
# Packages
No description provided by the author
# Functions
FromHeader looks for the request in the authentication header or call ParseMultipartForm if not present.
FromMultiple combines multiple extractors by chaining.
FromParams returns the JWT when passed as the URL query param "token".
NewConfiguration creates a configuration for server.
NewConfigurationTrustProvider creates a configuration for server with no enforcement for token sig alg type, instead trust provider.
NewJWKClient creates a new JWKClient instance from the provided options.
NewJWKClientWithCache creates a new JWKClient instance from the provided options and a custom keycacher interface.
NewKeyProvider provide a simple passphrase key provider.
NewMemoryKeyCacher creates a new Keycacher interface with option to set max age of cached keys and max size of the cache.
NewValidator creates a new validator with the provided configuration.
# Variables
No description provided by the author
No description provided by the author
No description provided by the author
ErrNoJWTHeaders is returned when there are no headers in the JWT.
No description provided by the author
ErrTokenNotFound is returned by the ValidateRequest if the token was not found in the request.
Configuring with MaxCacheSizeNoCheck will skip key cache size check.
Configuring with MaxKeyAgeNoCheck will skip key expiry check.
# Structs
Configuration contains all the information about the Auth0 service.
No description provided by the author
No description provided by the author
No description provided by the author
JWTValidator helps middleware to validate token.
# Interfaces
No description provided by the author
RequestTokenExtractor can extract a JWT from a request.
SecretProvider will provide everything needed retrieve the secret.
# Type aliases
RequestTokenExtractorFunc function conforming to the RequestTokenExtractor interface.
SecretProviderFunc simple wrappers to provide secret with functions.