v4: trying to create a user token: `These rules must pass for ... id must be present`
Confirmation
- [x] My issue isn't already found on the issue tracker.
- [x] I have replicated my issue using the latest version of the library and it is still present.
cloudflare-go version
v4.0.0
Go environment
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/USER/Library/Caches/go-build'
GOENV='/Users/USER/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/USER/.gvm/pkgsets/go1.23.4/global/pkg/mod'
GONOPROXY='github.com/Kong'
GONOSUMDB='github.com/Kong'
GOOS='darwin'
GOPATH='/Users/USER/.gvm/pkgsets/go1.23.4/global'
GOPRIVATE='github.com/Kong'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/USER/.gvm/gos/go1.23.4'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/USER/.gvm/gos/go1.23.4/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.23.4'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/USER/Library/Application Support/go/telemetry'
GCCGO='gccgo'
GOARM64='v8.0'
AR='ar'
CC='clang'
CXX='clang++'
CGO_ENABLED='1'
GOMOD='/Users/USER/code_/own/bws-sync/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/0m/_63w01516tgf3cftmp9h7ylm0000gn/T/go-build3003870686=/tmp/go-build -gno-record-gcc-switches -fno-common'
Expected output
No error.
Actual output
2025/01/18 13:36:56 POST "https://api.cloudflare.com/client/v4/user/tokens": 400 Bad Request {"success":false,"errors":[{"code":400,"message":"- These rules must pass for `{ \"meta\": { \"key\": \"id\", \"value\": \"47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\" } }`\n - id must be present"}],"messages":[],"result":null}
Code demonstrating the issue
import (
"context"
"fmt"
"log"
"time"
"github.com/caarlos0/env/v11"
"github.com/cloudflare/cloudflare-go/v4"
"github.com/cloudflare/cloudflare-go/v4/dns"
"github.com/cloudflare/cloudflare-go/v4/option"
"github.com/cloudflare/cloudflare-go/v4/shared"
"github.com/cloudflare/cloudflare-go/v4/user"
"github.com/cloudflare/cloudflare-go/v4/zones"
)
...
api := cloudflare.NewClient(
option.WithAPIToken(token),
)
...
token, err := api.User.Tokens.New(ctx, user.TokenNewParams{
Name: cloudflare.String("test"),
Policies: cloudflare.F([]shared.TokenPolicyParam{
{
Effect: cloudflare.F(shared.TokenPolicyEffectAllow),
Resources: cloudflare.F(map[string]string{
"com.cloudflare.Client.account.zone." + zoneID: "*",
}),
PermissionGroups: cloudflare.F([]shared.TokenPolicyPermissionGroupParam{
{
Meta: cloudflare.F(
shared.TokenPolicyPermissionGroupsMetaParam{
Key: cloudflare.String("id"),
Value: cloudflare.String("47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"), // REDACTED
},
),
},
{
Meta: cloudflare.F(
shared.TokenPolicyPermissionGroupsMetaParam{
Key: cloudflare.String("scopes"),
Value: cloudflare.String("com.cloudflare.Client.account"),
},
),
},
{
Meta: cloudflare.F(
shared.TokenPolicyPermissionGroupsMetaParam{
Key: cloudflare.String("name"),
Value: cloudflare.String("DNS Write"),
},
),
},
}),
},
}),
})
Steps to reproduce
- Create API using v4 client.
- Try to create a user token
References
Old code using v0.114.0 of the API worked fine:
token, err := api.CreateAPIToken(ctx, cloudflare.APIToken{
Name: "test",
Policies: []cloudflare.APITokenPolicies{
{
Effect: "allow",
Resources: map[string]interface{}{
"com.cloudflare.api.account.zone." + zoneID: "*",
},
PermissionGroups: []cloudflare.APITokenPermissionGroups{
{
ID: "47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
Scopes: []string{"com.cloudflare.api.account"},
Name: "DNS Write",
},
},
},
},
})
I'm experiencing the same issue. It seems this is ultimately due to TokenPolicyParam's reference to PermissionGroups referencing the param.Field[[]TokenPolicyPermissionGroupParam] type. TokenPolicyPermissionGroupParam only references the Meta field. Yet, it seems there is a TokenPolicyPermissionGroup type, which includes the expected fields, such as ID, Meta, etc.
Would it be best to fix the type TokenPolicyPermissionGroupParam to reference multiple TokenPolicyPermissionGroup instances? It would be nice to see the documentation improvements regarding Permission Groups and their formatting with the updated V4 SDK. The Cloudflare Docs tutorial seems like it might be outdated.
I have submitted a pull request after digging into this and coming up with a solution that enabled me to successfully generate tokens: https://github.com/cloudflare/cloudflare-go/pull/3906
have you tried to use ID within the shared.TokenPolicyPermissionGroupParam struct? instead of just Meta?
The method for creating a user token has been fixed and is currently working as intended. The example noted in the documentation works just fine now that the ID field is available. Reference: https://developers.cloudflare.com/api/go/resources/user/subresources/tokens/methods/create/ Note that while the generated example from the documentation references v3, it works just fine with the most recent version (v4).
This issue should be okay to close as resolved now.
I can confirm that the example from the docs linked by @nicholas-fedor works.
For me it ended up being:
token, err := client.User.Tokens.New(ctx, user.TokenNewParams{
Name: cloudflare.F("test"),
Policies: cloudflare.F([]shared.TokenPolicyParam{
{
Effect: cloudflare.F(shared.TokenPolicyEffectAllow),
Resources: cloudflare.F(map[string]string{
"com.cloudflare.api.account.zone." + zoneID: "*",
}),
PermissionGroups: cloudflare.F([]shared.TokenPolicyPermissionGroupParam{
{
ID: cloudflare.String("47xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
Meta: cloudflare.F(
shared.TokenPolicyPermissionGroupsMetaParam{
Key: cloudflare.String("name"),
Value: cloudflare.String("DNS Write"),
},
),
},
}),
},
}),
})
This issue hasn't been updated in a while. If it's still reproducing, please comment to let us know. Thank you!