Skip to content

Channel Package

Authentication Engine - Portable authentication module supporting OAuth, API Key, Basic, and credential-based auth.


The Channel package (packages/channel/) provides a unified interface for handling various authentication types. It’s designed to be portable and can be used independently of ION Flow.


packages/channel/
├── core/
│ └── app_service.go # Core app execution service
├── services/
│ ├── authorize.go # Authorization flow
│ ├── token.go # Token handling
│ ├── refresh.go # Token refresh
│ ├── callback.go # OAuth callback
│ ├── info.go # Connection info
│ ├── response.go # Response processing
│ └── core.go # Core service
└── models/
├── app.go # App configuration
├── app_action.go # App action
├── app_connection.go # Connection type
├── app_webhook.go # App webhook
├── connection.go # Active connection
└── field.go # Field definitions

TypeDescriptionFlow
oauth2_codeOAuth 2.0 Authorization CodeRedirect → Callback → Token
oauth2_code_refresh_tokenOAuth 2.0 with refreshSame + automatic refresh
api_keyAPI Key authenticationDirect request with key
basicHTTP Basic authenticationUsername/password
client_credentialsOAuth 2.0 Client CredentialsToken request
owner_credentialsOAuth 2.0 Resource OwnerToken request with password

Start the authorization process:

func Authorize(kind string, apiJson map[string]interface{}, params map[string]interface{}, state string) (*AuthResponse, error)

Parameters:

ParameterTypeDescription
kindstringAuth type identifier
apiJsonmap[string]anyAPI configuration
paramsmap[string]anyConnection parameters
statestringOAuth state parameter

Returns:

type AuthResponse struct {
Status string // "authorizing", "success", "error"
Metadata map[string]interface{} // Response data (URL, tokens, etc.)
}

Get or exchange tokens:

func TokenHandler(apiJson map[string]any, params map[string]any) (map[string]any, error)

Refresh expired tokens:

func RefreshHandler(apiJson map[string]any, params map[string]any) (map[string]any, error)

Get connection information:

func Info(kind string, apiJson map[string]any, params map[string]any) (map[string]any, error)

Process API responses:

func ResponseHandler(apiJson map[string]any, response map[string]any) (map[string]any, error)

sequenceDiagram
participant App
participant Channel
participant Provider
App->>Channel: Authorize("oauth2_code", config, params, state)
Channel-->>App: {status: "authorizing", authorization_url: "..."}
App->>Provider: Redirect user to authorization_url
Provider-->>App: Callback with code
App->>Channel: TokenHandler(config, {code: "..."})
Channel->>Provider: Exchange code for token
Provider-->>Channel: Access token + Refresh token
Channel-->>App: {data: {access_token, refresh_token}}
App->>Channel: Info("oauth2_code", config, {connection: {...}})
Channel->>Provider: Get user info
Provider-->>Channel: User data
Channel-->>App: {metadata: {...}}

sequenceDiagram
participant App
participant Channel
participant Provider
App->>Channel: Authorize("api_key", config, params, "")
Channel->>Provider: Test request with API key
Provider-->>Channel: Response
Channel-->>App: {status: "success", metadata: {...}}

{
"type": "oauth2_code_refresh_token",
"authorize": {
"url": "https://provider.com/oauth/authorize",
"qs": {
"client_id": "{{app.client_id}}",
"redirect_uri": "{{app.callback_url}}",
"scope": "read write",
"response_type": "code"
}
},
"token": {
"url": "https://provider.com/oauth/token",
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": {
"client_id": "{{app.client_id}}",
"client_secret": "{{app.client_secret}}",
"code": "{{params.code}}",
"grant_type": "authorization_code",
"redirect_uri": "{{app.callback_url}}"
},
"response": {
"access_token": "{{data.access_token}}",
"refresh_token": "{{data.refresh_token}}",
"expires_in": "{{data.expires_in}}"
}
},
"refresh": {
"url": "https://provider.com/oauth/token",
"method": "POST",
"body": {
"client_id": "{{app.client_id}}",
"client_secret": "{{app.client_secret}}",
"refresh_token": "{{connection.refresh_token}}",
"grant_type": "refresh_token"
}
},
"info": {
"url": "https://api.provider.com/me",
"method": "GET",
"headers": {
"Authorization": "Bearer {{connection.access_token}}"
},
"response": {
"metadata": {
"id": "{{data.id}}",
"name": "{{data.name}}",
"email": "{{data.email}}"
}
}
}
}
{
"type": "api_key",
"url": "https://api.provider.com/validate",
"method": "GET",
"headers": {
"X-API-Key": "{{params.api_key}}"
},
"response": {
"metadata": {
"account_id": "{{data.account_id}}",
"name": "{{data.name}}"
}
}
}

import "gitlab.com/altacrest/flow_binaries/packages/channel/services"
// 1. Start authorization
response, err := services.Authorize(
"oauth2_code",
appConfig,
params,
uuid.New().String(),
)
// Redirect user to response.Metadata["authorization_url"]
// 2. Handle callback
tokenResponse, err := services.TokenHandler(appConfig, map[string]any{
"code": callbackCode,
})
// 3. Get user info
info, err := services.Info("oauth2_code", appConfig, map[string]any{
"connection": tokenResponse["data"],
})
// 4. Refresh token when needed
newToken, err := services.RefreshHandler(appConfig, map[string]any{
"connection": existingConnection,
})
response, err := services.Authorize("api_key", appConfig, map[string]any{
"api_key": "your-api-key",
}, "")
if response.Status == "success" {
// Connection valid
metadata := response.Metadata
}

LibraryPurpose
gorm.io/datatypesJSON field support