{"record":{"id":"63d7a117e2b9212f","repo":"grpc/grpc-go","slug":"no-alts-authinfo-found-in-peer","errorCode":null,"errorMessage":"no alts.AuthInfo found in Peer","messagePattern":"no alts\\.AuthInfo found in Peer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/alts/utils.go","lineNumber":49,"sourceCode":"// AuthInfoFromContext extracts the alts.AuthInfo object from the given context,\n// if it exists. This API should be used by gRPC server RPC handlers to get\n// information about the communicating peer. For client-side, use grpc.Peer()\n// CallOption.\nfunc AuthInfoFromContext(ctx context.Context) (AuthInfo, error) {\n\tp, ok := peer.FromContext(ctx)\n\tif !ok {\n\t\treturn nil, errors.New(\"no Peer found in Context\")\n\t}\n\treturn AuthInfoFromPeer(p)\n}\n\n// AuthInfoFromPeer extracts the alts.AuthInfo object from the given peer, if it\n// exists. This API should be used by gRPC clients after obtaining a peer object\n// using the grpc.Peer() CallOption.\nfunc AuthInfoFromPeer(p *peer.Peer) (AuthInfo, error) {\n\taltsAuthInfo, ok := p.AuthInfo.(AuthInfo)\n\tif !ok {\n\t\treturn nil, errors.New(\"no alts.AuthInfo found in Peer\")\n\t}\n\treturn altsAuthInfo, nil\n}\n\n// ClientAuthorizationCheck checks whether the client is authorized to access\n// the requested resources based on the given expected client service accounts.\n// This API should be used by gRPC server RPC handlers. This API should not be\n// used by clients.\nfunc ClientAuthorizationCheck(ctx context.Context, expectedServiceAccounts []string) error {\n\tauthInfo, err := AuthInfoFromContext(ctx)\n\tif err != nil {\n\t\treturn status.Errorf(codes.PermissionDenied, \"The context is not an ALTS-compatible context: %v\", err)\n\t}\n\tpeer := authInfo.PeerServiceAccount()\n\tfor _, sa := range expectedServiceAccounts {\n\t\tif strings.EqualFold(peer, sa) {\n\t\t\treturn nil\n\t\t}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/alts/utils.go#L31-L67","documentation":"Returned by AuthInfoFromPeer (credentials/alts/utils.go:46-51) when the Peer exists but its AuthInfo field is not of type alts.AuthInfo — the type assertion p.AuthInfo.(AuthInfo) at utils.go:47 fails. The connection was established with non-ALTS credentials (TLS, insecure, etc.), so there is no ALTS auth info to extract.","triggerScenarios":"AuthInfoFromPeer/AuthInfoFromContext is called on a Peer whose AuthInfo is a TLSInfo (or other type) because the channel/server used TLS or insecure credentials instead of ALTS. The assertion at utils.go:47 returns ok==false.","commonSituations":"Server handler using alts.ClientAuthorizationCheck while the server was started with grpc.Creds(credentials.NewTLS(...)); client switched from ALTS to TLS but auth code still calls AuthInfoFromPeer; mixed-credential deployments where some connections are TLS.","solutions":["Ensure the server uses ALTS creds: grpc.NewServer(grpc.Creds(alts.NewServerCreds(opts))) and the client uses alts.NewClientCreds(...).","Before extracting ALTS info, type-check p.AuthInfo: if _, ok := p.AuthInfo.(alts.AuthInfo); !ok { /* not an ALTS conn */ }.","If you must support both TLS and ALTS, branch on the AuthInfo type rather than assuming ALTS.","Use ClientAuthorizationCheck which converts this into codes.PermissionDenied for a clean failure."],"exampleFix":"// before — server runs TLS but handler expects ALTS\nsrv := grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConf)))\n// in handler: alts.AuthInfoFromContext(ctx) -> no alts.AuthInfo found in Peer\n\n// after — match creds to the auth check\nsrv := grpc.NewServer(grpc.Creds(alts.NewServerCreds(opts)))\n// or branch on type\nswitch ai := p.AuthInfo.(type) {\ncase alts.AuthInfo:  _ = ai\ncase credentials.TLSInfo: _ = ai\n}","handlingStrategy":"type-guard","validationCode":"// Branch on AuthInfo type so non-ALTS connections are handled, not errored\nswitch ai := p.AuthInfo.(type) {\ncase alts.AuthInfo:    use(ai)\ncase credentials.TLSInfo: useTLS(ai)\ndefault:               return status.Error(codes.PermissionDenied, \"unsupported creds\")\n}","typeGuard":"func isALTSAuthInfo(ai credentials.AuthInfo) bool {\n    _, ok := ai.(alts.AuthInfo)\n    return ok\n}","tryCatchPattern":"if _, err := alts.AuthInfoFromPeer(p); err != nil {\n    if strings.Contains(err.Error(), \"no alts.AuthInfo found\") {\n        // connection is not ALTS; either switch to ALTS creds or branch by type\n    }\n}","preventionTips":["Match server creds (grpc.Creds) to the auth-info extractor you call.","Type-switch on p.AuthInfo when supporting multiple credential types.","Use ClientAuthorizationCheck to get clean PermissionDenied status."],"tags":["alts","auth","credentials","grpc-go"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}