mirror of
https://github.com/peridotbuild/peridot.git
synced 2024-06-15 22:30:15 +00:00
Add auth interceptor for gRPC
This commit is contained in:
parent
bfcd4fbbe2
commit
e1f84f2bfc
97
base/go/auth.go
Normal file
97
base/go/auth.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
|
||||
"golang.org/x/oauth2"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const UserContextKey = "user"
|
||||
|
||||
type OidcInterceptorDetails struct {
|
||||
Issuer string
|
||||
Group string
|
||||
AllowUnauthenticated bool
|
||||
}
|
||||
|
||||
type oidcClaims struct {
|
||||
Groups []string
|
||||
}
|
||||
|
||||
func OidcGrpcInterceptor(details *OidcInterceptorDetails) (grpc.UnaryServerInterceptor, error) {
|
||||
ctx := context.TODO()
|
||||
provider, err := oidc.NewProvider(ctx, details.Issuer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
interceptor := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, status.Error(codes.InvalidArgument, "missing metadata")
|
||||
}
|
||||
|
||||
token, err := auth.AuthFromMD(ctx, "bearer")
|
||||
if err != nil {
|
||||
if details.AllowUnauthenticated {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
// let's check if there is a cookie
|
||||
cookie := md.Get("cookie")
|
||||
if len(cookie) == 0 {
|
||||
if details.AllowUnauthenticated {
|
||||
return handler(ctx, req)
|
||||
}
|
||||
return nil, status.Error(codes.Unauthenticated, "missing auth token")
|
||||
}
|
||||
|
||||
// parse the cookie
|
||||
header := http.Header{}
|
||||
header.Add("Cookie", cookie[0])
|
||||
req := http.Request{Header: header}
|
||||
|
||||
// verify the token
|
||||
cookieToken, err := req.Cookie(frontendAuthCookieKey)
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, err.Error())
|
||||
}
|
||||
|
||||
token = cookieToken.Value
|
||||
}
|
||||
|
||||
// verify the token
|
||||
userInfo, err := provider.UserInfo(ctx, oauth2.StaticTokenSource(&oauth2.Token{
|
||||
AccessToken: token,
|
||||
TokenType: "bearer",
|
||||
}))
|
||||
if err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, err.Error())
|
||||
}
|
||||
|
||||
// check if the user is in the group
|
||||
if details.Group != "" {
|
||||
var claims oidcClaims
|
||||
if err := userInfo.Claims(&claims); err != nil {
|
||||
return nil, status.Error(codes.Unauthenticated, err.Error())
|
||||
}
|
||||
|
||||
if !Contains[string](claims.Groups, details.Group) {
|
||||
return nil, status.Error(codes.PermissionDenied, "user not in group")
|
||||
}
|
||||
}
|
||||
|
||||
// add user to context
|
||||
ctx = context.WithValue(ctx, UserContextKey, userInfo)
|
||||
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
return interceptor, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user