@@ -41,25 +41,118 @@ let _databaseHost: string | undefined = undefined;
41
41
/** The actual address for the Firestore emulator */
42
42
let _firestoreHost : string | undefined = undefined ;
43
43
44
- /** Create an unsecured JWT for the given auth payload. See https://tools.ietf.org/html/rfc7519#section-6. */
45
- function createUnsecuredJwt ( auth : object ) : string {
44
+ export type Provider =
45
+ | 'custom'
46
+ | 'email'
47
+ | 'password'
48
+ | 'phone'
49
+ | 'anonymous'
50
+ | 'google.com'
51
+ | 'facebook.com'
52
+ | 'github.com'
53
+ | 'twitter.com'
54
+ | 'microsoft.com'
55
+ | 'apple.com' ;
56
+
57
+ export type FirebaseIdToken = {
58
+ // Always set to https://securetoken.google.com/PROJECT_ID
59
+ iss : string ;
60
+
61
+ // Always set to PROJECT_ID
62
+ aud : string ;
63
+
64
+ // The user's unique id
65
+ sub : string ;
66
+
67
+ // The token issue time, in seconds since epoch
68
+ iat : number ;
69
+
70
+ // The token expiry time, normally 'iat' + 3600
71
+ exp : number ;
72
+
73
+ // The user's unique id, must be equal to 'sub'
74
+ user_id : string ;
75
+
76
+ // The time the user authenticated, normally 'iat'
77
+ auth_time : number ;
78
+
79
+ // The sign in provider, only set when the provider is 'anonymous'
80
+ provider_id ?: 'anonymous' ;
81
+
82
+ // The user's primary email
83
+ email ?: string ;
84
+
85
+ // The user's email verification status
86
+ email_verified ?: boolean ;
87
+
88
+ // The user's primary phone number
89
+ phone_number ?: string ;
90
+
91
+ // The user's display name
92
+ name ?: string ;
93
+
94
+ // The user's profile photo URL
95
+ picture ?: string ;
96
+
97
+ // Information on all identities linked to this user
98
+ firebase : {
99
+ // The primary sign-in provider
100
+ sign_in_provider : Provider ;
101
+
102
+ // A map of providers to the user's list of unique identifiers from
103
+ // each provider
104
+ identities ?: { [ provider in Provider ] ?: string [ ] } ;
105
+ } ;
106
+
107
+ // Custom claims set by the developer
108
+ claims ?: object ;
109
+ } ;
110
+
111
+ // To avoid a breaking change, we accept the 'uid' option here, but
112
+ // new users should prefer 'sub' instead.
113
+ export type TokenOptions = Partial < FirebaseIdToken > & { uid ?: string } ;
114
+
115
+ function createUnsecuredJwt ( token : TokenOptions , projectId ?: string ) : string {
46
116
// Unsecured JWTs use "none" as the algorithm.
47
117
const header = {
48
118
alg : 'none' ,
49
- kid : 'fakekid'
119
+ kid : 'fakekid' ,
120
+ type : 'JWT'
50
121
} ;
51
- // Ensure that the auth payload has a value for 'iat'.
52
- ( auth as any ) . iat = ( auth as any ) . iat || 0 ;
53
- // Use `uid` field as a backup when `sub` is missing.
54
- ( auth as any ) . sub = ( auth as any ) . sub || ( auth as any ) . uid ;
55
- if ( ! ( auth as any ) . sub ) {
56
- throw new Error ( "auth must be an object with a 'sub' or 'uid ' field" ) ;
122
+
123
+ const project = projectId || 'fake-project' ;
124
+ const iat = token . iat || 0 ;
125
+ const uid = token . sub || token . uid || token . user_id ;
126
+ if ( ! uid ) {
127
+ throw new Error ( "Auth must contain 'sub', 'uid', or 'user_id ' field! " ) ;
57
128
}
129
+
130
+ // Remove the uid option since it's not actually part of the token spec
131
+ delete token . uid ;
132
+
133
+ const payload : FirebaseIdToken = {
134
+ // Set all required fields to decent defaults
135
+ iss : `https://securetoken.google.com/${ project } ` ,
136
+ aud : project ,
137
+ iat : iat ,
138
+ exp : iat + 3600 ,
139
+ auth_time : iat ,
140
+ sub : uid ,
141
+ user_id : uid ,
142
+ firebase : {
143
+ sign_in_provider : 'custom' ,
144
+ identities : { }
145
+ } ,
146
+
147
+ // Override with user options
148
+ ...token
149
+ } ;
150
+
58
151
// Unsecured JWTs use the empty string as a signature.
59
152
const signature = '' ;
60
153
return [
61
154
base64 . encodeString ( JSON . stringify ( header ) , /*webSafe=*/ false ) ,
62
- base64 . encodeString ( JSON . stringify ( auth ) , /*webSafe=*/ false ) ,
155
+ base64 . encodeString ( JSON . stringify ( payload ) , /*webSafe=*/ false ) ,
63
156
signature
64
157
] . join ( '.' ) ;
65
158
}
@@ -71,15 +164,15 @@ export function apps(): firebase.app.App[] {
71
164
export type AppOptions = {
72
165
databaseName ?: string ;
73
166
projectId ?: string ;
74
- auth ?: object ;
167
+ auth ?: TokenOptions ;
75
168
} ;
76
169
/** Construct an App authenticated with options.auth. */
77
170
export function initializeTestApp ( options : AppOptions ) : firebase . app . App {
78
- return initializeApp (
79
- options . auth ? createUnsecuredJwt ( options . auth ) : undefined ,
80
- options . databaseName ,
81
- options . projectId
82
- ) ;
171
+ const jwt = options . auth
172
+ ? createUnsecuredJwt ( options . auth , options . projectId )
173
+ : undefined ;
174
+
175
+ return initializeApp ( jwt , options . databaseName , options . projectId ) ;
83
176
}
84
177
85
178
export type AdminAppOptions = {
0 commit comments