{"record":{"id":"30bb7e38a5634f93","repo":"grpc/grpc-go","slug":"empty-accesstoken-in-response-v","errorCode":null,"errorMessage":"empty accessToken in response (%v)","messagePattern":"empty accessToken in response \\((.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/sts/sts.go","lineNumber":329,"sourceCode":"\tresp.Body.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif resp.StatusCode == http.StatusOK {\n\t\treturn body, nil\n\t}\n\tlogger.Warningf(\"http status %d, body: %s\", resp.StatusCode, string(body))\n\treturn nil, fmt.Errorf(\"http status %d, body: %s\", resp.StatusCode, string(body))\n}\n\nfunc tokenInfoFromResponse(respBody []byte) (*tokenInfo, error) {\n\trespData := &responseParameters{}\n\tif err := json.Unmarshal(respBody, respData); err != nil {\n\t\treturn nil, fmt.Errorf(\"json.Unmarshal(%v): %v\", respBody, err)\n\t}\n\tif respData.AccessToken == \"\" {\n\t\treturn nil, fmt.Errorf(\"empty accessToken in response (%v)\", string(respBody))\n\t}\n\treturn &tokenInfo{\n\t\ttokenType:  respData.TokenType,\n\t\ttoken:      respData.AccessToken,\n\t\texpiryTime: time.Now().Add(time.Duration(respData.ExpiresIn) * time.Second),\n\t}, nil\n}\n\n// requestParameters stores all STS request attributes defined in\n// https://tools.ietf.org/html/rfc8693#section-2.1.\ntype requestParameters struct {\n\t// REQUIRED. The value \"urn:ietf:params:oauth:grant-type:token-exchange\"\n\t// indicates that a token exchange is being performed.\n\tGrantType string `json:\"grant_type\"`\n\t// OPTIONAL. Indicates the location of the target service or resource where\n\t// the client intends to use the requested security token.\n\tResource string `json:\"resource,omitempty\"`\n\t// OPTIONAL. The logical name of the target service where the client intends","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/sts/sts.go#L311-L347","documentation":"Returned by tokenInfoFromResponse in sts/sts.go:329 when the STS response parsed as valid JSON but the access_token field is empty. Per RFC 8693 the issued_token/access_token is REQUIRED, so gRPC treats an empty value as a protocol violation even on HTTP 200.","triggerScenarios":"The STS server returns 200 with a JSON body missing the access_token field (or an empty string), e.g. returns only issued_token_type/token_type, or an error-shaped JSON that nonetheless carried 200.","commonSituations":"Subject/actor token accepted but no token issued (rare server bug); audience/scope accepted structurally but issuance skipped; STS implementation that returns 200 with an error payload; subject token type not actually exchangeable.","solutions":["Inspect the response body shown in the error to see which fields were returned.","Verify SubjectTokenType is a type the STS server can actually exchange for an access token.","Confirm RequestedTokenType and Audience are supported by the issuer.","Check the STS server logs / contact the token broker owner if 200-with-empty-token persists."],"exampleFix":"// before\nopts := sts.Options{\n    SubjectTokenType: \"urn:ietf:params:oauth:token-type:unknown\",\n}\n\n// after\nopts := sts.Options{\n    SubjectTokenType: \"urn:ietf:params:oauth:token-type:jwt\",\n    RequestedTokenType: \"urn:ietf:params:oauth:token-type:access_token\",\n}","handlingStrategy":"validation","validationCode":"// Ensure requested/subject token types are ones the issuer will exchange for an access token.\n// Validate config before dial; the only runtime guard is parsing the error.\nif opts.SubjectTokenType == \"\" { return errors.New(\"SubjectTokenType required\") }\nif opts.RequestedTokenType != \"\" && opts.RequestedTokenType != \"urn:ietf:params:oauth:token-type:access_token\" {\n    return fmt.Errorf(\"unsupported requested token type %q\", opts.RequestedTokenType)\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"empty accessToken in response\") {\n    // issuer returned 200 with no access_token; verify SubjectTokenType/Audience/RequestedTokenType\n}","preventionTips":["Use standard RFC 8693 token-type URNs for SubjectTokenType and RequestedTokenType.","Confirm Audience matches a value the STS server can mint for.","Log the full response body when this fires to diagnose server-side issuance skips."],"tags":["sts","authentication","network","oauth","validation","go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}