Skip to content

Commit 54ce40e

Browse files
authored
Add App Check built in providers (#678)
* Add App Check built in providers * Delete DebugProvider.cs * Address feedback * Update BuiltInProviderWrapper.cs
1 parent b5488d2 commit 54ce40e

7 files changed

+478
-0
lines changed

app_check/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ set(firebase_app_check_src
2929
src/IAppCheckProvider.cs
3030
src/IAppCheckProviderFactory.cs
3131
src/TokenChangedEventArgs.cs
32+
33+
# Built In Providers
34+
src/BuiltInProviderWrapper.cs
35+
src/AppAttestProviderFactory.cs
36+
src/DebugAppCheckProviderFactory.cs
37+
src/DeviceCheckProviderFactory.cs
38+
src/PlayIntegrityProviderFactory.cs
3239
)
3340

3441
if(NOT FIREBASE_UNI_LIBRARY AND APPLE AND NOT IOS)
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
20+
namespace Firebase.AppCheck {
21+
22+
/// Implementation of an IAppCheckProviderFactory that builds
23+
/// providering using the App Attest service. To be used
24+
/// when targeting the iOS platform.
25+
public sealed class AppAttestProviderFactory : IAppCheckProviderFactory {
26+
// The static Factory singleton
27+
private static AppAttestProviderFactory s_factoryInstance;
28+
29+
// The C++ factory that this class wraps
30+
private AppAttestProviderFactoryInternal factoryInternal;
31+
32+
// Map from App names to Providers already created by the factory
33+
private Dictionary<string, BuiltInProviderWrapper> providerMap = new Dictionary<string, BuiltInProviderWrapper>();
34+
35+
// Private constructor as users are meant to use the GetInstance function.
36+
private AppAttestProviderFactory(AppAttestProviderFactoryInternal factoryInternal) {
37+
this.factoryInternal = factoryInternal;
38+
}
39+
40+
private void ThrowIfNull() {
41+
if (factoryInternal == null ||
42+
AppAttestProviderFactoryInternal.getCPtr(factoryInternal).Handle == System.IntPtr.Zero) {
43+
throw new System.NullReferenceException();
44+
}
45+
}
46+
47+
/**
48+
* Gets an instance of this class for installation into a
49+
* FirebaseAppCheck instance.
50+
*/
51+
public static AppAttestProviderFactory GetInstance() {
52+
if (s_factoryInstance != null) {
53+
return s_factoryInstance;
54+
}
55+
56+
// Get the C++ Factory, and wrap it
57+
AppAttestProviderFactoryInternal factoryInternal = AppAttestProviderFactoryInternal.GetInstance();
58+
// The returned factory can be null, if the platform isn't supported.
59+
if (factoryInternal == null) {
60+
throw new FirebaseException((int)AppCheckError.UnsupportedProvider,
61+
"App Attest is only supported on iOS+ platforms.");
62+
}
63+
s_factoryInstance = new AppAttestProviderFactory(factoryInternal);
64+
return s_factoryInstance;
65+
}
66+
67+
/**
68+
* Gets the IAppCheckProvider associated with the given
69+
* FirebaseApp instance, or creates one if none already exists.
70+
*/
71+
public IAppCheckProvider CreateProvider(FirebaseApp app) {
72+
BuiltInProviderWrapper provider;
73+
if (providerMap.TryGetValue(app.Name, out provider)) {
74+
return provider;
75+
}
76+
77+
ThrowIfNull();
78+
AppCheckProviderInternal providerInternal = factoryInternal.CreateProvider(app);
79+
provider = new BuiltInProviderWrapper(providerInternal);
80+
providerMap[app.Name] = provider;
81+
return provider;
82+
}
83+
}
84+
85+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.Threading.Tasks;
20+
21+
namespace Firebase.AppCheck {
22+
23+
internal class BuiltInProviderWrapper : IAppCheckProvider {
24+
25+
private static int s_pendingGetTokenKey = 0;
26+
private static Dictionary<int, TaskCompletionSource<AppCheckToken>> s_pendingGetTokens =
27+
new Dictionary<int, TaskCompletionSource<AppCheckToken>>();
28+
29+
// Function for C++ to call when it needs to finish a GetToken call.
30+
private static AppCheckUtil.CompleteBuiltInGetTokenDelegate completeGetTokenDelegate =
31+
new AppCheckUtil.CompleteBuiltInGetTokenDelegate(CompleteBuiltInGetTokenMethod);
32+
33+
static BuiltInProviderWrapper() {
34+
// Register the callback to complete GetTokens
35+
AppCheckUtil.SetCompleteBuiltInGetTokenCallback(completeGetTokenDelegate);
36+
}
37+
38+
AppCheckProviderInternal providerInternal;
39+
40+
public BuiltInProviderWrapper(AppCheckProviderInternal providerInternal) {
41+
this.providerInternal = providerInternal;
42+
}
43+
44+
private void ThrowIfNull() {
45+
if (providerInternal == null ||
46+
AppCheckProviderInternal.getCPtr(providerInternal).Handle == System.IntPtr.Zero) {
47+
throw new System.NullReferenceException();
48+
}
49+
}
50+
51+
public System.Threading.Tasks.Task<AppCheckToken> GetTokenAsync() {
52+
ThrowIfNull();
53+
54+
int key;
55+
TaskCompletionSource<AppCheckToken> tcs;
56+
lock (s_pendingGetTokens) {
57+
key = s_pendingGetTokenKey++;
58+
tcs = new TaskCompletionSource<AppCheckToken>();
59+
s_pendingGetTokens[key] = tcs;
60+
}
61+
AppCheckUtil.GetTokenFromBuiltInProvider(providerInternal, key);
62+
return tcs.Task;
63+
}
64+
65+
// This is called from the C++ implementation, on the Unity main thread.
66+
private static void CompleteBuiltInGetTokenMethod(int key, System.IntPtr tokenCPtr,
67+
int error, string errorMessage) {
68+
TaskCompletionSource<AppCheckToken> tcs;
69+
lock (s_pendingGetTokens) {
70+
if (!s_pendingGetTokens.TryGetValue(key, out tcs)) {
71+
return;
72+
}
73+
s_pendingGetTokens.Remove(key);
74+
}
75+
76+
if (error == 0) {
77+
// Create the C# object that wraps the Token's C++ pointer, passing false for ownership
78+
// to prevent the cleanup of the C# object from deleting the C++ object when done.
79+
AppCheckTokenInternal tokenInternal = new AppCheckTokenInternal(tokenCPtr, false);
80+
AppCheckToken token = AppCheckToken.FromAppCheckTokenInternal(tokenInternal);
81+
tcs.TrySetResult(token);
82+
} else {
83+
tcs.TrySetException(new FirebaseException(error, errorMessage));
84+
}
85+
}
86+
87+
}
88+
89+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
20+
namespace Firebase.AppCheck {
21+
22+
/// Implementation of an IAppCheckProviderFactory that builds
23+
/// DebugAppCheckProviders.
24+
///
25+
/// DebugAppCheckProvider can exchange a debug token registered in the Firebase
26+
/// console for a Firebase App Check token. The debug provider is designed to
27+
/// enable testing applications on a simulator or test environment.
28+
///
29+
/// NOTE: Do not use the debug provider in applications used by real users.
30+
public sealed class DebugAppCheckProviderFactory : IAppCheckProviderFactory {
31+
// The static Factory singleton
32+
private static DebugAppCheckProviderFactory s_factoryInstance;
33+
34+
// The C++ factory that this class wraps
35+
private DebugAppCheckProviderFactoryInternal factoryInternal;
36+
37+
// Map from App names to Providers already created by the factory
38+
private Dictionary<string, BuiltInProviderWrapper> providerMap = new Dictionary<string, BuiltInProviderWrapper>();
39+
40+
// Private constructor as users are meant to use the GetInstance function.
41+
private DebugAppCheckProviderFactory(DebugAppCheckProviderFactoryInternal factoryInternal) {
42+
this.factoryInternal = factoryInternal;
43+
}
44+
45+
private void ThrowIfNull() {
46+
if (factoryInternal == null ||
47+
DebugAppCheckProviderFactoryInternal.getCPtr(factoryInternal).Handle == System.IntPtr.Zero) {
48+
throw new System.NullReferenceException();
49+
}
50+
}
51+
52+
/**
53+
* Gets an instance of this class for installation into a
54+
* FirebaseAppCheck instance.
55+
*/
56+
public static DebugAppCheckProviderFactory GetInstance() {
57+
if (s_factoryInstance != null) {
58+
return s_factoryInstance;
59+
}
60+
61+
// Get the C++ Factory, and wrap it
62+
DebugAppCheckProviderFactoryInternal factoryInternal = DebugAppCheckProviderFactoryInternal.GetInstance();
63+
s_factoryInstance = new DebugAppCheckProviderFactory(factoryInternal);
64+
return s_factoryInstance;
65+
}
66+
67+
/**
68+
* Gets the IAppCheckProvider associated with the given
69+
* FirebaseApp instance, or creates one if none already exists.
70+
*/
71+
public IAppCheckProvider CreateProvider(FirebaseApp app) {
72+
BuiltInProviderWrapper provider;
73+
if (providerMap.TryGetValue(app.Name, out provider)) {
74+
return provider;
75+
}
76+
77+
ThrowIfNull();
78+
AppCheckProviderInternal providerInternal = factoryInternal.CreateProvider(app);
79+
provider = new BuiltInProviderWrapper(providerInternal);
80+
providerMap[app.Name] = provider;
81+
return provider;
82+
}
83+
}
84+
85+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
20+
namespace Firebase.AppCheck {
21+
22+
/// Implementation of an IAppCheckProviderFactory that builds
23+
/// providering using the Device Check service. To be used
24+
/// when targeting the iOS platform.
25+
public sealed class DeviceCheckProviderFactory : IAppCheckProviderFactory {
26+
// The static Factory singleton
27+
private static DeviceCheckProviderFactory s_factoryInstance;
28+
29+
// The C++ factory that this class wraps
30+
private DeviceCheckProviderFactoryInternal factoryInternal;
31+
32+
// Map from App names to Providers already created by the factory
33+
private Dictionary<string, BuiltInProviderWrapper> providerMap = new Dictionary<string, BuiltInProviderWrapper>();
34+
35+
// Private constructor as users are meant to use the GetInstance function.
36+
private DeviceCheckProviderFactory(DeviceCheckProviderFactoryInternal factoryInternal) {
37+
this.factoryInternal = factoryInternal;
38+
}
39+
40+
private void ThrowIfNull() {
41+
if (factoryInternal == null ||
42+
DeviceCheckProviderFactoryInternal.getCPtr(factoryInternal).Handle == System.IntPtr.Zero) {
43+
throw new System.NullReferenceException();
44+
}
45+
}
46+
47+
/**
48+
* Gets an instance of this class for installation into a
49+
* FirebaseAppCheck instance.
50+
*/
51+
public static DeviceCheckProviderFactory GetInstance() {
52+
if (s_factoryInstance != null) {
53+
return s_factoryInstance;
54+
}
55+
56+
// Get the C++ Factory, and wrap it
57+
DeviceCheckProviderFactoryInternal factoryInternal = DeviceCheckProviderFactoryInternal.GetInstance();
58+
// The returned factory can be null, if the platform isn't supported.
59+
if (factoryInternal == null) {
60+
throw new FirebaseException((int)AppCheckError.UnsupportedProvider,
61+
"Device Check is only supported on iOS+ platforms.");
62+
}
63+
s_factoryInstance = new DeviceCheckProviderFactory(factoryInternal);
64+
return s_factoryInstance;
65+
}
66+
67+
/**
68+
* Gets the IAppCheckProvider associated with the given
69+
* FirebaseApp instance, or creates one if none already exists.
70+
*/
71+
public IAppCheckProvider CreateProvider(FirebaseApp app) {
72+
BuiltInProviderWrapper provider;
73+
if (providerMap.TryGetValue(app.Name, out provider)) {
74+
return provider;
75+
}
76+
77+
ThrowIfNull();
78+
AppCheckProviderInternal providerInternal = factoryInternal.CreateProvider(app);
79+
provider = new BuiltInProviderWrapper(providerInternal);
80+
providerMap[app.Name] = provider;
81+
return provider;
82+
}
83+
}
84+
85+
}

0 commit comments

Comments
 (0)