@@ -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
270272func (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.
290293func (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.
317303func (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.
361369func (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.
372379func (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