当前位置: 首页 > 知识库问答 >
问题:

使用Firebase身份验证从Dart调用Google Cloud运行gRPC:证书由未知机构签名

姬康平
2023-03-14

我使用gRPC中间件在流中检查Firebase身份验证令牌:

package main
...
func main() {
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }

    grpcEndpoint := fmt.Sprintf(":%s", port)
    log.Printf("gRPC endpoint [%s]", grpcEndpoint)

    logger, err := zap.NewProduction()
    if err != nil {
        log.Fatalf("Failed to init logger: %v", err)
    }
    defer logger.Sync() // flushes buffer, if any

    grpcServer := grpc.NewServer(
        grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
            grpc_ctxtags.StreamServerInterceptor(),
            grpc_zap.StreamServerInterceptor(logger),
            grpc_auth.StreamServerInterceptor(server.AuthFunc))),
    )
    ctx := context.Background()
    fb, err := firebase.NewApp(ctx, &firebase.Config{
        ProjectID: "my-firebase-project",
    })
    server.App = fb
    if err != nil {
        panic(fmt.Sprintf("Failed to init firebase: %v", err))
    }
    pb.RegisterMyAwesomeServer(grpcServer, server.NewServer())

    listen, err := net.Listen("tcp", grpcEndpoint)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("Starting: gRPC Listener [%s]\n", grpcEndpoint)
    log.Fatal(grpcServer.Serve(listen))
}
package server
...
func parseToken(ctx context.Context, token string) (*auth.Token, error) {
    client, err := App.Auth(ctx)
    if err != nil {
        return nil, err
    }

    nt, err := client.VerifyIDToken(ctx, token)
    if err != nil {
        return nil, err
    }

    return nt, nil
}

type AuthToken string
func AuthFunc(ctx context.Context) (context.Context, error) {
    token, err := grpc_auth.AuthFromMD(ctx, "bearer")
    if err != nil {
        return nil, err
    }

    tokenInfo, err := parseToken(ctx, token)
    if err != nil {
        return nil, status.Errorf(codes.Unauthenticated, "invalid auth token: %v", err)
    }
    grpc_ctxtags.Extract(ctx).Set("auth.uid", tokenInfo.UID)

    newCtx := context.WithValue(ctx, AuthToken("tokenInfo"), tokenInfo)

    return newCtx, nil
}

客户端只需将他的Firebase身份验证令牌传递给每个流请求

class ClientFirebaseAuthInterceptor implements ClientInterceptor {
  final String _authToken;
  ClientFirebaseAuthInterceptor(this._authToken);
  @override
  ResponseStream<R> interceptStreaming<Q, R>(
      ClientMethod<Q, R> method,
      Stream<Q> requests,
      CallOptions options,
      ClientStreamingInvoker<Q, R> invoker) {
    return invoker(
      method,
      requests,
      options = options.mergedWith(
        CallOptions(metadata: {'authorization': 'bearer $_authToken'}),
      ),
    );
  }
}
final token = await firebase.auth!.currentUser!.getIdToken();
final apiUrl = "my.gcp.run.url"
final channelOptions = ChannelOptions(ChannelCredentials.secure(
    authority: apiUrl,
));
    
final channel = ClientChannel(
    apiUrl,
    options: channelOptions,
    port: 443,
);
final client = MyAwesomeClient(
    channel!,
    options: CallOptions(
      timeout: Duration(seconds: 30),
    ),
    interceptors: [
      ClientFirebaseAuthInterceptor(token),
    ],
);
client.myAwesomeStream(Stream.value(MyAwesomeRequest(foo: 'bar')))

当在本地运行服务器(并转到不安全模式)时,它工作良好。部署时,我应该使用<code>ChannelCredentials。secure()在客户端中,对吗?当GCP运行时,是否自行管理SSL?不知怎的,我得到了这个错误:

gRPC错误(代码:16,代码名称:UNAUTHENTICATED,消息:无效的身份验证令牌:获取https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com:x509:由未知机构签名的证书,详细信息:[],rawResponse:null,拖车:…})

我应该向< code > channel credentials . secure()传递一些附加参数吗?

我的 GCP 运行启用了 HTTP2,并且“允许未经身份验证的调用”如果您正在创建公共 API 或网站,请选中此选项。

非常感谢。

共有1个答案

井高峯
2023-03-14

事实上,后端缺少证书…
使用以下方法解决:

复制--from=build/etc/ssl/certs/ca证书。crt/etc/ssl/certs/

在泊坞窗文件中

FROM golang as build

WORKDIR /all

COPY . .

# Build static binary
RUN CGO_ENABLED=0 GOOS=linux \
    go build -a -installsuffix cgo \
    -o /go/bin/server \
    cmd/main/main.go

FROM scratch

COPY --from=build /go/bin/server /server
COPY --from=build /all/config.yaml /config.yaml
COPY --from=build /all/svc.dev.json /svc.dev.json

### THIS SOLVED
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
###

ENV GOOGLE_APPLICATION_CREDENTIALS /svc.dev.json

ENTRYPOINT ["/server", "./config.yaml"]
 类似资料:
  • 我正在配置一个Kubernetes集群,在CoreOS中有2个节点,如中所述https://coreos.com/kubernetes/docs/latest/getting-started.html没有法兰绒。两台服务器都在同一个网络中。 但在worker中运行kubelet时,我得到了:x509:未知授权机构签署的证书(可能是因为尝试验证候选授权机构证书“kube ca”时出现了“crypto

  • 我正在使用Go包来查询pzug。应用程序的容器化如下: 但是,我得到以下错误: 我已经尝试过这里建议的x509证书,该证书由未知的权威机构签署,但运气不佳。有什么想法吗?

  • 我有一个客户端服务器场景。 我有厚客户端和瘦客户端(浏览器),它们与我的服务器进行通信。 我的胖客户端使用X-509系统证书进行客户端证书身份验证,并与服务器通信 此外,此证书用于生成签名URL(带过期时间),以便我的瘦客户机与服务器通信,用于完整性和授权目的。在这种情况下,我也有一个基于令牌的方法用于身份验证。 现在,我想使用客户端凭据或基于身份验证代码将身份验证机制移动到基于OAuth的流。

  • 我试图从Web请求数据的一些基本示例,但是所有对不同主机的请求都会导致SSL错误:。注意:我不支持代理,也没有发生任何形式的证书拦截,因为使用curl或浏览器没有问题。 我目前使用的代码示例是: 编辑:代码运行在Arch linux内核4.9.37-1-lts上。 编辑2:显然在我的系统上的版本之间有差异,通过(重新)移动证书并重新手动安装包,问题得到了解决。

  • 我正在使用和创建。我正在使用该公司的VPN。 通过kubectl create-f./rc/mongo-rc.yaml命令创建了RC。 使用kubectl describe pod mongo-5zttk命令时出现以下kubernetes事件: 当我尝试使用访问网址时: 我可以成功地从泊坞中心注册表中提取 映像。 环境信息: minikube版本:v1.14.1 kubectl 客户端版本:v1.

  • 我已经在我的android应用程序中添加了Firebase手机认证,它运行良好,但是应用程序名称没有包含在短信验证消息中,因为它出现在Firebase控制台的短信模板中:(%LOGIN_CODE%是%APP_NAME%的校验码。)。 我收到的消息如下:(%LOGIN_CODE%是您的验证码) 我的应用程序的调试版本和发布版本都有这个问题。 那么,如何将应用程序名称添加到此消息中。