Skip to content

Commit 49c571b

Browse files
authored
Integration tests for CreateCustomToken and VerifyIdToken (#5)
* Custom token creation API * Updated documentation * Added documentation and code clean up * Improved error handling * new line at eof * Improved error handling: Parsing errors returned by IAM * Reducing the level of indirection in error handling * Added integration tests
1 parent 36822f1 commit 49c571b

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
resources/integration_*
2+
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright 2018, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.Net.Http;
18+
using System.Text;
19+
using System.Threading.Tasks;
20+
using Xunit;
21+
using FirebaseAdmin;
22+
using FirebaseAdmin.Auth;
23+
using Google.Apis.Auth.OAuth2;
24+
using Google.Apis.Util;
25+
26+
namespace FirebaseAdmin.IntegrationTests
27+
{
28+
public class FirebaseAuthTest
29+
{
30+
private const string VerifyCustomTokenUrl =
31+
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken";
32+
33+
public FirebaseAuthTest()
34+
{
35+
IntegrationTestUtils.EnsureDefaultApp();
36+
}
37+
38+
[Fact]
39+
public async Task CreateCustomToken()
40+
{
41+
var customToken = await FirebaseAuth.DefaultInstance
42+
.CreateCustomTokenAsync("testuser");
43+
var idToken = await SignInWithCustomTokenAsync(customToken);
44+
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
45+
Assert.Equal("testuser", decoded.Uid);
46+
}
47+
48+
[Fact]
49+
public async Task CreateCustomTokenWithClaims()
50+
{
51+
var developerClaims = new Dictionary<string, object>()
52+
{
53+
{"admin", true},
54+
{"package", "gold"},
55+
{"magicNumber", 42L},
56+
};
57+
var customToken = await FirebaseAuth.DefaultInstance.CreateCustomTokenAsync(
58+
"testuser", developerClaims);
59+
var idToken = await SignInWithCustomTokenAsync(customToken);
60+
Assert.False(string.IsNullOrEmpty(idToken));
61+
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
62+
Assert.Equal("testuser", decoded.Uid);
63+
foreach (var entry in developerClaims)
64+
{
65+
object value;
66+
Assert.True(decoded.Claims.TryGetValue(entry.Key, out value));
67+
Assert.Equal(entry.Value, value);
68+
}
69+
}
70+
71+
[Fact]
72+
public async Task CreateCustomTokenWithoutServiceAccount()
73+
{
74+
var googleCred = FirebaseApp.DefaultInstance.Options.Credential;
75+
var serviceAcct = (ServiceAccountCredential) googleCred.UnderlyingCredential;
76+
var token = await ((ITokenAccess) googleCred).GetAccessTokenForRequestAsync();
77+
var app = FirebaseApp.Create(new AppOptions()
78+
{
79+
Credential = GoogleCredential.FromAccessToken(token),
80+
ServiceAccountId = serviceAcct.Id,
81+
}, "IAMSignApp");
82+
try
83+
{
84+
var customToken = await FirebaseAuth.GetAuth(app).CreateCustomTokenAsync(
85+
"testuser");
86+
var idToken = await SignInWithCustomTokenAsync(customToken);
87+
var decoded = await FirebaseAuth.DefaultInstance.VerifyIdTokenAsync(idToken);
88+
Assert.Equal("testuser", decoded.Uid);
89+
}
90+
finally
91+
{
92+
app.Delete();
93+
}
94+
}
95+
96+
private static async Task<string> SignInWithCustomTokenAsync(string customToken)
97+
{
98+
var rb = new Google.Apis.Requests.RequestBuilder()
99+
{
100+
Method = Google.Apis.Http.HttpConsts.Post,
101+
BaseUri = new Uri(VerifyCustomTokenUrl),
102+
};
103+
rb.AddParameter(RequestParameterType.Query, "key", IntegrationTestUtils.GetApiKey());
104+
var request = rb.CreateRequest();
105+
var jsonSerializer = Google.Apis.Json.NewtonsoftJsonSerializer.Instance;
106+
var payload = jsonSerializer.Serialize(new SignInRequest{
107+
CustomToken = customToken,
108+
ReturnSecureToken = true,
109+
});
110+
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");
111+
using (var client = new HttpClient())
112+
{
113+
var response = await client.SendAsync(request);
114+
response.EnsureSuccessStatusCode();
115+
var json = await response.Content.ReadAsStringAsync();
116+
var parsed = jsonSerializer.Deserialize<SignInResponse>(json);
117+
return parsed.IdToken;
118+
}
119+
}
120+
}
121+
122+
internal class SignInRequest
123+
{
124+
[Newtonsoft.Json.JsonProperty("token")]
125+
public string CustomToken { get; set; }
126+
127+
[Newtonsoft.Json.JsonProperty("returnSecureToken")]
128+
public bool ReturnSecureToken { get; set; }
129+
}
130+
131+
internal class SignInResponse
132+
{
133+
[Newtonsoft.Json.JsonProperty("idToken")]
134+
public String IdToken { get; set; }
135+
}
136+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2018, Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
using System;
16+
using System.Collections.Generic;
17+
using System.IO;
18+
using FirebaseAdmin;
19+
using Google.Apis.Auth.OAuth2;
20+
using Google.Apis.Json;
21+
22+
namespace FirebaseAdmin.IntegrationTests
23+
{
24+
internal static class IntegrationTestUtils
25+
{
26+
private const string ServiceAccountFile = "./resources/integration_cert.json";
27+
private const string ApiKeyFile = "./resources/integration_apikey.txt";
28+
29+
private static readonly Lazy<FirebaseApp> DefaultFirebaseApp = new Lazy<FirebaseApp>(() => {
30+
var options = new AppOptions()
31+
{
32+
Credential = GoogleCredential.FromFile(ServiceAccountFile),
33+
};
34+
return FirebaseApp.Create(options);
35+
}, true);
36+
37+
public static FirebaseApp EnsureDefaultApp()
38+
{
39+
return DefaultFirebaseApp.Value;
40+
}
41+
42+
public static string GetApiKey()
43+
{
44+
return System.IO.File.ReadAllText(ApiKeyFile).Trim();
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)