Skip to main content

Overview

The SSO service provides enterprise-grade single sign-on for your developer organization. It supports multiple identity provider connections (OIDC, SAML 2.0, and LDAP), domain-based enforcement, JIT (just-in-time) provisioning, and session management. Compatible with Okta, Azure AD, Google Workspace, Auth0, OneLogin, PingFederate, OpenLDAP, FreeIPA, and any SAML 2.0, OIDC, or LDAP-compliant provider.
conn, err := client.SSO.CreateConnection(ctx, grantex.CreateSsoConnectionParams{
    Name:            "Okta Production",
    Protocol:        "oidc",
    IssuerURL:       "https://mycompany.okta.com",
    ClientID:        "your-client-id",
    ClientSecret:    "your-client-secret",
    Domains:         []string{"mycompany.com"},
    JitProvisioning: true,
})

Enterprise SSO Connections

Create Connection

Create a new SSO identity provider connection. You can create multiple connections for different domains or providers.
conn, err := client.SSO.CreateConnection(ctx, grantex.CreateSsoConnectionParams{
    Name:            "Okta Production",
    Protocol:        "oidc",
    IssuerURL:       "https://mycompany.okta.com",
    ClientID:        "your-okta-client-id",
    ClientSecret:    "your-okta-client-secret",
    Domains:         []string{"mycompany.com", "mycompany.org"},
    JitProvisioning: true,
    DefaultRole:     "member",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("ID: %s\n", conn.ID)                    // sso_conn_01HX...
fmt.Printf("Name: %s\n", conn.Name)                // Okta Production
fmt.Printf("Protocol: %s\n", conn.Protocol)        // oidc
fmt.Printf("Status: %s\n", conn.Status)            // active
fmt.Printf("Domains: %v\n", conn.Domains)          // [mycompany.com mycompany.org]
fmt.Printf("JIT: %v\n", conn.JitProvisioning)      // true
fmt.Printf("Created: %s\n", conn.CreatedAt)        // 2026-03-29T12:00:00Z

SAML example

samlConn, err := client.SSO.CreateConnection(ctx, grantex.CreateSsoConnectionParams{
    Name:                        "Azure AD SAML",
    Protocol:                    "saml",
    MetadataURL:                 "https://login.microsoftonline.com/.../federationmetadata.xml",
    AssertionConsumerServiceURL: "https://yourapp.com/sso/saml/callback",
    EntityID:                    "https://yourapp.com/saml/metadata",
    Domains:                     []string{"contoso.com"},
    JitProvisioning:             true,
    AttributeMapping: map[string]string{
        "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
        "name":  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/displayname",
    },
})

CreateSsoConnectionParams

FieldTypeRequiredDescription
NamestringYesA human-readable name for this connection.
ProtocolstringYes"oidc", "saml", or "ldap".
IssuerURLstringOIDC onlyThe OIDC issuer URL.
ClientIDstringOIDC onlyOAuth 2.0 client ID from your IdP.
ClientSecretstringOIDC onlyOAuth 2.0 client secret from your IdP.
MetadataURLstringSAML onlyThe SAML metadata URL.
AssertionConsumerServiceURLstringSAML onlyThe SAML ACS URL.
EntityIDstringSAML onlyThe SAML service provider entity ID.
Domains[]stringNoEmail domains to associate with this connection.
JitProvisioningboolNoEnable just-in-time user provisioning.
DefaultRolestringNoDefault role for JIT-provisioned users.
AttributeMappingmap[string]stringNoCustom attribute mapping for SAML assertions.

SsoConnection

FieldTypeDescription
IDstringUnique connection identifier.
NamestringThe connection display name.
Protocolstring"oidc", "saml", or "ldap".
Statusstring"active", "inactive", or "error".
Domains[]stringAssociated email domains.
JitProvisioningboolWhether JIT provisioning is enabled.
CreatedAtstringISO 8601 creation timestamp.
UpdatedAtstringISO 8601 last-updated timestamp.
Note: The ClientSecret is never returned in responses. It is stored securely on the server.

List Connections

List all SSO connections for your organization.
resp, err := client.SSO.ListConnections(ctx)
if err != nil {
    log.Fatal(err)
}

for _, conn := range resp.Connections {
    fmt.Printf("%s (%s) - %s\n", conn.Name, conn.Protocol, conn.Status)
    fmt.Printf("  Domains: %v\n", conn.Domains)
}

Get Connection

Retrieve a single SSO connection by ID.
conn, err := client.SSO.GetConnection(ctx, "sso_conn_01HX...")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Name: %s\n", conn.Name)         // Okta Production
fmt.Printf("Protocol: %s\n", conn.Protocol) // oidc
fmt.Printf("Status: %s\n", conn.Status)     // active

Update Connection

Update an existing SSO connection.
updated, err := client.SSO.UpdateConnection(ctx, "sso_conn_01HX...", grantex.UpdateSsoConnectionParams{
    Name:            "Okta Production (updated)",
    JitProvisioning: grantex.Bool(false),
    Domains:         []string{"mycompany.com", "mycompany.org", "subsidiary.com"},
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Name: %s\n", updated.Name)      // Okta Production (updated)
fmt.Printf("Domains: %v\n", updated.Domains) // [mycompany.com mycompany.org subsidiary.com]

UpdateSsoConnectionParams

FieldTypeDescription
NamestringUpdated display name.
Domains[]stringUpdated list of associated email domains.
JitProvisioning*boolEnable or disable JIT provisioning.
DefaultRolestringUpdated default role for JIT-provisioned users.
AttributeMappingmap[string]stringUpdated SAML attribute mapping.

Delete Connection

Delete an SSO connection. Users associated with this connection will no longer be able to log in via SSO.
err := client.SSO.DeleteConnection(ctx, "sso_conn_01HX...")
if err != nil {
    log.Fatal(err)
}
// Connection is removed
Warning: Deleting a connection immediately disables SSO login for all users routed through it. Ensure you have an alternative authentication method configured before removing a connection.

Test Connection

Test an SSO connection to verify that the IdP configuration is correct and reachable.
test, err := client.SSO.TestConnection(ctx, "sso_conn_01HX...")
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Success: %v\n", test.Success)           // true
fmt.Printf("Message: %s\n", test.Message)            // Connection verified successfully
fmt.Printf("Response time: %dms\n", test.ResponseTime) // 142

SsoTestResult

FieldTypeDescription
SuccessboolWhether the connection test passed.
MessagestringHuman-readable result message.
ResponseTimeintIdP response time in milliseconds.

Enforcement

Set Enforcement

Enforce SSO login for your organization. When enabled, all members must authenticate through an SSO connection.
enforcement, err := client.SSO.SetEnforcement(ctx, grantex.SsoEnforcementParams{
    Enforced:    true,
    ExemptRoles: []string{"owner"},
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Enforced: %v\n", enforcement.Enforced)       // true
fmt.Printf("Exempt roles: %v\n", enforcement.ExemptRoles) // [owner]

SsoEnforcementParams

FieldTypeRequiredDescription
EnforcedboolYesWhether SSO login is enforced for all members.
ExemptRoles[]stringNoRoles exempt from SSO enforcement.

SsoEnforcement

FieldTypeDescription
EnforcedboolWhether SSO enforcement is active.
ExemptRoles[]stringRoles exempt from the enforcement policy.

Session Management

List Sessions

List active SSO sessions for your organization.
sessions, err := client.SSO.ListSessions(ctx)
if err != nil {
    log.Fatal(err)
}

for _, s := range sessions.Sessions {
    fmt.Printf("%s - %s - expires %s\n", s.Email, s.ConnectionName, s.ExpiresAt)
}

SsoSession

FieldTypeDescription
IDstringSession identifier.
EmailstringThe user’s email address.
ConnectionIDstringThe SSO connection used for this session.
ConnectionNamestringDisplay name of the SSO connection.
CreatedAtstringISO 8601 session creation timestamp.
ExpiresAtstringISO 8601 session expiration timestamp.

Revoke Session

Revoke an active SSO session, forcing the user to re-authenticate.
err := client.SSO.RevokeSession(ctx, "sso_sess_01HX...")
if err != nil {
    log.Fatal(err)
}
// Session is revoked

Enterprise Login Flow

Get Login URL (enterprise)

Get the SSO authorization URL for a user based on their email domain. The domain is matched against configured connections to route the user to the correct IdP.
login, err := client.SSO.GetLoginURL(ctx, grantex.SsoLoginParams{
    Domain:      "mycompany.com",
    RedirectURI: "https://yourapp.com/sso/callback",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Redirect to: %s\n", login.AuthorizeURL)
fmt.Printf("Connection: %s\n", login.ConnectionID)  // sso_conn_01HX...
fmt.Printf("Protocol: %s\n", login.Protocol)         // oidc

SsoLoginParams

FieldTypeRequiredDescription
DomainstringYesEmail domain to match against SSO connections.
RedirectURIstringNoOverride the redirect URI for this login request.

SsoLoginResponse (enterprise)

FieldTypeDescription
AuthorizeURLstringThe full authorization URL. Redirect the user here.
ConnectionIDstringThe matched SSO connection ID.
ProtocolstringThe protocol of the matched connection.

Handle OIDC Callback

Handle the callback from an OIDC identity provider. Exchanges the authorization code for user information and provisions the user if JIT is enabled.
result, err := client.SSO.HandleOidcCallback(ctx, grantex.SsoOidcCallbackParams{
    Code:  "oidc_auth_code",
    State: "csrf_state",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Email: %s\n", *result.Email)              // alice@mycompany.com
fmt.Printf("Name: %s\n", *result.Name)                // Alice Smith
fmt.Printf("Subject: %s\n", *result.Sub)              // okta|abc123
fmt.Printf("Developer ID: %s\n", result.DeveloperID)  // dev_01HXYZ...
fmt.Printf("Connection: %s\n", result.ConnectionID)   // sso_conn_01HX...
fmt.Printf("Provisioned: %v\n", result.Provisioned)   // true

SsoOidcCallbackParams

FieldTypeRequiredDescription
CodestringYesThe authorization code from the OIDC callback.
StatestringYesThe state parameter for CSRF protection.

SsoCallbackResponse

FieldTypeDescription
Email*stringThe user’s email address from the IdP.
Name*stringThe user’s display name from the IdP.
Sub*stringThe user’s subject identifier from the IdP.
DeveloperIDstringThe Grantex developer ID.
ConnectionIDstringThe SSO connection that handled this authentication.
ProvisionedboolWhether the user was JIT-provisioned during this login.

Handle SAML Callback

Handle the callback from a SAML 2.0 identity provider. Validates the SAML assertion and provisions the user if JIT is enabled.
result, err := client.SSO.HandleSamlCallback(ctx, grantex.SsoSamlCallbackParams{
    SAMLResponse: samlResponseValue,
    RelayState:   relayStateValue,
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Email: %s\n", *result.Email)              // bob@contoso.com
fmt.Printf("Name: %s\n", *result.Name)                // Bob Jones
fmt.Printf("Developer ID: %s\n", result.DeveloperID)  // dev_01HXYZ...
fmt.Printf("Connection: %s\n", result.ConnectionID)   // sso_conn_02HX...
fmt.Printf("Provisioned: %v\n", result.Provisioned)   // false

SsoSamlCallbackParams

FieldTypeRequiredDescription
SAMLResponsestringYesThe base64-encoded SAML response from the IdP.
RelayStatestringNoThe RelayState parameter from the SAML callback.
Returns the same SsoCallbackResponse as HandleOidcCallback().

Handle LDAP Callback

Authenticate a user via LDAP bind. Unlike OIDC and SAML which use browser redirects, LDAP authentication submits credentials directly. Grantex binds to the LDAP directory, verifies the user’s password, reads their attributes and group memberships, maps groups to scopes, and provisions the user if JIT is enabled.
result, err := client.SSO.HandleLdapCallback(ctx, grantex.SsoLdapCallbackParams{
    Username:     "alice",
    Password:     "user-password",
    ConnectionID: "sso_conn_03HX...",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Email: %s\n", *result.Email)              // alice@mycompany.com
fmt.Printf("Name: %s\n", *result.Name)                // Alice Smith
fmt.Printf("Developer ID: %s\n", result.DeveloperID)  // dev_01HXYZ...
fmt.Printf("Connection: %s\n", result.ConnectionID)   // sso_conn_03HX...
fmt.Printf("Provisioned: %v\n", result.Provisioned)   // true

SsoLdapCallbackParams

FieldTypeRequiredDescription
UsernamestringYesThe user’s LDAP username (e.g. uid, sAMAccountName, or full DN).
PasswordstringYesThe user’s LDAP password for bind authentication.
ConnectionIDstringYesThe SSO connection ID for the LDAP directory.
Returns the same SsoCallbackResponse as HandleOidcCallback().
Note: LDAP credentials are never stored by Grantex. They are used only for the bind operation and discarded immediately after authentication.

Full Enterprise SSO Flow Example

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"

    "github.com/mishrasanjeev/grantex-go"
)

func main() {
    ctx := context.Background()
    client := grantex.NewClient(os.Getenv("GRANTEX_API_KEY"))

    // Step 1: Create SSO connections (one-time setup)
    _, err := client.SSO.CreateConnection(ctx, grantex.CreateSsoConnectionParams{
        Name:            "Okta Production",
        Protocol:        "oidc",
        IssuerURL:       os.Getenv("OKTA_ISSUER_URL"),
        ClientID:        os.Getenv("OKTA_CLIENT_ID"),
        ClientSecret:    os.Getenv("OKTA_CLIENT_SECRET"),
        Domains:         []string{"mycompany.com"},
        JitProvisioning: true,
        DefaultRole:     "member",
    })
    if err != nil {
        log.Fatal(err)
    }

    _, err = client.SSO.CreateConnection(ctx, grantex.CreateSsoConnectionParams{
        Name:                        "Azure AD SAML",
        Protocol:                    "saml",
        MetadataURL:                 os.Getenv("AZURE_METADATA_URL"),
        AssertionConsumerServiceURL: "https://yourapp.com/sso/saml/callback",
        EntityID:                    "https://yourapp.com/saml/metadata",
        Domains:                     []string{"contoso.com"},
        JitProvisioning:             true,
    })
    if err != nil {
        log.Fatal(err)
    }

    // Step 2: Enforce SSO for the organization
    _, err = client.SSO.SetEnforcement(ctx, grantex.SsoEnforcementParams{
        Enforced:    true,
        ExemptRoles: []string{"owner"},
    })
    if err != nil {
        log.Fatal(err)
    }

    // Step 3: Redirect user to SSO login based on email domain
    http.HandleFunc("/sso/login", func(w http.ResponseWriter, r *http.Request) {
        domain := r.URL.Query().Get("domain")
        login, err := client.SSO.GetLoginURL(ctx, grantex.SsoLoginParams{
            Domain:      domain,
            RedirectURI: "https://yourapp.com/sso/callback",
        })
        if err != nil {
            http.Error(w, err.Error(), 500)
            return
        }
        http.Redirect(w, r, login.AuthorizeURL, http.StatusFound)
    })

    // Step 4a: Handle OIDC callback
    http.HandleFunc("/sso/callback", func(w http.ResponseWriter, r *http.Request) {
        result, err := client.SSO.HandleOidcCallback(ctx, grantex.SsoOidcCallbackParams{
            Code:  r.URL.Query().Get("code"),
            State: r.URL.Query().Get("state"),
        })
        if err != nil {
            http.Error(w, err.Error(), 500)
            return
        }

        fmt.Printf("Welcome, %s (%s)\n", *result.Name, *result.Email)
        if result.Provisioned {
            fmt.Println("New user provisioned via JIT")
        }
        http.Redirect(w, r, "/dashboard", http.StatusFound)
    })

    // Step 4b: Handle SAML callback
    http.HandleFunc("/sso/saml/callback", func(w http.ResponseWriter, r *http.Request) {
        r.ParseForm()
        result, err := client.SSO.HandleSamlCallback(ctx, grantex.SsoSamlCallbackParams{
            SAMLResponse: r.FormValue("SAMLResponse"),
            RelayState:   r.FormValue("RelayState"),
        })
        if err != nil {
            http.Error(w, err.Error(), 500)
            return
        }

        fmt.Printf("Welcome, %s (%s)\n", *result.Name, *result.Email)
        http.Redirect(w, r, "/dashboard", http.StatusFound)
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

Legacy Single-Config Methods

Note: The following methods manage a single OIDC configuration per organization. They are retained for backward compatibility. For new integrations, use the enterprise connection methods above which support multiple IdPs, SAML, and domain-based routing.

Create Config

config, err := client.SSO.CreateConfig(ctx, grantex.CreateSsoConfigParams{
    IssuerURL:    "https://accounts.google.com",
    ClientID:     "your-client-id",
    ClientSecret: "your-client-secret",
    RedirectURI:  "https://myapp.com/sso/callback",
})

Get Config

config, err := client.SSO.GetConfig(ctx)
fmt.Printf("Issuer: %s\n", config.IssuerURL)

Delete Config

err := client.SSO.DeleteConfig(ctx)

Get Login URL (legacy)

result, err := client.SSO.GetLoginURL(ctx, "acme-corp")
// Redirect user to result.AuthorizeURL

Handle Callback

result, err := client.SSO.HandleCallback(ctx, authCode, state)
fmt.Printf("User: %s (%s)\n", *result.Name, *result.Email)

Legacy Types

SsoConfig

FieldTypeDescription
IssuerURLstringOIDC issuer URL
ClientIDstringOAuth client ID
RedirectURIstringCallback URL
CreatedAtstringISO 8601 timestamp
UpdatedAtstringISO 8601 timestamp