File tree Expand file tree Collapse file tree 4 files changed +56
-5
lines changed
FirebaseAdmin.IntegrationTests Expand file tree Collapse file tree 4 files changed +56
-5
lines changed Original file line number Diff line number Diff line change @@ -144,8 +144,16 @@ test suite makes a large number of writes to the Firebase realtime database. Dow
144
144
account key file from the "Settings > Service Accounts" page of the project, and copy it to
145
145
` FirebaseAdmin/FirebaseAdmin.IntegrationTests/resources/integration_cert.json ` . Also obtain the
146
146
API key for the same project from "Settings > General", and save it to
147
- ` FirebaseAdmin/FirebaseAdmin.IntegrationTests/resources/integration_apikey.txt ` . Finally, to run
148
- the integration test suite:
147
+ ` FirebaseAdmin/FirebaseAdmin.IntegrationTests/resources/integration_apikey.txt ` .
148
+
149
+ You'll also need to grant your service account the 'Firebase Authentication Admin' role. This is
150
+ required to ensure that exported user records contain the password hashes of the user accounts:
151
+ 1 . Go to [ Google Cloud Platform Console / IAM & admin] ( https://console.cloud.google.com/iam-admin ) .
152
+ 2 . Find your service account in the list, and click the 'pencil' icon to edit it's permissions.
153
+ 3 . Click 'ADD ANOTHER ROLE' and choose 'Firebase Authentication Admin'.
154
+ 4 . Click 'SAVE'.
155
+
156
+ Finally, to run the integration test suite:
149
157
150
158
``` bash
151
159
$ dotnet test FirebaseAdmin.IntegrationTests
Original file line number Diff line number Diff line change @@ -324,8 +324,15 @@ public async Task ListUsers()
324
324
if ( users . Contains ( uid ) && ! listedUsers . Contains ( uid ) )
325
325
{
326
326
listedUsers . Add ( uid ) ;
327
- Assert . NotNull ( enumerator . Current . PasswordHash ) ;
328
- Assert . NotNull ( enumerator . Current . PasswordSalt ) ;
327
+ var errMsgTemplate = "Missing {0} field. A common cause would be "
328
+ + "forgetting to add the 'Firebase Authentication Admin' permission. "
329
+ + "See instructions in CONTRIBUTING.md" ;
330
+ AssertWithMessage . NotNull (
331
+ enumerator . Current . PasswordHash ,
332
+ string . Format ( errMsgTemplate , "PasswordHash" ) ) ;
333
+ AssertWithMessage . NotNull (
334
+ enumerator . Current . PasswordSalt ,
335
+ string . Format ( errMsgTemplate , "PasswordSalt" ) ) ;
329
336
}
330
337
}
331
338
@@ -365,6 +372,20 @@ private static async Task<string> SignInWithCustomTokenAsync(string customToken)
365
372
}
366
373
}
367
374
375
+ /**
376
+ * Additional Xunit style asserts that allow specifying an error message upon failure.
377
+ */
378
+ internal static class AssertWithMessage
379
+ {
380
+ internal static void NotNull ( object obj , string msg )
381
+ {
382
+ if ( obj == null )
383
+ {
384
+ throw new Xunit . Sdk . XunitException ( "Assert.NotNull() Failure: " + msg ) ;
385
+ }
386
+ }
387
+ }
388
+
368
389
internal class SignInRequest
369
390
{
370
391
[ Newtonsoft . Json . JsonProperty ( "token" ) ]
Original file line number Diff line number Diff line change 14
14
15
15
using System ;
16
16
using System . Collections . Generic ;
17
+ using System . Text ;
17
18
using Xunit ;
18
19
19
20
namespace FirebaseAdmin . Auth . Tests
@@ -151,5 +152,17 @@ public void AllProperties()
151
152
Assert . Equal ( UserRecord . UnixEpoch . AddMilliseconds ( 100 ) , metadata . CreationTimestamp ) ;
152
153
Assert . Equal ( UserRecord . UnixEpoch . AddMilliseconds ( 150 ) , metadata . LastSignInTimestamp ) ;
153
154
}
155
+
156
+ [ Fact ]
157
+ public void RedactedPasswordCleared ( )
158
+ {
159
+ var user = new ExportedUserRecord ( new GetAccountInfoResponse . User ( )
160
+ {
161
+ UserId = "user1" ,
162
+ PasswordHash = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( "REDACTED" ) ) ,
163
+ } ) ;
164
+
165
+ Assert . Null ( user . PasswordHash ) ;
166
+ }
154
167
}
155
168
}
Original file line number Diff line number Diff line change 12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
14
15
+ using System ;
16
+ using System . Text ;
17
+
15
18
namespace FirebaseAdmin . Auth
16
19
{
17
20
/// <summary>
@@ -20,10 +23,16 @@ namespace FirebaseAdmin.Auth
20
23
/// </summary>
21
24
public sealed class ExportedUserRecord : UserRecord
22
25
{
26
+ private static readonly string B64Redacted =
27
+ Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( "REDACTED" ) ) ;
28
+
23
29
internal ExportedUserRecord ( GetAccountInfoResponse . User user )
24
30
: base ( user )
25
31
{
26
- this . PasswordHash = user . PasswordHash ;
32
+ // If the password hash is redacted (probably due to missing permissions) then clear it
33
+ // out, similar to how the salt is returned. (Otherwise, it *looks* like a b64-encoded
34
+ // hash is present, which is confusing.)
35
+ this . PasswordHash = user . PasswordHash == B64Redacted ? null : user . PasswordHash ;
27
36
this . PasswordSalt = user . PasswordSalt ;
28
37
}
29
38
You can’t perform that action at this time.
0 commit comments