-
Notifications
You must be signed in to change notification settings - Fork 22
/
client.go
106 lines (93 loc) · 2.97 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package system
import (
"io/ioutil"
"net/http"
"time"
"github.com/zitadel/oidc/pkg/client"
"github.com/zitadel/oidc/pkg/oidc"
"golang.org/x/oauth2"
"gopkg.in/square/go-jose.v2"
"github.com/zitadel/zitadel-go/v2/pkg/client/middleware"
"github.com/zitadel/zitadel-go/v2/pkg/client/zitadel"
"github.com/zitadel/zitadel-go/v2/pkg/client/zitadel/system"
)
type Client struct {
Connection *zitadel.Connection
system.SystemServiceClient
}
func NewClient(issuer, api string, source JWTAuthenticationSource, opts ...Option) (*Client, error) {
options := make([]zitadel.Option, len(opts)+1)
options[0] = zitadel.WithJWTProfileTokenSource(source())
for i, opt := range opts {
options[i+1] = opt()
}
conn, err := zitadel.NewConnection(issuer, api, nil, options...)
if err != nil {
return nil, err
}
return &Client{
Connection: conn,
SystemServiceClient: system.NewSystemServiceClient(conn.ClientConn),
}, nil
}
type Option func() zitadel.Option
// WithInsecure disables transport security for the client connection
// use only when absolutely necessary (e.g. local development)
func WithInsecure() func() zitadel.Option {
return func() zitadel.Option {
return zitadel.WithInsecure()
}
}
type JWTAuthenticationSource func() middleware.JWTProfileTokenSource
// JWTProfileFromPath reads the key at the provided path and creates a JWTAuthenticationSource (oauth2.TokensSource)
// to authenticate against the SystemAPI
func JWTProfileFromPath(keyPath, userID string) JWTAuthenticationSource {
return func() middleware.JWTProfileTokenSource {
return func(issuer string, _ []string) (oauth2.TokenSource, error) {
key, err := ioutil.ReadFile(keyPath)
if err != nil {
return nil, err
}
return jwtAuthenticationTokenSource(issuer, userID, key)
}
}
}
// JWTProfileFromKey creates a JWTAuthenticationSource (oauth2.TokensSource) from the provided key (and userID)
// to authenticate against the SystemAPI
func JWTProfileFromKey(key []byte, userID string) JWTAuthenticationSource {
return func() middleware.JWTProfileTokenSource {
return func(issuer string, _ []string) (oauth2.TokenSource, error) {
return jwtAuthenticationTokenSource(issuer, userID, key)
}
}
}
type jwtAuthentication struct {
userID string
audience []string
signer jose.Signer
httpClient *http.Client
}
func jwtAuthenticationTokenSource(issuer, userID string, key []byte) (oauth2.TokenSource, error) {
signer, err := client.NewSignerFromPrivateKeyByte(key, "")
if err != nil {
return nil, err
}
source := &jwtAuthentication{
userID: userID,
audience: []string{issuer},
signer: signer,
httpClient: http.DefaultClient,
}
return source, nil
}
func (j *jwtAuthentication) Token() (*oauth2.Token, error) {
token, err := client.SignedJWTProfileAssertion(j.userID, j.audience, time.Hour, j.signer)
if err != nil {
return nil, err
}
return &oauth2.Token{
AccessToken: token,
TokenType: oidc.BearerToken,
Expiry: time.Now().Add(time.Hour - 5*time.Second),
}, nil
}