AuthAction is a flexible auth platform for both frontend and M2M apps. It supports OAuth2, social logins, passkeys, and includes user, role, and org management. Scalable up to 1M MAUs for free, it's ideal for startups and enterprises alike.
In this blog, we'll explore how to authorise Go APIs using AuthAction.
Prerequisites
Before you begin, ensure you have:
- Go 1.21 or later: Download from golang.org
- AuthAction Account: You'll need your AuthAction tenant domain and API identifier
Configuration
1. Install Required Packages
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
2. Configure AuthAction Settings
Create a .env
file in your project root:
AUTHACTION_DOMAIN=your-authaction-tenant-domain
AUTHACTION_AUDIENCE=your-authaction-api-identifier
3. Implement JWT Middleware
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()
}
}
Usage
1. Create Your API
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")
}
2. Testing the API
- Obtain an Access Token:
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"
}'
- Call Protected Endpoints:
curl --request GET \
--url http://localhost:8080/api/protected \
--header 'Authorization: Bearer YOUR_ACCESS_TOKEN'
Security Features
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
Common Issues
Invalid Token Errors
- Ensure your token is signed with RS256 algorithm
- Verify the token contains correct issuer and audience claims
- Check that environment variables are correctly set
Public Key Fetching Errors
- Verify your application can reach AuthAction's JWKS endpoint
- The JWKS URI should be:
https://your-authaction-tenant-domain/.well-known/jwks.json
Unauthorized Access
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
Conclusion
Integrating authorization into a Go API application using AuthAction is a straightforward process. This example helps streamline the setup, offering developers a robust foundation to build secure applications with minimal effort.
If you run into any issues, double-check your configurations to ensure everything is set up correctly. Happy coding!
Feel free to leave your thoughts and questions in the comments below!
Top comments (0)