Skip to content

vida-co/go-auth0

Β 
Β 

Repository files navigation

Build Coverage Godoc Go report License
Build Status Coverage Status GoDoc Report Cart MIT License

Contributors

Thanks goes to these wonderful people who contribute(d) or maintain(ed) this repo (emoji key):

Conrad Sopala
Conrad Sopala

🚧 πŸ‘€
Yannick Heinrich
Yannick Heinrich

🚧 πŸ’»
Hao Chau
Hao Chau

πŸ’»
Max Ekman
Max Ekman

πŸ’»
Tony Jia
Tony Jia

πŸ’»

Go-Auth0


go-auth0 is a package helping to authenticate using the Auth0 service.

This repo is supported and maintained by Community Developers, not Auth0. For more information about different support levels check https://auth0.com/docs/support/matrix .

Getting started

Installation

go get github.com/auth0-community/go-auth0

Usage

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(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.

Usage

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

Validating a token outside an HTTP request

Sometimes a token is received from something that is not an HTTP request (such as a GRPC call) when a token must be validated in those cases, use ValidateToken directly

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 = retrieveToken() // Retrieves the token through custom logic, such as for example fetching it from GRPC metadata
if err := validator.ValidateToken(token); err != nil {
	fmt.Println("Cannot validate token because of", err)
}

Contribute

Feel like contributing to this repo? We're glad to hear that! Before you start contributing please visit our Contributing Guideline .

Here you can also find the PR template to fill once creating a PR. It will automatically appear once you open a pull request.

Issues Reporting

Spotted a bug or any other kind of issue? We're just humans and we're always waiting for constructive feedback! Check our section on how to report issues!

Here you can also find the Issue template to fill once opening a new issue. It will automatically appear once you create an issue.

Repo Community

Feel like PRs and issues are not enough? Want to dive into further discussion about the tool? We created topics for each Auth0 Community repo so that you can join discussion on stack available on our repos. Here it is for this one: go-auth0

License

This project is licensed under the MIT license. See the LICENSE file for more info.

What is Auth0?

Auth0 helps you to:

  • Add authentication with multiple authentication sources, either social like

    • Google
    • Facebook
    • Microsoft
    • Linkedin
    • GitHub
    • Twitter
    • Box
    • Salesforce
    • etc.

    or enterprise identity systems like:

    • Windows Azure AD
    • Google Apps
    • Active Directory
    • ADFS
    • Any SAML Identity Provider
  • Add authentication through more traditional username/password databases

  • Add support for linking different user accounts with the same user

  • Support for generating signed JSON Web Tokens to call your APIs and create user identity flow securely

  • Analytics of how, when and where users are logging in

  • Pull data from other sources and add it to user profile, through JavaScript rules

Create a free Auth0 account

  • Go to Auth0 website
  • Hit the SIGN UP button in the upper-right corner

About

πŸ” Go package helping to deal with Auth0

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 100.0%