From b5c8828997e053b849743b91c4e6909d2f35ed4b Mon Sep 17 00:00:00 2001 From: Prabhjot Singh Sethi Date: Thu, 22 May 2025 15:06:08 +0000 Subject: [PATCH] Enable client side handling of the Auth info header Signed-off-by: Prabhjot Singh Sethi --- auth/auth.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 9 +++++++- go.sum | 12 +++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/auth/auth.go b/auth/auth.go index 8c423dc..163775c 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -4,10 +4,15 @@ package auth import ( + "context" "encoding/base64" "encoding/json" "net/http" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "github.com/Prabhjot-Sethi/core/errors" ) @@ -23,6 +28,9 @@ type AuthInfo struct { SessionID string `json:"sid"` } +// struct identifier for the context +type authInfo struct{} + // Sets Auth Info Header in the provided Http Request typically will // be used only by the entity that has performed that authentication // on the given http request already and has the relevant Auth Info @@ -55,6 +63,59 @@ func GetAuthInfoHeader(r *http.Request) (*AuthInfo, error) { return info, nil } +// extract the header information from the GRPC context +func extractHeader(ctx context.Context, header string) (string, error) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return "", status.Error(codes.NotFound, "No Metadata available in incoming message") + } + + hValue, ok := md[header] + if !ok { + return "", status.Errorf(codes.NotFound, "missing header: %s", header) + } + + if len(hValue) != 1 { + return "", status.Errorf(codes.NotFound, "no value associated with header: %s", header) + } + + return hValue[0], nil +} + +// Processes the headers available in context, to validate that the authentication is already performed +func ProcessAuthInfo(ctx context.Context) (context.Context, error) { + val, err := extractHeader(ctx, httpClientAuthContext) + if err != nil { + return ctx, errors.Wrapf(errors.Unauthorized, "failed to extract auth info header: %s", err) + } + + b, err := base64.RawURLEncoding.DecodeString(val) + if err != nil { + return ctx, errors.Wrapf(errors.Unauthorized, "invalid user info received: %s", err) + } + + info := &AuthInfo{} + err = json.Unmarshal(b, info) + if err != nil { + return ctx, errors.Wrapf(errors.Unauthorized, "failed to get user info from header: %s", err) + } + + // create new context with value of the auth info + authCtx := context.WithValue(ctx, authInfo{}, info) + return authCtx, nil +} + +// gets Auth Info from Context available in the Http Request +func GetAuthInfoFromContext(ctx context.Context) (*AuthInfo, error) { + val := ctx.Value(authInfo{}) + switch info := val.(type) { + case *AuthInfo: + return info, nil + default: + return nil, errors.Wrapf(errors.NotFound, "auth info not found") + } +} + // delete the Auth info header from the given HTTP request func DeleteAuthInfoHeader(r *http.Request) { r.Header.Del(httpClientAuthContext) diff --git a/go.mod b/go.mod index bda355a..8c78a15 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,14 @@ module github.com/Prabhjot-Sethi/core go 1.24 -require github.com/google/go-cmp v0.7.0 // indirect +require google.golang.org/grpc v1.72.1 + +require ( + github.com/google/go-cmp v0.7.0 // indirect + golang.org/x/sys v0.30.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/protobuf v1.36.5 // indirect +) require ( github.com/golang/snappy v1.0.0 // indirect diff --git a/go.sum b/go.sum index 86484f9..3d59a67 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -27,6 +29,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= @@ -36,6 +40,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -48,3 +54,9 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= +google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= +google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=