@@ -2,6 +2,7 @@ import { auth, User } from 'firebase/app';
22import * as React from 'react' ;
33import { user } from 'rxfire/auth' ;
44import { useObservable , useFirebaseApp , ReactFireOptions } from '..' ;
5+ import { from } from 'rxjs' ;
56
67function getAuthFromContext ( ) : auth . Auth {
78 const firebaseApp = useFirebaseApp ( ) ;
@@ -42,13 +43,50 @@ export function useUser<T = unknown>(
4243 ) ;
4344}
4445
46+ export function useIdTokenResult ( user : User , forceRefresh : boolean = false ) {
47+ if ( ! user ) {
48+ throw new Error ( 'you must provide a user' ) ;
49+ }
50+
51+ const idToken$ = from ( user . getIdTokenResult ( forceRefresh ) ) ;
52+
53+ return useObservable ( idToken$ , `${ user . uid } -claims` ) ;
54+ }
55+
4556export interface AuthCheckProps {
4657 auth ?: auth . Auth ;
4758 fallback : React . ReactNode ;
4859 children : React . ReactNode ;
4960 requiredClaims ?: Object ;
5061}
5162
63+ export interface ClaimsCheckProps {
64+ user : User ;
65+ fallback : React . ReactNode ;
66+ children : React . ReactNode ;
67+ requiredClaims ?: Object ;
68+ }
69+
70+ export function ClaimsCheck ( { user, fallback, children, requiredClaims } ) {
71+ const { claims } = useIdTokenResult ( user , false ) ;
72+ const missingClaims = { } ;
73+
74+ Object . keys ( requiredClaims ) . forEach ( claim => {
75+ if ( requiredClaims [ claim ] !== claims [ claim ] ) {
76+ missingClaims [ claim ] = {
77+ expected : requiredClaims [ claim ] ,
78+ actual : claims [ claim ]
79+ } ;
80+ }
81+ } ) ;
82+
83+ if ( Object . keys ( missingClaims ) . length === 0 ) {
84+ return children ;
85+ } else {
86+ return fallback ;
87+ }
88+ }
89+
5290export function AuthCheck ( {
5391 auth,
5492 fallback,
@@ -57,33 +95,19 @@ export function AuthCheck({
5795} : AuthCheckProps ) : React . ReactNode {
5896 const user = useUser < User > ( auth ) ;
5997
60- React . useLayoutEffect ( ( ) => {
61- // TODO(jeff) see if this actually works
62- if ( requiredClaims ) {
63- throw user . getIdTokenResult ( ) . then ( idTokenResult => {
64- const { claims } = idTokenResult ;
65- const missingClaims = { } ;
66- Object . keys ( requiredClaims ) . forEach ( claim => {
67- if ( requiredClaims [ claim ] !== claims [ claim ] ) {
68- missingClaims [ claim ] = {
69- expected : requiredClaims [ claim ] ,
70- actual : claims [ claim ]
71- } ;
72- }
73- } ) ;
74-
75- if ( Object . keys ( missingClaims ) . length > 0 ) {
76- throw new Error (
77- `Mismatched Claims: ${ JSON . stringify ( missingClaims ) } `
78- ) ;
79- }
80- } ) ;
81- }
82- } ) ;
83-
84- if ( ! user ) {
85- return fallback ;
98+ if ( user ) {
99+ return requiredClaims ? (
100+ < ClaimsCheck
101+ user = { user }
102+ fallback = { fallback }
103+ requiredClaims = { requiredClaims }
104+ >
105+ { children }
106+ </ ClaimsCheck >
107+ ) : (
108+ children
109+ ) ;
86110 } else {
87- return children ;
111+ return fallback ;
88112 }
89113}
0 commit comments