Installation
Install the SDK using go get:go get -u github.com/scalekit-inc/scalekit-sdk-go
Quick Start
Initialize the Scalekit client with your environment credentials:utils/auth.go
package main
import (
"os"
"github.com/scalekit-inc/scalekit-sdk-go"
)
var scalekitClient, err = scalekit.NewScalekitClient(
os.Getenv("SCALEKIT_ENVIRONMENT_URL"),
os.Getenv("SCALEKIT_CLIENT_ID"),
os.Getenv("SCALEKIT_CLIENT_SECRET"),
)
if err != nil {
panic(err)
}
Core Methods
Generate Authorization URL
Create an authorization URL to redirect users:Login handler
import (
"net/http"
"github.com/gin-gonic/gin"
)
func loginHandler(c *gin.Context) {
redirectUri := "https://yourapp.com/auth/callback"
options := scalekit.AuthorizationUrlOptions{
Scopes: []string{"openid", "profile", "email", "offline_access"},
State: generateSecureState(), // For CSRF protection
}
url, err := scalekitClient.GetAuthorizationUrl(redirectUri, options)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate URL"})
return
}
c.Redirect(http.StatusFound, url.String())
}
Exchange Authorization Code
Exchange the authorization code for tokens:Callback handler
func authCallbackHandler(c *gin.Context) {
code := c.Query("code")
errorParam := c.Query("error")
if errorParam != "" {
c.Redirect(http.StatusFound, "/login?error=auth_failed")
return
}
if code == "" {
c.Redirect(http.StatusFound, "/login?error=missing_code")
return
}
// Exchange code for tokens
options := scalekit.AuthenticationOptions{}
authResult, err := scalekitClient.AuthenticateWithCode(
c.Request.Context(),
code,
"https://yourapp.com/auth/callback",
options,
)
if err != nil {
log.Printf("Token exchange failed: %v", err)
c.Redirect(http.StatusFound, "/login?error=exchange_failed")
return
}
user := authResult.User
accessToken := authResult.AccessToken
refreshToken := authResult.RefreshToken
// Store tokens securely
session := sessions.Default(c)
session.Set("user", user)
session.Save()
c.Redirect(http.StatusFound, "/dashboard")
}
Validate Access Token
Validate tokens in middleware:Auth middleware
import (
"context"
"net/http"
"github.com/gin-gonic/gin"
)
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
accessToken, err := c.Cookie("accessToken")
if err != nil || accessToken == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication required"})
c.Abort()
return
}
// Validate token
isValid, err := scalekitClient.ValidateAccessToken(
c.Request.Context(),
accessToken,
)
if err != nil || !isValid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
c.Next()
}
}
Refresh Access Token
Refresh expired tokens:Token refresh
ctx := context.Background()
refreshToken, _ := c.Cookie("refreshToken")
authResult, err := scalekitClient.RefreshAccessToken(ctx, refreshToken)
if err != nil {
log.Printf("Token refresh failed: %v", err)
c.Redirect(http.StatusFound, "/login")
return
}
// Update cookies with new tokens
c.SetSameSite(http.SameSiteStrictMode)
c.SetCookie(
"accessToken",
authResult.AccessToken,
authResult.ExpiresIn-60,
"/",
"",
true, // Secure
true, // HttpOnly
)
Organization Management
Create Organization
Create organizations for enterprise customers:import "context"
ctx := context.Background()
organization, err := scalekitClient.Organization.CreateOrganization(
ctx,
"Acme Corp",
scalekit.CreateOrganizationOptions{
ExternalID: "org_12345",
},
)
if err != nil {
log.Printf("Failed to create organization: %v", err)
return
}
fmt.Printf("Organization created: %s\n", organization.ID)
Generate Admin Portal Link
Generate portal links for SSO configuration:ctx := context.Background()
link, err := scalekitClient.Organization().GeneratePortalLink(
ctx,
organizationID,
)
if err != nil {
return "", err
}
// Use link.Location for iframe or shareable URL
return link.Location, nil
Session Management
Get Session Details
Retrieve session information:ctx := context.Background()
sessionDetails, err := scalekitClient.Session().GetSession(
ctx,
"ses_1234567890123456",
)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Session: %+v\n", sessionDetails)
List User Sessions
List all sessions for a user:import (
"time"
"context"
sessionsv1 "github.com/scalekit-inc/scalekit-sdk-go/pkg/grpc/scalekit/v1/sessions"
"google.golang.org/protobuf/types/known/timestamppb"
)
ctx := context.Background()
startTime, _ := time.Parse(time.RFC3339, "2025-01-01T00:00:00Z")
endTime, _ := time.Parse(time.RFC3339, "2025-12-31T23:59:59Z")
filter := &sessionsv1.UserSessionFilter{
Status: []string{"ACTIVE"},
StartTime: timestamppb.New(startTime),
EndTime: timestamppb.New(endTime),
}
userSessions, err := scalekitClient.Session().GetUserSessions(
ctx,
"usr_1234567890123456",
10, // page size
"", // page token
filter,
)
if err != nil {
log.Fatal(err)
}
Revoke Session
Revoke specific sessions:ctx := context.Background()
revokedSession, err := scalekitClient.Session().RevokeSession(
ctx,
"ses_1234567890123456",
)
if err != nil {
log.Fatal(err)
}
fmt.Println("Session revoked")
Revoke All User Sessions
Logout from all devices:ctx := context.Background()
revokedSessions, err := scalekitClient.Session().RevokeAllUserSessions(
ctx,
"usr_1234567890123456",
)
if err != nil {
log.Fatal(err)
}
fmt.Println("All sessions revoked")
Advanced Features
Custom Authorization Options
Customize authorization with additional parameters:options := scalekit.AuthorizationUrlOptions{
Scopes: []string{"openid", "profile", "email", "offline_access"},
OrganizationId: "org_123", // Route to specific organization
ConnectionId: "conn_456", // Route to specific connection
LoginHint: "[email protected]", // Pre-fill email
Prompt: "login", // Force re-authentication
State: generateState(), // CSRF protection
}
url, _ := scalekitClient.GetAuthorizationUrl(redirectUri, options)
Error Handling
Handle SDK errors appropriately:import "errors"
authResult, err := scalekitClient.AuthenticateWithCode(
ctx,
code,
redirectUri,
options,
)
if err != nil {
// Check for specific error types
if errors.Is(err, scalekit.ErrInvalidGrant) {
// Authorization code expired or already used
return c.Redirect(http.StatusFound, "/login?error=code_expired")
}
if errors.Is(err, scalekit.ErrInvalidClient) {
// Invalid credentials
log.Printf("SDK configuration error: %v", err)
}
// Handle other errors
log.Printf("Authentication error: %v", err)
return c.JSON(http.StatusInternalServerError, gin.H{"error": "Authentication failed"})
}
Context-Aware Operations
All SDK methods accept a context for cancellation and timeouts:import (
"context"
"time"
)
// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Use context in SDK calls
authResult, err := scalekitClient.AuthenticateWithCode(
ctx,
code,
redirectUri,
options,
)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
log.Println("Request timed out")
}
return err
}
Framework Examples
Gin
Complete Gin integration:main.go
package main
import (
"context"
"net/http"
"os"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin"
"github.com/scalekit-inc/scalekit-sdk-go"
)
var scalekitClient *scalekit.ScalekitClient
func main() {
var err error
scalekitClient, err = scalekit.NewScalekitClient(
os.Getenv("SCALEKIT_ENVIRONMENT_URL"),
os.Getenv("SCALEKIT_CLIENT_ID"),
os.Getenv("SCALEKIT_CLIENT_SECRET"),
)
if err != nil {
panic(err)
}
r := gin.Default()
// Setup session store
store := cookie.NewStore([]byte(os.Getenv("SESSION_SECRET")))
r.Use(sessions.Sessions("mysession", store))
r.GET("/login", loginHandler)
r.GET("/auth/callback", callbackHandler)
r.GET("/dashboard", AuthMiddleware(), dashboardHandler)
r.Run(":8080")
}
func loginHandler(c *gin.Context) {
state := generateState()
session := sessions.Default(c)
session.Set("oauth_state", state)
session.Save()
options := scalekit.AuthorizationUrlOptions{
Scopes: []string{"openid", "profile", "email"},
State: state,
}
url, _ := scalekitClient.GetAuthorizationUrl(
"https://yourapp.com/auth/callback",
options,
)
c.Redirect(http.StatusFound, url.String())
}
func callbackHandler(c *gin.Context) {
code := c.Query("code")
state := c.Query("state")
session := sessions.Default(c)
storedState := session.Get("oauth_state")
if state != storedState {
c.String(http.StatusBadRequest, "Invalid state")
return
}
options := scalekit.AuthenticationOptions{}
authResult, err := scalekitClient.AuthenticateWithCode(
c.Request.Context(),
code,
"https://yourapp.com/auth/callback",
options,
)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"})
return
}
session.Set("user", authResult.User)
session.Save()
c.Redirect(http.StatusFound, "/dashboard")
}
func dashboardHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Welcome to dashboard"})
}
Echo
Echo framework integration:main.go
package main
import (
"net/http"
"os"
"github.com/labstack/echo/v4"
"github.com/scalekit-inc/scalekit-sdk-go"
)
var scalekitClient *scalekit.ScalekitClient
func main() {
var err error
scalekitClient, err = scalekit.NewScalekitClient(
os.Getenv("SCALEKIT_ENVIRONMENT_URL"),
os.Getenv("SCALEKIT_CLIENT_ID"),
os.Getenv("SCALEKIT_CLIENT_SECRET"),
)
if err != nil {
panic(err)
}
e := echo.New()
e.GET("/login", loginHandler)
e.GET("/auth/callback", callbackHandler)
e.Logger.Fatal(e.Start(":8080"))
}
func loginHandler(c echo.Context) error {
options := scalekit.AuthorizationUrlOptions{
Scopes: []string{"openid", "profile", "email"},
}
url, _ := scalekitClient.GetAuthorizationUrl(
"https://yourapp.com/auth/callback",
options,
)
return c.Redirect(http.StatusFound, url.String())
}
func callbackHandler(c echo.Context) error {
code := c.QueryParam("code")
options := scalekit.AuthenticationOptions{}
authResult, err := scalekitClient.AuthenticateWithCode(
c.Request().Context(),
code,
"https://yourapp.com/auth/callback",
options,
)
if err != nil {
return c.JSON(http.StatusUnauthorized, map[string]string{
"error": "Authentication failed",
})
}
// Store user in session
return c.Redirect(http.StatusFound, "/dashboard")
}
Concurrent Operations
The SDK is safe for concurrent use:import "sync"
func validateMultipleTokens(tokens []string) []bool {
var wg sync.WaitGroup
results := make([]bool, len(tokens))
ctx := context.Background()
for i, token := range tokens {
wg.Add(1)
go func(index int, accessToken string) {
defer wg.Done()
isValid, _ := scalekitClient.ValidateAccessToken(ctx, accessToken)
results[index] = isValid
}(i, token)
}
wg.Wait()
return results
}