Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"encoding/pem"
"errors"
"fmt"
"net/http"
"strings"

"firebase.google.com/go/internal"
Expand Down Expand Up @@ -102,6 +101,7 @@ func NewClient(ctx context.Context, c *internal.AuthConfig) (*Client, error) {
}
email = svcAcct.ClientEmail
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may as well keep the spacing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a simple merge of the existing dev branch into master. We don't make manual changes here. These have to be addressed on dev as separate PRs.

var snr signer
if email != "" && pk != nil {
snr = serviceAcctSigner{email: email, pk: pk}
Expand All @@ -111,21 +111,15 @@ func NewClient(ctx context.Context, c *internal.AuthConfig) (*Client, error) {
return nil, err
}
}
hc := http.DefaultClient
if len(c.Opts) > 0 { // TODO: fix the default when len = 0
hc, _, err = transport.NewHTTPClient(ctx, c.Opts...)
if err != nil {
return nil, err
}
}
ks, err := newHTTPKeySource(googleCertURL, hc)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

hc, _, err := transport.NewHTTPClient(ctx, c.Opts...)
if err != nil {
return nil, err
}

return &Client{
hc: &internal.HTTPClient{Client: hc},
ks: ks,
ks: newHTTPKeySource(googleCertURL, hc),
projectID: c.ProjectID,
snr: snr,
url: idToolKitURL,
Expand Down
19 changes: 14 additions & 5 deletions auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@ var testIDToken string
var testGetUserResponse []byte
var testListUsersResponse []byte

var defaultTestOpts = []option.ClientOption{
option.WithCredentialsFile("../testdata/service_account.json"),
}

func TestMain(m *testing.M) {
var (
err error
ks keySource
ctx context.Context
creds *google.DefaultCredentials
opts []option.ClientOption
)
if appengine.IsDevAppServer() {
aectx, aedone, err := aetest.NewContext()
Expand All @@ -62,8 +67,8 @@ func TestMain(m *testing.M) {
}
} else {
ctx = context.Background()
opt := option.WithCredentialsFile("../testdata/service_account.json")
creds, err = transport.Creds(ctx, opt)
opts = defaultTestOpts
creds, err = transport.Creds(ctx, opts...)
if err != nil {
log.Fatalln(err)
}
Expand All @@ -72,7 +77,7 @@ func TestMain(m *testing.M) {
}
client, err = NewClient(ctx, &internal.AuthConfig{
Creds: creds,
Opts: []option.ClientOption{option.WithCredentialsFile("../testdata/service_account.json")},
Opts: opts,
ProjectID: "mock-project-id",
})
if err != nil {
Expand Down Expand Up @@ -170,7 +175,9 @@ func TestCustomTokenError(t *testing.T) {
}

func TestCustomTokenInvalidCredential(t *testing.T) {
s, err := NewClient(context.Background(), &internal.AuthConfig{})
// AuthConfig with nil Creds
conf := &internal.AuthConfig{Opts: defaultTestOpts}
s, err := NewClient(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -237,7 +244,9 @@ func TestVerifyIDTokenError(t *testing.T) {
}

func TestNoProjectID(t *testing.T) {
c, err := NewClient(context.Background(), &internal.AuthConfig{})
// AuthConfig with empty ProjectID
conf := &internal.AuthConfig{Opts: defaultTestOpts}
c, err := NewClient(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions auth/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ type httpKeySource struct {
Mutex *sync.Mutex
}

func newHTTPKeySource(uri string, hc *http.Client) (*httpKeySource, error) {
func newHTTPKeySource(uri string, hc *http.Client) *httpKeySource {
return &httpKeySource{
KeyURI: uri,
HTTPClient: hc,
Clock: systemClock{},
Mutex: &sync.Mutex{},
}, nil
}
}

// Keys returns the RSA Public Keys hosted at this key source's URI. Refreshes the data if
Expand Down
29 changes: 5 additions & 24 deletions auth/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,8 @@ func TestHTTPKeySource(t *testing.T) {
if err != nil {
t.Fatal(err)
}
ks, err := newHTTPKeySource("http://mock.url", http.DefaultClient)
if err != nil {
t.Fatal(err)
}

ks := newHTTPKeySource("http://mock.url", http.DefaultClient)
if ks.HTTPClient == nil {
t.Errorf("HTTPClient = nil; want non-nil")
}
Expand All @@ -105,11 +102,7 @@ func TestHTTPKeySourceWithClient(t *testing.T) {
}

hc, rc := newTestHTTPClient(data)
ks, err := newHTTPKeySource("http://mock.url", hc)
if err != nil {
t.Fatal(err)
}

ks := newHTTPKeySource("http://mock.url", hc)
if ks.HTTPClient != hc {
t.Errorf("HTTPClient = %v; want %v", ks.HTTPClient, hc)
}
Expand All @@ -120,23 +113,15 @@ func TestHTTPKeySourceWithClient(t *testing.T) {

func TestHTTPKeySourceEmptyResponse(t *testing.T) {
hc, _ := newTestHTTPClient([]byte(""))
ks, err := newHTTPKeySource("http://mock.url", hc)
if err != nil {
t.Fatal(err)
}

ks := newHTTPKeySource("http://mock.url", hc)
if keys, err := ks.Keys(); keys != nil || err == nil {
t.Errorf("Keys() = (%v, %v); want = (nil, error)", keys, err)
}
}

func TestHTTPKeySourceIncorrectResponse(t *testing.T) {
hc, _ := newTestHTTPClient([]byte("{\"foo\": 1}"))
ks, err := newHTTPKeySource("http://mock.url", hc)
if err != nil {
t.Fatal(err)
}

ks := newHTTPKeySource("http://mock.url", hc)
if keys, err := ks.Keys(); keys != nil || err == nil {
t.Errorf("Keys() = (%v, %v); want = (nil, error)", keys, err)
}
Expand All @@ -148,11 +133,7 @@ func TestHTTPKeySourceTransportError(t *testing.T) {
Err: errors.New("transport error"),
},
}
ks, err := newHTTPKeySource("http://mock.url", hc)
if err != nil {
t.Fatal(err)
}

ks := newHTTPKeySource("http://mock.url", hc)
if keys, err := ks.Keys(); keys != nil || err == nil {
t.Errorf("Keys() = (%v, %v); want = (nil, error)", keys, err)
}
Expand Down
61 changes: 41 additions & 20 deletions auth/user_mgt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ import (
"testing"

"firebase.google.com/go/internal"

"golang.org/x/net/context"
"golang.org/x/oauth2"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
)

var testUser = &UserRecord{
Expand Down Expand Up @@ -621,24 +624,17 @@ func TestMakeExportedUser(t *testing.T) {
}

func TestHTTPError(t *testing.T) {
s := mockAuthServer{}
s.Srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.Req = append(s.Req, r)
w.WriteHeader(500)
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"error":"test"}`))
}))
s := echoServer([]byte(`{"error":"test"}`), t)
defer s.Close()
s.Status = 500

client, err := NewClient(context.Background(), &internal.AuthConfig{})
if err != nil {
t.Fatal()
u, err := s.Client.GetUser(context.Background(), "some uid")
if u != nil || err == nil {
t.Fatalf("GetUser() = (%v, %v); want = (nil, error)", u, err)
}
client.url = s.Srv.URL + "/"

want := `http error status: 500; reason: {"error":"test"}`
_, err = client.GetUser(context.Background(), "some uid")
if err == nil || err.Error() != want {
if err.Error() != want {
t.Errorf("GetUser() = %v; want = %q", err, want)
}
}
Expand All @@ -664,7 +660,6 @@ type mockAuthServer struct {
func echoServer(resp interface{}, t *testing.T) *mockAuthServer {
var b []byte
var err error
testVersion := "test.version"
switch v := resp.(type) {
case nil:
b = []byte("")
Expand All @@ -678,19 +673,30 @@ func echoServer(resp interface{}, t *testing.T) *mockAuthServer {
}
s := mockAuthServer{Resp: b}

const testToken = "test.token"
const testVersion = "test.version"

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatal(err)
}
s.Rbody = reqBody
s.Req = append(s.Req, r)
vh := r.Header.Get("X-Client-Version")
wantvh := "Go/Admin/" + testVersion
if vh != wantvh {
t.Errorf("version header = %s; want: %s", vh, wantvh)

gh := r.Header.Get("Authorization")
wh := "Bearer " + testToken
if gh != wh {
t.Errorf("Authorization header = %q; want = %q", gh, wh)
}
s.Rbody = reqBody

gh = r.Header.Get("X-Client-Version")
wh = "Go/Admin/" + testVersion
if gh != wh {
t.Errorf("X-Client-Version header = %q; want: %q", gh, wh)
}

for k, v := range s.Header {
w.Header().Set(k, v)
}
Expand All @@ -702,7 +708,14 @@ func echoServer(resp interface{}, t *testing.T) *mockAuthServer {

})
s.Srv = httptest.NewServer(handler)
authClient, err := NewClient(context.Background(), &internal.AuthConfig{Version: testVersion})

conf := &internal.AuthConfig{
Opts: []option.ClientOption{
option.WithTokenSource(&mockTokenSource{testToken}),
},
Version: testVersion,
}
authClient, err := NewClient(context.Background(), conf)
if err != nil {
t.Fatal(err)
}
Expand All @@ -714,3 +727,11 @@ func echoServer(resp interface{}, t *testing.T) *mockAuthServer {
func (s *mockAuthServer) Close() {
s.Srv.Close()
}

type mockTokenSource struct {
AccessToken string
}

func (m *mockTokenSource) Token() (*oauth2.Token, error) {
return &oauth2.Token{AccessToken: m.AccessToken}, nil
}
12 changes: 11 additions & 1 deletion firebase.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"cloud.google.com/go/firestore"

"firebase.google.com/go/auth"
"firebase.google.com/go/iid"
"firebase.google.com/go/internal"
"firebase.google.com/go/storage"

Expand All @@ -44,7 +45,7 @@ var firebaseScopes = []string{
}

// Version of the Firebase Go Admin SDK.
const Version = "2.2.1"
const Version = "2.3.0"

// An App holds configuration and state common to all Firebase services that are exposed from the SDK.
type App struct {
Expand Down Expand Up @@ -89,6 +90,15 @@ func (a *App) Firestore(ctx context.Context) (*firestore.Client, error) {
return firestore.NewClient(ctx, a.projectID, a.opts...)
}

// InstanceID returns an instance of iid.Client.
func (a *App) InstanceID(ctx context.Context) (*iid.Client, error) {
conf := &internal.InstanceIDConfig{
ProjectID: a.projectID,
Opts: a.opts,
}
return iid.NewClient(ctx, conf)
}

// NewApp creates a new App from the provided config and client options.
//
// If the client options contain a valid credential (a service account file, a refresh token file or an
Expand Down
12 changes: 12 additions & 0 deletions firebase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,18 @@ func TestFirestoreWithNoProjectID(t *testing.T) {
}
}

func TestInstanceID(t *testing.T) {
ctx := context.Background()
app, err := NewApp(ctx, nil, option.WithCredentialsFile("testdata/service_account.json"))
if err != nil {
t.Fatal(err)
}

if c, err := app.InstanceID(ctx); c == nil || err != nil {
t.Errorf("InstanceID() = (%v, %v); want (iid, nil)", c, err)
}
}

func TestCustomTokenSource(t *testing.T) {
ctx := context.Background()
ts := &testTokenSource{AccessToken: "mock-token-from-custom"}
Expand Down
Loading