{"record":{"id":"7a2991455d219c3b","repo":"kataras/iris","slug":"auth-configuration-s-access-token-is-missing-fr","errorCode":null,"errorMessage":"auth: configuration: %s access token is missing from the configuration","messagePattern":"auth: configuration: (.+?) access token is missing from the configuration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/configuration.go","lineNumber":83,"sourceCode":"\nfunc (c *Configuration) validate() (jwt.Keys, error) {\n\tif len(c.Headers) == 0 {\n\t\treturn nil, fmt.Errorf(\"auth: configuration: headers slice is empty\")\n\t}\n\n\tif c.Cookie.Name != \"\" {\n\t\tif c.Cookie.Hash == \"\" || c.Cookie.Block == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"auth: configuration: cookie block and cookie hash are required for security reasons when cookie is used\")\n\t\t}\n\t}\n\n\tkeys, err := c.Keys.Load()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"auth: configuration: %w\", err)\n\t}\n\n\tif _, ok := keys[KIDAccess]; !ok {\n\t\treturn nil, fmt.Errorf(\"auth: configuration: %s access token is missing from the configuration\", KIDAccess)\n\t}\n\n\t// Let's keep refresh optional.\n\t// if _, ok := keys[KIDRefresh]; !ok {\n\t// \treturn nil, fmt.Errorf(\"auth: configuration: %s refresh token is missing from the configuration\", KIDRefresh)\n\t// }\n\treturn keys, nil\n}\n\n// BindRandom binds the \"c\" configuration to random values for keys and cookie security.\n// Keys will not be persisted between restarts,\n// a more persistent storage should be considered for production applications,\n// see BindFile method and LoadConfiguration/MustLoadConfiguration package-level functions.\nfunc (c *Configuration) BindRandom() error {\n\taccessPublic, accessPrivate, err := jwt.GenerateEdDSA()\n\tif err != nil {\n\t\treturn err\n\t}","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/auth/configuration.go#L65-L101","documentation":"The auth Configuration validator (auth/configuration.go:82-84) requires the JWT key set loaded from c.Keys to contain a key whose ID is KIDAccess (\"IRIS_AUTH_ACCESS\"). That key signs/verifies access tokens. When Configuration.New -> validate runs and no key with that KID exists, construction of the auth feature is aborted with this error. The refresh key (IRIS_AUTH_REFRESH) is intentionally optional, but the access key is mandatory.","triggerScenarios":"Calling auth.New(cfg) (directly or via iris auth configuration loading) where cfg.Keys is empty, or contains keys with IDs other than \"IRIS_AUTH_ACCESS\", or a KeysConfiguration whose entries fail to load/parse so keys[KIDAccess] is absent after c.Keys.Load().","commonSituations":"Hand-writing the auth YAML/JSON config and omitting the Keys section entirely; using a custom key ID in the keys list instead of the required IRIS_AUTH_ACCESS constant; copying an example config that only defines IRIS_AUTH_REFRESH; building Configuration programmatically and forgetting to call BindRandom before New.","solutions":["Add a keys entry with ID equal to auth.KIDAccess (\"IRIS_AUTH_ACCESS\"), e.g. an EdDSA key with public/private PEM values and a MaxAge.","Easiest: call cfg.BindRandom() (or use MustGenerateConfiguration / auth.MustLoadConfiguration) to populate both access and refresh keys automatically.","If loading keys from file, verify the keys section ID fields exactly match \"IRIS_AUTH_ACCESS\" and that c.Keys.Load() succeeds (check the wrapped error above this one).","In tests, generate keys with kataras/jwt (jwt.GenerateEdDSA) and assign them to the Keys field before calling auth.New."],"exampleFix":"// before\ncfg := auth.Configuration{\n    Headers: []string{\"Authorization\"},\n}\n_, err := auth.New(cfg) // error: IRIS_AUTH_ACCESS access token is missing\n\n// after\ncfg := auth.Configuration{\n    Headers: []string{\"Authorization\"},\n}\nif err := cfg.BindRandom(); err != nil {\n    panic(err)\n}\n_, err := auth.New(cfg)","handlingStrategy":"validation","validationCode":"func hasAccessKey(cfg auth.Configuration) bool {\n    for _, k := range cfg.Keys {\n        if k.ID == auth.KIDAccess && k.Public != \"\" && k.Private != \"\" {\n            return true\n        }\n    }\n    return false\n}\n// call before auth.New: if !hasAccessKey(cfg) { cfg.BindRandom() }","typeGuard":"func validAuthConfig(cfg auth.Configuration) bool {\n    keys, err := cfg.Keys.Load()\n    if err != nil {\n        return false\n    }\n    _, ok := keys[auth.KIDAccess]\n    return ok\n}","tryCatchPattern":"auth, err := auth.New(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), auth.KIDAccess) {\n        // regenerate keys or fix the keys section before retrying\n        if berr := cfg.BindRandom(); berr != nil {\n            log.Fatalf(\"cannot generate auth keys: %v\", berr)\n        }\n        auth, err = auth.New(cfg)\n    }\n    if err != nil {\n        log.Fatalf(\"auth configuration invalid: %v\", err)\n    }\n}","preventionTips":["Always create auth.Configuration via BindRandom(), MustGenerateConfiguration, or MustLoadConfiguration instead of hand-assembling the Keys field.","Keep the key ID exactly auth.KIDAccess (\"IRIS_AUTH_ACCESS\") in file-based configs.","Persist generated keys to a file (BindFile) so production configs always contain the access key.","Validate configuration files in CI by loading them with auth.LoadConfiguration before deploy."],"tags":["go","jwt","configuration","auth"],"backgroundTag":"missing-jwt-signing-key","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}