Skip to content

Commit 928b104

Browse files
Merge dev into master
2 parents 4121c50 + 862fabe commit 928b104

15 files changed

+460
-100
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,24 @@ jobs:
66
name: Module build
77
runs-on: ubuntu-latest
88
strategy:
9+
fail-fast: false
910
matrix:
10-
go: [1.12, 1.13, 1.14]
11+
go: [1.12, 1.16]
1112

1213
steps:
1314
- name: Set up Go ${{ matrix.go }}
1415
uses: actions/setup-go@v1
1516
with:
1617
go-version: ${{ matrix.go }}
1718

19+
- name: Install golint
20+
run: go get golang.org/x/lint/golint
21+
1822
- name: Check out code
1923
uses: actions/checkout@v2
2024

2125
- name: Run Linter
2226
run: |
23-
go get -u golang.org/x/lint/golint
2427
GOLINT=`go list -f {{.Target}} golang.org/x/lint/golint`
2528
$GOLINT -set_exit_status ./...
2629
@@ -44,12 +47,13 @@ jobs:
4447
runs-on: ubuntu-latest
4548
env:
4649
GOPATH: ${{ github.workspace }}/go
50+
GO111MODULE: off
4751

4852
steps:
49-
- name: Set up Go 1.12
53+
- name: Set up Go 1.16
5054
uses: actions/setup-go@v1
5155
with:
52-
go-version: 1.12
56+
go-version: 1.16
5357

5458
- name: Check out code into GOPATH
5559
uses: actions/checkout@v2

.github/workflows/release.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,16 @@ jobs:
4444
with:
4545
go-version: 1.12
4646

47+
- name: Install golint
48+
run: go get golang.org/x/lint/golint
49+
4750
- name: Check out code
4851
uses: actions/checkout@v2
4952
with:
5053
ref: ${{ github.event.client_payload.ref || github.ref }}
5154

5255
- name: Run Linter
5356
run: |
54-
go get -u golang.org/x/lint/golint
5557
GOLINT=`go list -f {{.Target}} golang.org/x/lint/golint`
5658
$GOLINT -set_exit_status ./...
5759

auth/auth.go

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,12 @@ func NewClient(ctx context.Context, conf *internal.AuthConfig) (*Client, error)
103103
}
104104
}
105105

106-
idTokenVerifier, err := newIDTokenVerifier(ctx, conf.ProjectID, isEmulator)
106+
idTokenVerifier, err := newIDTokenVerifier(ctx, conf.ProjectID)
107107
if err != nil {
108108
return nil, err
109109
}
110110

111-
cookieVerifier, err := newSessionCookieVerifier(ctx, conf.ProjectID, isEmulator)
111+
cookieVerifier, err := newSessionCookieVerifier(ctx, conf.ProjectID)
112112
if err != nil {
113113
return nil, err
114114
}
@@ -144,6 +144,7 @@ func NewClient(ctx context.Context, conf *internal.AuthConfig) (*Client, error)
144144
cookieVerifier: cookieVerifier,
145145
signer: signer,
146146
clock: internal.SystemClock,
147+
isEmulator: isEmulator,
147148
}
148149
return &Client{
149150
baseClient: base,
@@ -265,6 +266,7 @@ type baseClient struct {
265266
cookieVerifier *tokenVerifier
266267
signer cryptoSigner
267268
clock internal.Clock
269+
isEmulator bool
268270
}
269271

270272
func (c *baseClient) withTenantID(tenantID string) *baseClient {
@@ -281,63 +283,68 @@ func (c *baseClient) withTenantID(tenantID string) *baseClient {
281283
// https://firebase.google.com/docs/auth/admin/verify-id-tokens#retrieve_id_tokens_on_clients for
282284
// more details on how to obtain an ID token in a client app.
283285
//
284-
// This function does not make any RPC calls most of the time. The only time it makes an RPC call
285-
// is when Google public keys need to be refreshed. These keys get cached up to 24 hours, and
286-
// therefore the RPC overhead gets amortized over many invocations of this function.
286+
// In non-emulator mode, this function does not make any RPC calls most of the time.
287+
// The only time it makes an RPC call is when Google public keys need to be refreshed.
288+
// These keys get cached up to 24 hours, and therefore the RPC overhead gets amortized
289+
// over many invocations of this function.
287290
//
288291
// This does not check whether or not the token has been revoked. Use `VerifyIDTokenAndCheckRevoked()`
289292
// when a revocation check is needed.
290293
func (c *baseClient) VerifyIDToken(ctx context.Context, idToken string) (*Token, error) {
291-
decoded, err := c.idTokenVerifier.VerifyToken(ctx, idToken)
292-
if err == nil && c.tenantID != "" && c.tenantID != decoded.Firebase.Tenant {
293-
return nil, &internal.FirebaseError{
294-
ErrorCode: internal.InvalidArgument,
295-
String: fmt.Sprintf("invalid tenant id: %q", decoded.Firebase.Tenant),
296-
Ext: map[string]interface{}{
297-
authErrorCode: tenantIDMismatch,
298-
},
299-
}
300-
}
301-
302-
return decoded, err
303-
}
304-
305-
// IsTenantIDMismatch checks if the given error was due to a mismatched tenant ID in a JWT.
306-
func IsTenantIDMismatch(err error) bool {
307-
return hasAuthErrorCode(err, tenantIDMismatch)
294+
return c.verifyIDToken(ctx, idToken, false)
308295
}
309296

310297
// VerifyIDTokenAndCheckRevoked verifies the provided ID token, and additionally checks that the
311298
// token has not been revoked.
312299
//
313-
// This function uses `VerifyIDToken()` internally to verify the ID token JWT. However, unlike
314-
// `VerifyIDToken()` this function must make an RPC call to perform the revocation check.
300+
// Unlike `VerifyIDToken()`, this function must make an RPC call to perform the revocation check.
315301
// Developers are advised to take this additional overhead into consideration when including this
316302
// function in an authorization flow that gets executed often.
317303
func (c *baseClient) VerifyIDTokenAndCheckRevoked(ctx context.Context, idToken string) (*Token, error) {
318-
decoded, err := c.VerifyIDToken(ctx, idToken)
319-
if err != nil {
320-
return nil, err
321-
}
304+
return c.verifyIDToken(ctx, idToken, true)
305+
}
322306

323-
revoked, err := c.checkRevoked(ctx, decoded)
307+
func (c *baseClient) verifyIDToken(ctx context.Context, idToken string, checkRevoked bool) (*Token, error) {
308+
decoded, err := c.idTokenVerifier.VerifyToken(ctx, idToken, c.isEmulator)
324309
if err != nil {
325310
return nil, err
326311
}
327312

328-
if revoked {
313+
if c.tenantID != "" && c.tenantID != decoded.Firebase.Tenant {
329314
return nil, &internal.FirebaseError{
330315
ErrorCode: internal.InvalidArgument,
331-
String: "ID token has been revoked",
316+
String: fmt.Sprintf("invalid tenant id: %q", decoded.Firebase.Tenant),
332317
Ext: map[string]interface{}{
333-
authErrorCode: idTokenRevoked,
318+
authErrorCode: tenantIDMismatch,
334319
},
335320
}
336321
}
337322

323+
if c.isEmulator || checkRevoked {
324+
revoked, err := c.checkRevoked(ctx, decoded)
325+
if err != nil {
326+
return nil, err
327+
}
328+
329+
if revoked {
330+
return nil, &internal.FirebaseError{
331+
ErrorCode: internal.InvalidArgument,
332+
String: "ID token has been revoked",
333+
Ext: map[string]interface{}{
334+
authErrorCode: idTokenRevoked,
335+
},
336+
}
337+
}
338+
}
339+
338340
return decoded, nil
339341
}
340342

343+
// IsTenantIDMismatch checks if the given error was due to a mismatched tenant ID in a JWT.
344+
func IsTenantIDMismatch(err error) bool {
345+
return hasAuthErrorCode(err, tenantIDMismatch)
346+
}
347+
341348
// IsIDTokenRevoked checks if the given error was due to a revoked ID token.
342349
//
343350
// When IsIDTokenRevoked returns true, IsIDTokenInvalid is guranteed to return true.
@@ -352,41 +359,47 @@ func IsIDTokenRevoked(err error) bool {
352359
// decoded claims in the input JWT. See https://firebase.google.com/docs/auth/admin/manage-cookies for more details on
353360
// how to obtain a session cookie.
354361
//
355-
// This function does not make any RPC calls most of the time. The only time it makes an RPC call
356-
// is when Google public keys need to be refreshed. These keys get cached up to 24 hours, and
357-
// therefore the RPC overhead gets amortized over many invocations of this function.
362+
// In non-emulator mode, this function does not make any RPC calls most of the time.
363+
// The only time it makes an RPC call is when Google public keys need to be refreshed.
364+
// These keys get cached up to 24 hours, and therefore the RPC overhead gets amortized
365+
// over many invocations of this function.
358366
//
359367
// This does not check whether or not the cookie has been revoked. Use `VerifySessionCookieAndCheckRevoked()`
360368
// when a revocation check is needed.
361369
func (c *Client) VerifySessionCookie(ctx context.Context, sessionCookie string) (*Token, error) {
362-
return c.cookieVerifier.VerifyToken(ctx, sessionCookie)
370+
return c.verifySessionCookie(ctx, sessionCookie, false)
363371
}
364372

365373
// VerifySessionCookieAndCheckRevoked verifies the provided session cookie, and additionally checks that the
366374
// cookie has not been revoked.
367375
//
368-
// This function uses `VerifySessionCookie()` internally to verify the cookie JWT. However, unlike
369-
// `VerifySessionCookie()` this function must make an RPC call to perform the revocation check.
376+
// Unlike `VerifySessionCookie()`, this function must make an RPC call to perform the revocation check.
370377
// Developers are advised to take this additional overhead into consideration when including this
371378
// function in an authorization flow that gets executed often.
372379
func (c *Client) VerifySessionCookieAndCheckRevoked(ctx context.Context, sessionCookie string) (*Token, error) {
373-
decoded, err := c.VerifySessionCookie(ctx, sessionCookie)
374-
if err != nil {
375-
return nil, err
376-
}
380+
return c.verifySessionCookie(ctx, sessionCookie, true)
381+
}
377382

378-
revoked, err := c.checkRevoked(ctx, decoded)
383+
func (c *Client) verifySessionCookie(ctx context.Context, sessionCookie string, checkRevoked bool) (*Token, error) {
384+
decoded, err := c.cookieVerifier.VerifyToken(ctx, sessionCookie, c.isEmulator)
379385
if err != nil {
380386
return nil, err
381387
}
382388

383-
if revoked {
384-
return nil, &internal.FirebaseError{
385-
ErrorCode: internal.InvalidArgument,
386-
String: "session cookie has been revoked",
387-
Ext: map[string]interface{}{
388-
authErrorCode: sessionCookieRevoked,
389-
},
389+
if c.isEmulator || checkRevoked {
390+
revoked, err := c.checkRevoked(ctx, decoded)
391+
if err != nil {
392+
return nil, err
393+
}
394+
395+
if revoked {
396+
return nil, &internal.FirebaseError{
397+
ErrorCode: internal.InvalidArgument,
398+
String: "session cookie has been revoked",
399+
Ext: map[string]interface{}{
400+
authErrorCode: sessionCookieRevoked,
401+
},
402+
}
390403
}
391404
}
392405

0 commit comments

Comments
 (0)