No description
Find a file
Neo Huyghe d892d1b16a
All checks were successful
CI / test (push) Successful in 18s
docs(examples): simple, provisioning (CSV), reset_mfa (helpdesk) runnable mains
2026-05-18 22:15:27 +02:00
.forgejo/workflows chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
examples docs(examples): simple, provisioning (CSV), reset_mfa (helpdesk) runnable mains 2026-05-18 22:15:27 +02:00
.gitignore chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
CHANGELOG.md chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
client.go feat(client): Config + New() with clientcredentials.Config + audience EndpointParam 2026-05-18 22:06:24 +02:00
client_test.go test: httptest-based coverage for all services, errors, client (86.2% statements) 2026-05-18 22:13:55 +02:00
doc.go chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
errors.go feat(types,errors): DTOs (User, Session, Passkey, Role, LinkedAccount) + typed APIError with errors.Is support 2026-05-18 22:00:08 +02:00
errors_test.go test: httptest-based coverage for all services, errors, client (86.2% statements) 2026-05-18 22:13:55 +02:00
go.mod feat(client): Config + New() with clientcredentials.Config + audience EndpointParam 2026-05-18 22:06:24 +02:00
go.sum feat(client): Config + New() with clientcredentials.Config + audience EndpointParam 2026-05-18 22:06:24 +02:00
http.go feat(http): request helper, JSON encode/decode, APIError parsing on non-2xx 2026-05-18 22:06:10 +02:00
LICENSE chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
oauth_helpers.go feat(client): Config + New() with clientcredentials.Config + audience EndpointParam 2026-05-18 22:06:24 +02:00
README.md chore: bootstrap orion-auth-m2m-sdk-go (Go 1.23, MIT, Forgejo CI) 2026-05-18 21:58:10 +02:00
testing_helpers_test.go test: httptest-based coverage for all services, errors, client (86.2% statements) 2026-05-18 22:13:55 +02:00
types.go feat(types,errors): DTOs (User, Session, Passkey, Role, LinkedAccount) + typed APIError with errors.Is support 2026-05-18 22:00:08 +02:00
users.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_auth.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_links.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_passkeys.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_roles.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_sessions.go feat(users): full service — CRUD, auth ops, roles, sessions, passkeys, linked accounts 2026-05-18 22:06:45 +02:00
users_subservices_test.go test: httptest-based coverage for all services, errors, client (86.2% statements) 2026-05-18 22:13:55 +02:00
users_test.go test: httptest-based coverage for all services, errors, client (86.2% statements) 2026-05-18 22:13:55 +02:00

orion-auth-m2m-sdk-go

Go SDK for the OrionAuth M2M admin API (/api/v1/m2m/users/*). Authenticates services via OAuth 2.0 Client Credentials and exposes a typed Go API for programmatic user management — create, update, delete, set password, reset MFA, manage roles and sessions, etc.

go get git.nhsoul.fr/nhpro/orion-auth-m2m-sdk-go

Quickstart

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    orionauthm2m "git.nhsoul.fr/nhpro/orion-auth-m2m-sdk-go"
)

func main() {
    client, err := orionauthm2m.New(orionauthm2m.Config{
        BaseURL:      "https://auth.example.com",
        Issuer:       "https://auth.example.com",
        ClientID:     os.Getenv("ORION_M2M_CLIENT_ID"),
        ClientSecret: os.Getenv("ORION_M2M_CLIENT_SECRET"),
        Scopes:       []string{"m2m:users:read", "m2m:users:write"},
    })
    if err != nil {
        log.Fatal(err)
    }

    ctx := context.Background()
    res, err := client.Users().Create(ctx, &orionauthm2m.CreateUserParams{
        Email: "alice@example.com",
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("created", res.User.ID, "password:", res.GeneratedPassword)
}

The SDK handles token caching and silent refresh through the standard golang.org/x/oauth2/clientcredentials token source — you never deal with the bearer header yourself.

Provisioning the M2M client

Before you can use this SDK you need a confidential OAuth client in OrionAuth that is allowed to call the M2M API. In the AdminUI:

  1. Service Accounts → New service account
  2. Pick a token endpoint auth method (client_secret_basic works for most services; use private_key_jwt for higher-trust environments)
  3. Save → copy the client secret shown once
  4. In the Resource Permissions section, grant the m2m:users:* scopes your service needs (start with m2m:users:read + m2m:users:write; add m2m:users:delete, m2m:users:manage_auth, m2m:users:manage_roles only when needed — least privilege)

API

client.Users().Create(ctx, params) (*CreateUserResult, error)
client.Users().Get(ctx, userID)    (*User, error)
client.Users().ListPage(ctx, page, perPage) ([]User, total int64, error)
client.Users().Iterate(ctx, batchSize, func([]User) error) error
client.Users().Update(ctx, userID, params) (*User, error)
client.Users().Delete(ctx, userID) error

client.Users().SetPassword(ctx, userID, password) error
client.Users().Unlock(ctx, userID) error
client.Users().ResetMFA(ctx, userID) error

client.Users().Roles().List(ctx, userID) ([]Role, error)
client.Users().Roles().Assign(ctx, userID, roleID) error
client.Users().Roles().Remove(ctx, userID, roleID) error

client.Users().Sessions().List(ctx, userID) ([]Session, error)
client.Users().Sessions().Revoke(ctx, userID, sessionID) error
client.Users().Sessions().RevokeAll(ctx, userID) (count int64, error)

client.Users().Passkeys().List(ctx, userID) ([]Passkey, error)
client.Users().Passkeys().Delete(ctx, userID, passkeyID) error

client.Users().LinkedAccounts().List(ctx, userID) ([]LinkedAccount, error)
client.Users().LinkedAccounts().Unlink(ctx, userID, linkID) error

Errors

Every API call returns an *APIError on a non-2xx response. Use errors.Is to react to specific failures:

_, err := client.Users().Get(ctx, missingID)
switch {
case errors.Is(err, orionauthm2m.ErrNotFound):
    // user gone
case errors.Is(err, orionauthm2m.ErrInsufficientScope):
    // token lacks the required m2m:users:* scope
case errors.Is(err, orionauthm2m.ErrM2MOnly):
    // someone wired a user bearer token here by mistake
case err != nil:
    // anything else — APIError will have StatusCode + Code + Message
}

License

MIT.