123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- /*
- *
- * Copyright 2018 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- // The server demonstrates how to consume and validate OAuth2 tokens provided by
- // clients for each RPC.
- package main
- import (
- "context"
- "crypto/tls"
- "log"
- "net"
- "strings"
- "google.golang.org/grpc"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/credentials"
- pb "google.golang.org/grpc/examples/helloworld/helloworld"
- "google.golang.org/grpc/metadata"
- "google.golang.org/grpc/status"
- "google.golang.org/grpc/testdata"
- )
- var (
- errMissingMetadata = status.Errorf(codes.InvalidArgument, "missing metadata")
- errInvalidToken = status.Errorf(codes.Unauthenticated, "invalid token")
- )
- func main() {
- log.Println("server starting on port 8080...")
- cert, err := tls.LoadX509KeyPair(testdata.Path("server1.pem"), testdata.Path("server1.key"))
- if err != nil {
- log.Fatalf("failed to load key pair: %s", err)
- }
- opts := []grpc.ServerOption{
- // The following grpc.ServerOption adds an interceptor for all unary
- // RPCs. To configure an interceptor for streaming RPCs, see:
- // https://godoc.org/google.golang.org/grpc#StreamInterceptor
- grpc.UnaryInterceptor(ensureValidToken),
- // Enable TLS for all incoming connections.
- grpc.Creds(credentials.NewServerTLSFromCert(&cert)),
- }
- s := grpc.NewServer(opts...)
- pb.RegisterGreeterServer(s, &server{})
- lis, err := net.Listen("tcp", ":8080")
- if err != nil {
- log.Fatalf("failed to listen: %v", err)
- }
- if err := s.Serve(lis); err != nil {
- log.Fatalf("failed to serve: %v", err)
- }
- }
- // server is used to implement helloworld.GreeterServer.
- type server struct{}
- // SayHello implements helloworld.GreeterServer
- func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
- return &pb.HelloReply{Message: "Hello " + in.Name}, nil
- }
- // valid validates the authorization.
- func valid(authorization []string) bool {
- if len(authorization) < 1 {
- return false
- }
- token := strings.TrimPrefix(authorization[0], "Bearer ")
- // Perform the token validation here. For the sake of this example, the code
- // here forgoes any of the usual OAuth2 token validation and instead checks
- // for a token matching an arbitrary string.
- if token != "some-secret-token" {
- return false
- }
- return true
- }
- // ensureValidToken ensures a valid token exists within a request's metadata. If
- // the token is missing or invalid, the interceptor blocks execution of the
- // handler and returns an error. Otherwise, the interceptor invokes the unary
- // handler.
- func ensureValidToken(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
- md, ok := metadata.FromIncomingContext(ctx)
- if !ok {
- return nil, errMissingMetadata
- }
- // The keys within metadata.MD are normalized to lowercase.
- // See: https://godoc.org/google.golang.org/grpc/metadata#New
- if !valid(md["authorization"]) {
- return nil, errInvalidToken
- }
- // Continue execution of handler after ensuring a valid token.
- return handler(ctx, req)
- }
|