Skip to content

Commit

Permalink
A minimal gRPC credentials implementation for the HTTP basic authenti…
Browse files Browse the repository at this point in the history
…cation scheme
  • Loading branch information
andrewmbenton committed May 4, 2023
1 parent b6dbda4 commit f37a8cb
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,21 @@ conn, err := grpc.Dial(hostname+":443", opts...)
Get a token from within your service handler:
```go
token, err := bearer.TokenFromContext(ctx)
```

##### HTTP basic authentication (user-id and password)

In your client:
```go
opts := []grpc.DialOption{
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})),
grpc.WithPerRPCCredentials(basic.NewPerRPCCredentials("your user-id", "your password")),
}

conn, err := grpc.Dial(hostname+":443", opts...)
```

Get basic auth credentials from within your service handler:
```go
creds, err := basic.CredentialsFromContext(ctx)
```
53 changes: 53 additions & 0 deletions credentials/basic/basic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package basic

import (
"context"
"encoding/base64"
"fmt"
"strings"

"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
)

const (
mdKey = "authorization"
mdValuePrefix = "Basic "
)

type Credentials struct {
UserID string
Password string
}

func (c Credentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
ri, _ := credentials.RequestInfoFromContext(ctx)
if err := credentials.CheckSecurityLevel(ri.AuthInfo, credentials.PrivacyAndIntegrity); err != nil {
return nil, fmt.Errorf("unable to transfer basic.Credentials PerRPCCredentials: %v", err)
}
return map[string]string{
mdKey: mdValuePrefix + base64.StdEncoding.EncodeToString([]byte(c.UserID+":"+c.Password)),
}, nil
}

func (c Credentials) RequireTransportSecurity() bool {
return true
}

func NewPerRPCCredentials(userID, password string) credentials.PerRPCCredentials {
return Credentials{UserID: userID, Password: password}
}

func CredentialsFromContext(ctx context.Context) (Credentials, error) {
var c Credentials
mv := metadata.ValueFromIncomingContext(ctx, mdKey)
if mv == nil || len(mv) == 0 {
return c, fmt.Errorf("basic auth credentials metadata key not found in context")
}
decodedCreds, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(mv[0], mdValuePrefix))
if err != nil {
return c, err
}
c.UserID, c.Password, _ = strings.Cut(string(decodedCreds), ":")
return c, nil
}

0 comments on commit f37a8cb

Please sign in to comment.