Skip to content

Commit

Permalink
Add support for authentication with a presigned JWT
Browse files Browse the repository at this point in the history
  • Loading branch information
Tolsto committed Jan 28, 2025
1 parent ecb8f77 commit cb18eb4
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
12 changes: 12 additions & 0 deletions pkg/client/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,15 @@ func ScopeProjectID(projectID string) string {
func ScopeZitadelAPI() string {
return ScopeProjectID(scopeZITADELProjectID)
}

// PreSignedJWT allows using a pre-signed JWT token for authorization.
// This is useful when you already have a valid JWT token and don't want the client
// to generate and sign a new one.
func PreSignedJWT(token string) TokenSourceInitializer {
return func(ctx context.Context, _ string) (oauth2.TokenSource, error) {
return oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: token,
TokenType: oidc.BearerToken,
}), nil
}
}
11 changes: 11 additions & 0 deletions pkg/client/middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type AuthInterceptor struct {
}

type JWTProfileTokenSource func(issuer string, scopes []string) (oauth2.TokenSource, error)
type JWTDirectTokenSource func() (oauth2.TokenSource, error)

func JWTProfileFromPath(ctx context.Context, keyPath string) JWTProfileTokenSource {
return func(issuer string, scopes []string) (oauth2.TokenSource, error) {
Expand Down Expand Up @@ -55,6 +56,16 @@ func NewAuthenticator(issuer string, jwtProfileTokenSource JWTProfileTokenSource
}, nil
}

func NewPresignedJWTAuthenticator(jwtDirectTokenSource JWTDirectTokenSource) (*AuthInterceptor, error) {
ts, err := jwtDirectTokenSource()
if err != nil {
return nil, err
}
return &AuthInterceptor{
TokenSource: oauth2.ReuseTokenSource(nil, ts),
}, nil
}

func (interceptor *AuthInterceptor) Unary() grpc.UnaryClientInterceptor {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
authCtx, err := interceptor.setToken(ctx)
Expand Down
25 changes: 24 additions & 1 deletion pkg/client/zitadel/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"crypto/x509"
"strings"

"github.com/zitadel/oidc/v3/pkg/oidc"
"golang.org/x/oauth2"

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

Expand All @@ -15,6 +18,7 @@ type Connection struct {
issuer string
api string
jwtProfileTokenSource middleware.JWTProfileTokenSource
jwtDirectTokenSource middleware.JWTDirectTokenSource
scopes []string
orgID string
insecure bool
Expand Down Expand Up @@ -66,7 +70,13 @@ func NewConnection(ctx context.Context, issuer, api string, scopes []string, opt
}

func (c *Connection) setInterceptors(issuer, orgID string, scopes []string, jwtProfileTokenSource middleware.JWTProfileTokenSource) error {
auth, err := middleware.NewAuthenticator(issuer, jwtProfileTokenSource, scopes...)
var auth *middleware.AuthInterceptor
var err error
if c.jwtDirectTokenSource != nil {
auth, err = middleware.NewPresignedJWTAuthenticator(c.jwtDirectTokenSource)
} else {
auth, err = middleware.NewAuthenticator(issuer, jwtProfileTokenSource, scopes...)
}
if err != nil {
return err
}
Expand Down Expand Up @@ -125,6 +135,19 @@ func WithJWTProfileTokenSource(provider middleware.JWTProfileTokenSource) func(*
}
}

// Use a pre-signed JWT for authentication
func WithJWTDirectTokenSource(jwt string) func(*Connection) error {
return func(client *Connection) error {
client.jwtDirectTokenSource = func() (oauth2.TokenSource, error) {
return oauth2.StaticTokenSource(&oauth2.Token{
AccessToken: jwt,
TokenType: oidc.BearerToken,
}), nil
}
return nil
}
}

// WithOrgID sets the organization context (where the api calls are executed)
// if not set the resource owner (organization) of the calling user will be used
func WithOrgID(orgID string) func(*Connection) error {
Expand Down

0 comments on commit cb18eb4

Please sign in to comment.