Skip to content

Integrating with Go API

This guide explains how to implement JWT authentication in your Go API using AuthAction’s JWKS (JSON Web Key Set) endpoint. You’ll learn how to secure your API endpoints using JWT tokens issued by AuthAction.

Example Repository: For a complete working example, check out our example repository.

Before you begin, ensure you have:

  1. Go 1.21 or later: Download from golang.org
  2. AuthAction Account: You’ll need your AuthAction tenant domain and API identifier
Terminal window
go get -u github.com/golang-jwt/jwt/v5
go get -u github.com/lestrrat-go/jwx/v2/jwk
go get -u github.com/gin-gonic/gin

Create a .env file in your project root:

Terminal window
AUTHACTION_DOMAIN=your-authaction-tenant-domain
AUTHACTION_AUDIENCE=your-authaction-api-identifier

Create a middleware file middleware/auth.go:

type JWKSMiddleware struct {
JWKSUri string
Issuer string
Audience string
Cache *jwk.Cache
}
func NewJWKSMiddleware(jwksUri, issuer, audience string) (*JWKSMiddleware, error) {
cache := jwk.NewCache(context.Background())
return &JWKSMiddleware{
JWKSUri: jwksUri,
Issuer: issuer,
Audience: audience,
Cache: cache,
}, nil
}
func (m *JWKSMiddleware) ValidateToken() gin.HandlerFunc {
return func(c *gin.Context) {
// Get token from Authorization header
tokenString := strings.Split(c.GetHeader("Authorization"), " ")[1]
// Fetch JWKS from AuthAction with caching
keySet, _ := m.Cache.Get(context.Background(), m.JWKSUri)
// Parse and validate token
token, _ := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
kid := token.Header["kid"].(string)
key, _ := keySet.LookupKeyID(kid)
var rawkey interface{}
key.Raw(&rawkey)
return rawkey, nil
})
// Validate claims
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
if aud, ok := claims["aud"].(string); ok && aud == m.Audience {
c.Set("claims", claims)
c.Next()
return
}
}
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
}
}

Create your main API file main.go:

func main() {
// Load environment variables
domain := os.Getenv("AUTHACTION_DOMAIN")
audience := os.Getenv("AUTHACTION_AUDIENCE")
// Construct JWKS URI and issuer
jwksUri := fmt.Sprintf("https://%s/.well-known/jwks.json", domain)
issuer := fmt.Sprintf("https://%s/", domain)
// Initialize middleware
authMiddleware, _ := middleware.NewJWKSMiddleware(jwksUri, issuer, audience)
r := gin.Default()
// Public endpoint
r.GET("/health", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "healthy"})
})
// Protected endpoint
protected := r.Group("/api")
protected.Use(authMiddleware.ValidateToken())
{
protected.GET("/protected", func(c *gin.Context) {
claims, _ := c.Get("claims")
c.JSON(200, gin.H{
"message": "Protected endpoint",
"claims": claims,
})
})
}
r.Run(":8080")
}
  1. Obtain an Access Token:
Terminal window
curl --request POST \
--url https://your-authaction-tenant-domain/oauth2/m2m/token \
--header 'content-type: application/json' \
--data '{
"client_id": "your-authaction-m2m-app-clientid",
"client_secret": "your-authaction-m2m-app-client-secret",
"audience": "your-authaction-api-identifier",
"grant_type": "client_credentials"
}'
  1. Call Protected Endpoints:
Terminal window
curl --request GET \
--url http://localhost:8080/api/protected \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'

The implementation includes:

  • JWT token validation using AuthAction’s JWKS endpoint
  • Automatic JWKS caching with periodic refresh
  • RS256 algorithm for token signing
  • Secure configuration management using environment variables
  • HTTPS support in production
  • Ensure your token is signed with RS256 algorithm
  • Verify the token contains correct issuer and audience claims
  • Check that environment variables are correctly set
  • Verify your application can reach AuthAction’s JWKS endpoint
  • The JWKS URI should be: https://your-authaction-tenant-domain/.well-known/jwks.json

If requests to protected endpoints fail, check:

  • The JWT token is included in the Authorization header
  • The token is valid and not expired
  • The token’s audience matches your API identifier
  • The token’s issuer matches your AuthAction domain