Skip to content

Commit e374a88

Browse files
authored
Merge pull request #147 from ekristen/firebase-auth-providers
feat: firebase auth providers
2 parents 25f7525 + 5a86a46 commit e374a88

File tree

6 files changed

+475
-2
lines changed

6 files changed

+475
-2
lines changed

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ require (
3535
cloud.google.com/go/compute/metadata v0.5.2 // indirect
3636
cloud.google.com/go/longrunning v0.6.2 // indirect
3737
cloud.google.com/go/monitoring v1.21.2 // indirect
38+
firebase.google.com/go/v4 v4.15.0 // indirect
3839
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 // indirect
3940
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 // indirect
4041
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 // indirect
42+
github.com/MicahParks/keyfunc v1.9.0 // indirect
4143
github.com/apache/arrow/go/v15 v15.0.2 // indirect
4244
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
4345
github.com/cespare/xxhash/v2 v2.3.0 // indirect
@@ -49,6 +51,7 @@ require (
4951
github.com/go-logr/logr v1.4.2 // indirect
5052
github.com/go-logr/stdr v1.2.2 // indirect
5153
github.com/goccy/go-json v0.10.2 // indirect
54+
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
5255
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
5356
github.com/golang/protobuf v1.5.4 // indirect
5457
github.com/google/flatbuffers v23.5.26+incompatible // indirect
@@ -86,6 +89,7 @@ require (
8689
golang.org/x/tools v0.24.0 // indirect
8790
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
8891
google.golang.org/appengine v1.6.8 // indirect
92+
google.golang.org/appengine/v2 v2.0.2 // indirect
8993
google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect
9094
google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect
9195
google.golang.org/grpc v1.67.1 // indirect

go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,17 @@ cloud.google.com/go/storage v1.47.0 h1:ajqgt30fnOMmLfWfu1PWcb+V9Dxz6n+9WKjdNg5R4
129129
cloud.google.com/go/storage v1.47.0/go.mod h1:Ks0vP374w0PW6jOUameJbapbQKXqkjGd/OJRp2fb9IQ=
130130
firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4=
131131
firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs=
132+
firebase.google.com/go/v4 v4.15.0 h1:k27M+cHbyN1YpBI2Cf4NSjeHnnYRB9ldXwpqA5KikN0=
133+
firebase.google.com/go/v4 v4.15.0/go.mod h1:S/4MJqVZn1robtXkHhpRUbwOC4gdYtgsiMMJQ4x+xmQ=
132134
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
133135
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1 h1:pB2F2JKCj1Znmp2rwxxt1J0Fg0wezTMgWYk5Mpbi1kg=
134136
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.24.1/go.mod h1:itPGVDKf9cC/ov4MdvJ2QZ0khw4bfoo9jzwTJlaxy2k=
135137
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s=
136138
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk=
137139
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU=
138140
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1/go.mod h1:viRWSEhtMZqz1rhwmOVKkWl6SwmVowfL9O2YR5gI2PE=
141+
github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o=
142+
github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
139143
github.com/apache/arrow/go/v15 v15.0.2 h1:60IliRbiyTWCWjERBCkO1W4Qun9svcYoZrSLcyOsMLE=
140144
github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA=
141145
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -199,12 +203,16 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
199203
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
200204
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
201205
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
206+
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
207+
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
208+
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
202209
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
203210
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
204211
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
205212
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
206213
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
207214
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
215+
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
208216
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
209217
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
210218
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@@ -355,6 +363,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
355363
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
356364
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
357365
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
366+
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
358367
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
359368
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
360369
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
@@ -474,6 +483,8 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
474483
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
475484
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
476485
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
486+
google.golang.org/appengine/v2 v2.0.2 h1:MSqyWy2shDLwG7chbwBJ5uMyw6SNqJzhJHNDwYB0Akk=
487+
google.golang.org/appengine/v2 v2.0.2/go.mod h1:PkgRUWz4o1XOvbqtWTkBtCitEJ5Tp4HoVEdMMYQR/8E=
477488
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
478489
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
479490
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=

pkg/gcputil/gcp.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,10 @@ func (g *GCP) ImpersonateServiceAccount(ctx context.Context, targetServiceAccoun
8383
defer credsClient.Close()
8484

8585
req := &credentialspb.GenerateAccessTokenRequest{
86-
Name: fmt.Sprintf("projects/-/serviceAccounts/%s", targetServiceAccount),
87-
Scope: []string{"https://www.googleapis.com/auth/cloud-platform"},
86+
Name: fmt.Sprintf("projects/-/serviceAccounts/%s", targetServiceAccount),
87+
Scope: []string{
88+
"https://www.googleapis.com/auth/cloud-platform",
89+
},
8890
Lifetime: &durationpb.Duration{
8991
Seconds: int64(time.Hour.Seconds()), // 1 hour
9092
},

pkg/gcputil/identitytoolkit.go

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package gcputil
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"net/http"
9+
10+
"github.com/sirupsen/logrus"
11+
"google.golang.org/api/option"
12+
htransport "google.golang.org/api/transport/http"
13+
)
14+
15+
const identityPlatformBasePath = "https://identitytoolkit.googleapis.com/admin/v2/"
16+
17+
// ProjectConfig represents the configuration of a project in Identity Platform
18+
type ProjectConfig struct {
19+
Name string `json:"name"`
20+
AutoDeleteAnonymousUsers bool `json:"autodeleteAnonymousUsers"`
21+
SignIn *SignInConfig `json:"signIn,omitempty"`
22+
MFA *MFAConfig `json:"mfa,omitempty"`
23+
}
24+
25+
type SignInConfig struct {
26+
Anonymous *ProviderConfig `json:"anonymous,omitempty"`
27+
Email *ProviderConfig `json:"email,omitempty"`
28+
Phone *ProviderConfig `json:"phoneNumber,omitempty"`
29+
}
30+
31+
type MFAConfig struct {
32+
State string `json:"state"`
33+
}
34+
35+
type ProviderConfig struct {
36+
Enabled bool `json:"enabled"`
37+
}
38+
39+
// IdentityPlatformService provides methods to interact with the Identity Platform API
40+
type IdentityPlatformService struct {
41+
client *http.Client
42+
BasePath string
43+
UserAgent string
44+
}
45+
46+
// NewIdentityPlatformService creates a new Identity Platform client
47+
func NewIdentityPlatformService(ctx context.Context, opts ...option.ClientOption) (*IdentityPlatformService, error) {
48+
client, endpoint, err := htransport.NewClient(ctx, opts...)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
s := &IdentityPlatformService{client: client, BasePath: identityPlatformBasePath}
54+
if endpoint != "" {
55+
s.BasePath = endpoint
56+
}
57+
58+
return s, nil
59+
}
60+
61+
// GetProjectConfig retrieves the configuration of a project
62+
func (s *IdentityPlatformService) GetProjectConfig(ctx context.Context, projectID string) (*ProjectConfig, error) {
63+
url := fmt.Sprintf("%sprojects/%s/config", s.BasePath, projectID)
64+
logrus.Tracef("url: %s", url)
65+
66+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
67+
if err != nil {
68+
return nil, fmt.Errorf("error creating request: %v", err)
69+
}
70+
71+
resp, err := s.client.Do(req)
72+
if err != nil {
73+
return nil, fmt.Errorf("error requesting project config: %v", err)
74+
}
75+
defer resp.Body.Close()
76+
77+
if resp.StatusCode != http.StatusOK {
78+
return nil, fmt.Errorf("API request error: status %d", resp.StatusCode)
79+
}
80+
81+
var config ProjectConfig
82+
if err = json.NewDecoder(resp.Body).Decode(&config); err != nil {
83+
return nil, fmt.Errorf("error decoding response: %v", err)
84+
}
85+
return &config, nil
86+
}
87+
88+
// UpdateProjectConfig updates the configuration of a project
89+
func (s *IdentityPlatformService) UpdateProjectConfig(ctx context.Context, projectID string, config *ProjectConfig) (*ProjectConfig, error) {
90+
url := fmt.Sprintf("%sprojects/%s/config", s.BasePath, projectID)
91+
logrus.Tracef("url: %s", url)
92+
93+
body, err := json.Marshal(config)
94+
if err != nil {
95+
return nil, fmt.Errorf("error marshaling request body: %v", err)
96+
}
97+
98+
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, url, bytes.NewReader(body))
99+
if err != nil {
100+
return nil, fmt.Errorf("error creating request: %v", err)
101+
}
102+
req.Header.Set("Content-Type", "application/json")
103+
104+
resp, err := s.client.Do(req)
105+
if err != nil {
106+
return nil, fmt.Errorf("error updating project config: %v", err)
107+
}
108+
defer resp.Body.Close()
109+
110+
if resp.StatusCode != http.StatusOK {
111+
return nil, fmt.Errorf("API request error: status %d", resp.StatusCode)
112+
}
113+
114+
var updatedConfig ProjectConfig
115+
if err = json.NewDecoder(resp.Body).Decode(&updatedConfig); err != nil {
116+
return nil, fmt.Errorf("error decoding response: %v", err)
117+
}
118+
return &updatedConfig, nil
119+
}
120+
121+
type ListDefaultSupportedOAuthIdpConfigsResponse struct {
122+
DefaultSupportedIdpConfigs []*DefaultSupportedOAuthIdpConfig `json:"defaultSupportedIdpConfigs"`
123+
}
124+
125+
type DefaultSupportedOAuthIdpConfig struct {
126+
Name *string `json:"name,omitempty"`
127+
Enabled *bool `json:"enabled,omitempty"`
128+
ClientID *string `json:"clientId,omitempty"`
129+
ClientSecret *string `json:"clientSecret,omitempty"`
130+
}
131+
132+
type ListOAuthIdpConfigsResponse struct {
133+
OAuthIdpConfigs []*OAuthIdpConfig `json:"oauthIdpConfigs"`
134+
}
135+
136+
type OAuthIdpConfig struct {
137+
Name *string `json:"name"`
138+
ClientId *string `json:"clientId"`
139+
Issuer *string `json:"issuer"`
140+
DisplayName *string `json:"displayName"`
141+
Enabled *bool `json:"enabled"`
142+
}
143+
144+
// ListDefaultSupportedOAuthIdpConfigs lists the OAuth IDP configurations of a project
145+
func (s *IdentityPlatformService) ListDefaultSupportedOAuthIdpConfigs(ctx context.Context, projectID string) (*ListDefaultSupportedOAuthIdpConfigsResponse, error) {
146+
url := fmt.Sprintf("%sprojects/%s/defaultSupportedIdpConfigs", s.BasePath, projectID)
147+
logrus.Tracef("url: %s", url)
148+
149+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
150+
if err != nil {
151+
return nil, fmt.Errorf("error creating request: %v", err)
152+
}
153+
154+
resp, err := s.client.Do(req)
155+
if err != nil {
156+
return nil, fmt.Errorf("error requesting OAuth IDP configs: %v", err)
157+
}
158+
defer resp.Body.Close()
159+
160+
if resp.StatusCode != http.StatusOK {
161+
return nil, fmt.Errorf("API request error: status %d", resp.StatusCode)
162+
}
163+
164+
var configs *ListDefaultSupportedOAuthIdpConfigsResponse
165+
if err = json.NewDecoder(resp.Body).Decode(&configs); err != nil {
166+
return nil, fmt.Errorf("error decoding response: %v", err)
167+
}
168+
return configs, nil
169+
}
170+
171+
// DeleteDefaultSupportedOAuthIdpConfig deletes an OAuth IDP configuration of a project
172+
func (s *IdentityPlatformService) DeleteDefaultSupportedOAuthIdpConfig(ctx context.Context, projectID, configID string) error {
173+
url := fmt.Sprintf("%sprojects/%s/defaultSupportedIdpConfigs/%s", s.BasePath, projectID, configID)
174+
logrus.Tracef("url: %s", url)
175+
176+
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil)
177+
if err != nil {
178+
return fmt.Errorf("error creating request: %v", err)
179+
}
180+
181+
resp, err := s.client.Do(req)
182+
if err != nil {
183+
return fmt.Errorf("error deleting OAuth IDP config: %v", err)
184+
}
185+
defer resp.Body.Close()
186+
187+
if resp.StatusCode != http.StatusOK {
188+
return fmt.Errorf("API request error: status %d", resp.StatusCode)
189+
}
190+
191+
return nil
192+
}
193+
194+
// ListOAuthIdpConfigs lists the OAuth IDP configurations of a project
195+
func (s *IdentityPlatformService) ListOAuthIdpConfigs(ctx context.Context, projectID string) (*ListOAuthIdpConfigsResponse, error) {
196+
url := fmt.Sprintf("%sprojects/%s/oauthIdpConfigs", s.BasePath, projectID)
197+
logrus.Tracef("url: %s", url)
198+
199+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
200+
if err != nil {
201+
return nil, fmt.Errorf("error creating request: %v", err)
202+
}
203+
204+
resp, err := s.client.Do(req)
205+
if err != nil {
206+
return nil, fmt.Errorf("error requesting OAuth IDP configs: %v", err)
207+
}
208+
defer resp.Body.Close()
209+
210+
if resp.StatusCode != http.StatusOK {
211+
return nil, fmt.Errorf("API request error: status %d", resp.StatusCode)
212+
}
213+
214+
var configs *ListOAuthIdpConfigsResponse
215+
if err = json.NewDecoder(resp.Body).Decode(&configs); err != nil {
216+
return nil, fmt.Errorf("error decoding response: %v", err)
217+
}
218+
return configs, nil
219+
}
220+
221+
// DeleteOAuthIdpConfig deletes an OAuth IDP configuration of a project
222+
func (s *IdentityPlatformService) DeleteOAuthIdpConfig(ctx context.Context, projectID, configID string) error {
223+
url := fmt.Sprintf("%sprojects/%s/oauthIdpConfigs/%s", s.BasePath, projectID, configID)
224+
logrus.Tracef("url: %s", url)
225+
226+
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil)
227+
if err != nil {
228+
return fmt.Errorf("error creating request: %v", err)
229+
}
230+
231+
resp, err := s.client.Do(req)
232+
if err != nil {
233+
return fmt.Errorf("error deleting OAuth IDP config: %v", err)
234+
}
235+
defer resp.Body.Close()
236+
237+
if resp.StatusCode != http.StatusOK {
238+
return fmt.Errorf("API request error: status %d", resp.StatusCode)
239+
}
240+
241+
return nil
242+
}

0 commit comments

Comments
 (0)