{"record":{"id":"d8d92e7261338ccb","repo":"gofr-dev/gofr","slug":"errmessage-dynamic-credential-validation-error","errorCode":null,"errorMessage":"errMessage (dynamic credential validation error)","messagePattern":"errMessage \\(dynamic credential validation error\\)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/gofr/service/mock_oauth_server.go","lineNumber":57,"sourceCode":"\t\ttestURL:       \"/test\",\n\t\taudienceClaim: config.EndpointParams.Get(\"aud\"),\n\t}\n\n\tserver.clientID = config.ClientID\n\tserver.clientSecret = config.ClientSecret\n\n\tprivateKey, err := rsa.GenerateKey(rand.Reader, privateKeyBits)\n\trequire.NoError(t, err, \"failed to generate private key, aborting\")\n\n\tserver.privateKey = privateKey\n\n\tmux := http.NewServeMux()\n\n\tmux.HandleFunc(server.tokenURL, func(w http.ResponseWriter, r *http.Request) {\n\t\terrMessage, statusCode := server.validateCredentials(r)\n\n\t\tif statusCode != http.StatusOK {\n\t\t\thttp.Error(w, errMessage, statusCode)\n\t\t\treturn\n\t\t}\n\n\t\taccessToken, err := server.generateToken(getClaims(r))\n\t\tif err != nil {\n\t\t\thttp.Error(w, \"Unable to generate token\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\t// Prepare the JSON response\n\t\tw.Header().Set(\"Content-Type\", \"application/json\")\n\t\tw.Header().Set(\"Cache-Control\", \"no-store\")\n\t\tw.Header().Set(\"Pragma\", \"no-cache\")\n\n\t\ttokenResponse := map[string]any{\n\t\t\t\"access_token\": accessToken,\n\t\t\t\"token_type\":   \"Bearer\",\n\t\t\t\"expires_in\":   3600,         // Expires in 1 hour","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/service/mock_oauth_server.go#L39-L75","documentation":"In the mock OAuth server (mock_oauth_server.go:57), validateCredentials returns an error message and HTTP status; when credentials are invalid the handler responds with http.Error(w, errMessage, statusCode). The exact body text is dynamic — it comes from the server's credential validator (e.g. \"invalid client credentials\"), so this entry represents whatever message your validateCredentials implementation produced.","triggerScenarios":"A test client POSTs to the mock server's token URL with a client ID/secret (or other credentials) that fail the server's validateCredentials check; the response carries that validator's message with a non-200 status.","commonSituations":"Using oAuthConfigForTests-generated credentials against a differently configured mock server; stale credentials cached in test fixtures; pointing a real client at the mock token endpoint with production credentials.","solutions":["Use the client credentials returned by the mock server's setup (oAuthConfigForTests) in the client under test.","Inspect validateCredentials in your mock server setup to see which credential fields it compares and align the test request.","Regenerate test credentials if generateRandomString output was persisted/staled across runs.","Log the request's credentials in the mock to diff expected vs actual."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// client side, before requesting a token\nif clientID == \"\" || clientSecret == \"\" {\n\treturn errors.New(\"missing client credentials for mock OAuth server\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Token(ctx, creds)\nif err != nil {\n\tlog.Printf(\"mock token endpoint said: %s\", readBody(resp)) // dynamic validator message\n\treturn fmt.Errorf(\"credential rejected by mock server: %w\", err)\n}","preventionTips":["Source test credentials from the same helper (oAuthConfigForTests) that configures the mock server.","Never hardcode credentials that may drift from the mock's validateCredentials.","Assert the token endpoint returns 200 in test setup before running dependent tests.","Keep validateCredentials and test fixtures in the same package so they change together."],"tags":["testing","oauth","mock-server","auth"],"backgroundTag":"invalid-oauth-credentials","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}