10 Commits

Author SHA1 Message Date
Patrick McDonagh
2e08234eef Adds search function for list view 2018-06-11 10:21:03 -05:00
Patrick McDonagh
ec2e0b643b Adds SideMenu and company view 2018-06-06 18:39:18 -05:00
Patrick McDonagh
25f862e1c5 Auth system converted to custom token
This allows for the case of when users change their passwords
2018-06-01 15:33:52 -05:00
Patrick McDonagh
80f2241604 Adds firebase auth 2018-06-01 13:36:16 -05:00
Patrick McDonagh
b1b80113c7 Pulls channel history from Firebase, not meshify 2018-06-01 11:29:47 -05:00
Patrick McDonagh
95467f9161 Adds firebase live data
Also no longer crashes when touching something while loading
2018-05-31 19:55:47 -05:00
Patrick McDonagh
c94cdc1369 Code cleanup 2018-05-30 08:56:57 -05:00
Patrick McDonagh
84af67cb1a Refactor to remove redundancies 2018-05-29 20:58:07 -05:00
Patrick McDonagh
53ddf1b15e Adds History Graph for channels 2018-05-29 16:54:16 -05:00
Patrick McDonagh
a6721d172c Enable writing channel values 2018-05-25 15:44:13 -05:00
752 changed files with 103253 additions and 3590 deletions

11
Podfile
View File

@@ -13,13 +13,24 @@ target 'pocloud' do
pod 'RealmSwift'
pod 'PromiseKit/Alamofire'
pod 'Kingfisher'
pod 'SwiftChart'
pod 'Firebase/Core'
pod 'Firebase/Database'
pod 'Firebase/Auth'
pod 'SideMenu'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
config.build_settings['CLANG_WARN_DOCUMENTATION_COMMENTS'] = 'NO'
end
end
installer.pods_project.build_configurations.each do |config|
config.build_settings.delete('CODE_SIGNING_ALLOWED')
config.build_settings.delete('CODE_SIGNING_REQUIRED')
end
end

View File

@@ -3,49 +3,116 @@ PODS:
- ChameleonFramework (2.1.0):
- ChameleonFramework/Default (= 2.1.0)
- ChameleonFramework/Default (2.1.0)
- Firebase/Auth (5.2.0):
- Firebase/CoreOnly
- FirebaseAuth (= 5.0.1)
- Firebase/Core (5.2.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 5.0.1)
- Firebase/CoreOnly (5.2.0):
- FirebaseCore (= 5.0.3)
- Firebase/Database (5.2.0):
- Firebase/CoreOnly
- FirebaseDatabase (= 5.0.1)
- FirebaseAnalytics (5.0.1):
- FirebaseCore (~> 5.0)
- FirebaseInstanceID (~> 3.0)
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- nanopb (~> 0.3)
- FirebaseAuth (5.0.1):
- FirebaseCore (~> 5.0)
- GTMSessionFetcher/Core (~> 1.1)
- FirebaseCore (5.0.3):
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- FirebaseDatabase (5.0.1):
- FirebaseCore (~> 5.0)
- leveldb-library (~> 1.18)
- FirebaseInstanceID (3.1.0):
- FirebaseCore (~> 5.0)
- GoogleToolboxForMac/Defines (2.1.4)
- "GoogleToolboxForMac/NSData+zlib (2.1.4)":
- GoogleToolboxForMac/Defines (= 2.1.4)
- GTMSessionFetcher/Core (1.1.15)
- Kingfisher (4.8.0)
- PromiseKit/Alamofire (6.2.7):
- leveldb-library (1.20)
- nanopb (0.3.8):
- nanopb/decode (= 0.3.8)
- nanopb/encode (= 0.3.8)
- nanopb/decode (0.3.8)
- nanopb/encode (0.3.8)
- PromiseKit/Alamofire (6.2.8):
- Alamofire (~> 4.0)
- PromiseKit/CorePromise
- PromiseKit/CorePromise (6.2.7)
- Realm (3.5.0):
- Realm/Headers (= 3.5.0)
- Realm/Headers (3.5.0)
- RealmSwift (3.5.0):
- Realm (= 3.5.0)
- PromiseKit/CorePromise (6.2.8)
- Realm (3.7.0):
- Realm/Headers (= 3.7.0)
- Realm/Headers (3.7.0)
- RealmSwift (3.7.0):
- Realm (= 3.7.0)
- SideMenu (4.0.0)
- SVProgressHUD (2.2.5)
- SwiftChart (1.0.1)
- SwiftyJSON (4.1.0)
DEPENDENCIES:
- Alamofire
- ChameleonFramework
- Firebase/Auth
- Firebase/Core
- Firebase/Database
- Kingfisher
- PromiseKit/Alamofire
- RealmSwift
- SideMenu
- SVProgressHUD
- SwiftChart
- SwiftyJSON
SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Alamofire
- ChameleonFramework
- Firebase
- FirebaseAnalytics
- FirebaseAuth
- FirebaseCore
- FirebaseDatabase
- FirebaseInstanceID
- GoogleToolboxForMac
- GTMSessionFetcher
- Kingfisher
- leveldb-library
- nanopb
- PromiseKit
- Realm
- RealmSwift
- SideMenu
- SVProgressHUD
- SwiftChart
- SwiftyJSON
SPEC CHECKSUMS:
Alamofire: e4fa87002c137ba2d8d634d2c51fabcda0d5c223
ChameleonFramework: d21a3cc247abfe5e37609a283a8238b03575cf64
Firebase: 25ed0412036d7d008568d1fb4d2e9d81ea8a0a2c
FirebaseAnalytics: b3628aea54c50464c32c393fb2ea032566e7ecc2
FirebaseAuth: 463b8ce33bd5d05f706dcd4615499e3212b4132b
FirebaseCore: a3c87242451633fff8490183898075ce77d168d2
FirebaseDatabase: 482bad9c2abd422bb2321194fb8c937e67426a89
FirebaseInstanceID: 05d779cbb97bd5bd5c51a38a903fc9cfe1b2454a
GoogleToolboxForMac: 91c824d21e85b31c2aae9bb011c5027c9b4e738f
GTMSessionFetcher: 5fa5b80fd20e439ef5f545fb2cb3ca6c6714caa2
Kingfisher: 976d828df2b24834c6a3f2fc4d82cdbd26552be1
PromiseKit: 12b9d87748b170714247d8b2677146ca57e488f2
Realm: 0378021c424e4e2bd6a0e63b27881e929d9b9ad1
RealmSwift: 3322562622fda2ad596985ead4d8d8be30cf838c
leveldb-library: 08cba283675b7ed2d99629a4bc5fd052cd2bb6a5
nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3
PromiseKit: 6788ce1a0ed5448b83d4aaf56b9fc49fb7647d32
Realm: 4998c6ced1ea15b3792f273b18f8e6faaf935b5c
RealmSwift: 7dc2ab780b9742a1fc7469b2e4776b9773e2e825
SideMenu: 70ee5657df63ec3382660ec4ef470bf1cf5db07d
SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
SwiftChart: ba767a678d568a5ee22d419e146a0582865e1aff
SwiftyJSON: c29297daf073d2aa016295d5809cdd68045c39b3
PODFILE CHECKSUM: 71fcda130d0048fb76ddc9524fd4cdd1df1a0e6f
PODFILE CHECKSUM: f920b0139378aa95335e4e152b9daa8cfaf65705
COCOAPODS: 1.5.2
COCOAPODS: 1.5.3

101
Pods/Firebase/CoreOnly/Sources/Firebase.h generated Executable file
View File

@@ -0,0 +1,101 @@
#import <FirebaseCore/FirebaseCore.h>
#if !defined(__has_include)
#error "Firebase.h won't import anything if your compiler doesn't support __has_include. Please \
import the headers individually."
#else
#if __has_include(<FirebaseAnalytics/FirebaseAnalytics.h>)
#import <FirebaseAnalytics/FirebaseAnalytics.h>
#else
#ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
#warning "FirebaseAnalytics.framework is not included in your target. Please add \
`Firebase/Core` to your Podfile or add FirebaseAnalytics.framework to your project to ensure \
Firebase services work as intended."
#endif // #ifndef FIREBASE_ANALYTICS_SUPPRESS_WARNING
#endif
#if __has_include(<FirebaseAuth/FirebaseAuth.h>)
#import <FirebaseAuth/FirebaseAuth.h>
#endif
#if __has_include(<FirebaseCrash/FirebaseCrash.h>)
#import <FirebaseCrash/FirebaseCrash.h>
#endif
#if __has_include(<FirebaseDatabase/FirebaseDatabase.h>)
#import <FirebaseDatabase/FirebaseDatabase.h>
#endif
#if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
#import <FirebaseDynamicLinks/FirebaseDynamicLinks.h>
#endif
#if __has_include(<FirebaseFirestore/FirebaseFirestore.h>)
#import <FirebaseFirestore/FirebaseFirestore.h>
#endif
#if __has_include(<FirebaseFunctions/FirebaseFunctions.h>)
#import <FirebaseFunctions/FirebaseFunctions.h>
#endif
#if __has_include(<FirebaseInstanceID/FirebaseInstanceID.h>)
#import <FirebaseInstanceID/FirebaseInstanceID.h>
#endif
#if __has_include(<FirebaseInvites/FirebaseInvites.h>)
#import <FirebaseInvites/FirebaseInvites.h>
#endif
#if __has_include(<FirebaseMessaging/FirebaseMessaging.h>)
#import <FirebaseMessaging/FirebaseMessaging.h>
#endif
#if __has_include(<FirebaseMLModelInterpreter/FirebaseMLModelInterpreter.h>)
#import <FirebaseMLModelInterpreter/FirebaseMLModelInterpreter.h>
#endif
#if __has_include(<FirebaseMLVision/FirebaseMLVision.h>)
#import <FirebaseMLVision/FirebaseMLVision.h>
#endif
#if __has_include(<FirebaseMLVisionBarcodeModel/FirebaseMLVisionBarcodeModel.h>)
#import <FirebaseMLVisionBarcodeModel/FirebaseMLVisionBarcodeModel.h>
#endif
#if __has_include(<FirebaseMLVisionFaceModel/FirebaseMLVisionFaceModel.h>)
#import <FirebaseMLVisionFaceModel/FirebaseMLVisionFaceModel.h>
#endif
#if __has_include(<FirebaseMLVisionLabelModel/FirebaseMLVisionLabelModel.h>)
#import <FirebaseMLVisionLabelModel/FirebaseMLVisionLabelModel.h>
#endif
#if __has_include(<FirebaseMLVisionTextModel/FirebaseMLVisionTextModel.h>)
#import <FirebaseMLVisionTextModel/FirebaseMLVisionTextModel.h>
#endif
#if __has_include(<FirebasePerformance/FirebasePerformance.h>)
#import <FirebasePerformance/FirebasePerformance.h>
#endif
#if __has_include(<FirebaseRemoteConfig/FirebaseRemoteConfig.h>)
#import <FirebaseRemoteConfig/FirebaseRemoteConfig.h>
#endif
#if __has_include(<FirebaseStorage/FirebaseStorage.h>)
#import <FirebaseStorage/FirebaseStorage.h>
#endif
#if __has_include(<GoogleMobileAds/GoogleMobileAds.h>)
#import <GoogleMobileAds/GoogleMobileAds.h>
#endif
#if __has_include(<Fabric/Fabric.h>)
#import <Fabric/Fabric.h>
#endif
#if __has_include(<Crashlytics/Crashlytics.h>)
#import <Crashlytics/Crashlytics.h>
#endif
#endif // defined(__has_include)

View File

@@ -0,0 +1,4 @@
module Firebase {
export *
header "Firebase.h"
}

87
Pods/Firebase/README.md generated Executable file
View File

@@ -0,0 +1,87 @@
# Firebase APIs for iOS
Simplify your iOS development, grow your user base, and monetize more
effectively with Firebase services.
Much more information can be found at [https://firebase.google.com](https://firebase.google.com).
## Install a Firebase SDK using CocoaPods
Firebase distributes several iOS specific APIs and SDKs via CocoaPods.
You can install the CocoaPods tool on OS X by running the following command from
the terminal. Detailed information is available in the [Getting Started
guide](https://guides.cocoapods.org/using/getting-started.html#getting-started).
```
$ sudo gem install cocoapods
```
## Try out an SDK
You can try any of the SDKs with `pod try`. Run the following command and select
the SDK you are interested in when prompted:
```
$ pod try Firebase
```
Note that some SDKs may require credentials. More information is available in
the SDK-specific documentation at [https://firebase.google.com/docs/](https://firebase.google.com/docs/).
## Add a Firebase SDK to your iOS app
CocoaPods is used to install and manage dependencies in existing Xcode projects.
1. Create an Xcode project, and save it to your local machine.
2. Create a file named `Podfile` in your project directory. This file defines
your project's dependencies, and is commonly referred to as a Podspec.
3. Open `Podfile`, and add your dependencies. A simple Podspec is shown here:
```
platform :ios, '8.0'
pod 'Firebase'
```
4. Save the file.
5. Open a terminal and `cd` to the directory containing the Podfile.
```
$ cd <path-to-project>/project/
```
6. Run the `pod install` command. This will install the SDKs specified in the
Podspec, along with any dependencies they may have.
```
$ pod install
```
7. Open your app's `.xcworkspace` file to launch Xcode. Use this file for all
development on your app.
8. You can also install other Firebase SDKs by adding the subspecs in the
Podfile.
```
pod 'Firebase/AdMob'
pod 'Firebase/Analytics'
pod 'Firebase/Auth'
pod 'Firebase/Crash'
pod 'Firebase/Database'
pod 'Firebase/DynamicLinks'
pod 'Firebase/Firestore'
pod 'Firebase/Functions'
pod 'Firebase/Invites'
pod 'Firebase/Messaging'
pod 'Firebase/MLCommon'
pod 'Firebase/MLModelInterpreter'
pod 'Firebase/MLVision'
pod 'Firebase/MLVisionBarcodeModel'
pod 'Firebase/MLVisionFaceModel'
pod 'Firebase/MLVisionLabelModel'
pod 'Firebase/MLVisionTextModel'
pod 'Firebase/Performance'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage'
```

View File

@@ -0,0 +1,62 @@
#import <Foundation/Foundation.h>
#import "FIRAnalytics.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Provides App Delegate handlers to be used in your App Delegate.
*
* To save time integrating Firebase Analytics in an application, Firebase Analytics does not
* require delegation implementation from the AppDelegate. Instead this is automatically done by
* Firebase Analytics. Should you choose instead to delegate manually, you can turn off the App
* Delegate Proxy by adding FirebaseAppDelegateProxyEnabled into your app's Info.plist and setting
* it to NO, and adding the methods in this category to corresponding delegation handlers.
*
* To handle Universal Links, you must return YES in
* [UIApplicationDelegate application:didFinishLaunchingWithOptions:].
*/
@interface FIRAnalytics (AppDelegate)
/**
* Handles events related to a URL session that are waiting to be processed.
*
* For optimal use of Firebase Analytics, call this method from the
* [UIApplicationDelegate application:handleEventsForBackgroundURLSession:completionHandler]
* method of the app delegate in your app.
*
* @param identifier The identifier of the URL session requiring attention.
* @param completionHandler The completion handler to call when you finish processing the events.
* Calling this completion handler lets the system know that your app's user interface is
* updated and a new snapshot can be taken.
*/
+ (void)handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(nullable void (^)(void))completionHandler;
/**
* Handles the event when the app is launched by a URL.
*
* Call this method from [UIApplicationDelegate application:openURL:options:] &#40;on iOS 9.0 and
* above&#41;, or [UIApplicationDelegate application:openURL:sourceApplication:annotation:] &#40;on
* iOS 8.x and below&#41; in your app.
*
* @param url The URL resource to open. This resource can be a network resource or a file.
*/
+ (void)handleOpenURL:(NSURL *)url;
/**
* Handles the event when the app receives data associated with user activity that includes a
* Universal Link (on iOS 9.0 and above).
*
* Call this method from [UIApplication continueUserActivity:restorationHandler:] in your app
* delegate (on iOS 9.0 and above).
*
* @param userActivity The activity object containing the data associated with the task the user
* was performing.
*/
+ (void)handleUserActivity:(id)userActivity;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,119 @@
#import <Foundation/Foundation.h>
#import "FIREventNames.h"
#import "FIRParameterNames.h"
#import "FIRUserPropertyNames.h"
NS_ASSUME_NONNULL_BEGIN
/// The top level Firebase Analytics singleton that provides methods for logging events and setting
/// user properties. See <a href="http://goo.gl/gz8SLz">the developer guides</a> for general
/// information on using Firebase Analytics in your apps.
NS_SWIFT_NAME(Analytics)
@interface FIRAnalytics : NSObject
/// Logs an app event. The event can have up to 25 parameters. Events with the same name must have
/// the same parameters. Up to 500 event names are supported. Using predefined events and/or
/// parameters is recommended for optimal reporting.
///
/// The following event names are reserved and cannot be used:
/// <ul>
/// <li>ad_activeview</li>
/// <li>ad_click</li>
/// <li>ad_exposure</li>
/// <li>ad_impression</li>
/// <li>ad_query</li>
/// <li>adunit_exposure</li>
/// <li>app_clear_data</li>
/// <li>app_remove</li>
/// <li>app_update</li>
/// <li>error</li>
/// <li>first_open</li>
/// <li>in_app_purchase</li>
/// <li>notification_dismiss</li>
/// <li>notification_foreground</li>
/// <li>notification_open</li>
/// <li>notification_receive</li>
/// <li>os_update</li>
/// <li>screen_view</li>
/// <li>session_start</li>
/// <li>user_engagement</li>
/// </ul>
///
/// @param name The name of the event. Should contain 1 to 40 alphanumeric characters or
/// underscores. The name must start with an alphabetic character. Some event names are
/// reserved. See FIREventNames.h for the list of reserved event names. The "firebase_",
/// "google_", and "ga_" prefixes are reserved and should not be used. Note that event names are
/// case-sensitive and that logging two events whose names differ only in case will result in
/// two distinct events.
/// @param parameters The dictionary of event parameters. Passing nil indicates that the event has
/// no parameters. Parameter names can be up to 40 characters long and must start with an
/// alphabetic character and contain only alphanumeric characters and underscores. Only NSString
/// and NSNumber (signed 64-bit integer and 64-bit floating-point number) parameter types are
/// supported. NSString parameter values can be up to 100 characters long. The "firebase_",
/// "google_", and "ga_" prefixes are reserved and should not be used for parameter names.
+ (void)logEventWithName:(NSString *)name
parameters:(nullable NSDictionary<NSString *, id> *)parameters
NS_SWIFT_NAME(logEvent(_:parameters:));
/// Sets a user property to a given value. Up to 25 user property names are supported. Once set,
/// user property values persist throughout the app lifecycle and across sessions.
///
/// The following user property names are reserved and cannot be used:
/// <ul>
/// <li>first_open_time</li>
/// <li>last_deep_link_referrer</li>
/// <li>user_id</li>
/// </ul>
///
/// @param value The value of the user property. Values can be up to 36 characters long. Setting the
/// value to nil removes the user property.
/// @param name The name of the user property to set. Should contain 1 to 24 alphanumeric characters
/// or underscores and must start with an alphabetic character. The "firebase_", "google_", and
/// "ga_" prefixes are reserved and should not be used for user property names.
+ (void)setUserPropertyString:(nullable NSString *)value forName:(NSString *)name
NS_SWIFT_NAME(setUserProperty(_:forName:));
/// Sets the user ID property. This feature must be used in accordance with
/// <a href="https://www.google.com/policies/privacy">Google's Privacy Policy</a>
///
/// @param userID The user ID to ascribe to the user of this app on this device, which must be
/// non-empty and no more than 256 characters long. Setting userID to nil removes the user ID.
+ (void)setUserID:(nullable NSString *)userID;
/// Sets the current screen name, which specifies the current visual context in your app. This helps
/// identify the areas in your app where users spend their time and how they interact with your app.
/// Must be called on the main thread.
///
/// Note that screen reporting is enabled automatically and records the class name of the current
/// UIViewController for you without requiring you to call this method. If you implement
/// viewDidAppear in your UIViewController but do not call [super viewDidAppear:], that screen class
/// will not be automatically tracked. The class name can optionally be overridden by calling this
/// method in the viewDidAppear callback of your UIViewController and specifying the
/// screenClassOverride parameter. setScreenName:screenClass: must be called after
/// [super viewDidAppear:].
///
/// If your app does not use a distinct UIViewController for each screen, you should call this
/// method and specify a distinct screenName each time a new screen is presented to the user.
///
/// The screen name and screen class remain in effect until the current UIViewController changes or
/// a new call to setScreenName:screenClass: is made.
///
/// @param screenName The name of the current screen. Should contain 1 to 100 characters. Set to nil
/// to clear the current screen name.
/// @param screenClassOverride The name of the screen class. Should contain 1 to 100 characters. By
/// default this is the class name of the current UIViewController. Set to nil to revert to the
/// default class name.
+ (void)setScreenName:(nullable NSString *)screenName
screenClass:(nullable NSString *)screenClassOverride;
/// The unique ID for this instance of the application.
+ (NSString *)appInstanceID;
/// Clears all analytics data for this instance from the device and resets the app instance ID.
/// FIRAnalyticsConfiguration values will be reset to the default values.
+ (void)resetAnalyticsData;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,13 @@
#ifndef FIR_SWIFT_NAME
#import <Foundation/Foundation.h>
// NS_SWIFT_NAME can only translate factory methods before the iOS 9.3 SDK.
// Wrap it in our own macro if it's a non-compatible SDK.
#ifdef __IPHONE_9_3
#define FIR_SWIFT_NAME(X) NS_SWIFT_NAME(X)
#else
#define FIR_SWIFT_NAME(X) // Intentionally blank.
#endif // #ifdef __IPHONE_9_3
#endif // FIR_SWIFT_NAME

View File

@@ -0,0 +1,407 @@
/// @file FIREventNames.h
///
/// Predefined event names.
///
/// An Event is an important occurrence in your app that you want to measure. You can report up to
/// 500 different types of Events per app and you can associate up to 25 unique parameters with each
/// Event type. Some common events are suggested below, but you may also choose to specify custom
/// Event types that are associated with your specific app. Each event type is identified by a
/// unique name. Event names can be up to 40 characters long, may only contain alphanumeric
/// characters and underscores ("_"), and must start with an alphabetic character. The "firebase_",
/// "google_", and "ga_" prefixes are reserved and should not be used.
#import <Foundation/Foundation.h>
/// Add Payment Info event. This event signifies that a user has submitted their payment information
/// to your app.
static NSString *const kFIREventAddPaymentInfo NS_SWIFT_NAME(AnalyticsEventAddPaymentInfo) =
@"add_payment_info";
/// E-Commerce Add To Cart event. This event signifies that an item was added to a cart for
/// purchase. Add this event to a funnel with kFIREventEcommercePurchase to gauge the effectiveness
/// of your checkout process. Note: If you supply the @c kFIRParameterValue parameter, you must
/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
/// accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
/// <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventAddToCart NS_SWIFT_NAME(AnalyticsEventAddToCart) = @"add_to_cart";
/// E-Commerce Add To Wishlist event. This event signifies that an item was added to a wishlist.
/// Use this event to identify popular gift items in your app. Note: If you supply the
/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency
/// parameter so that revenue metrics can be computed accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
/// <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// </ul>
static NSString *const kFIREventAddToWishlist NS_SWIFT_NAME(AnalyticsEventAddToWishlist) =
@"add_to_wishlist";
/// App Open event. By logging this event when an App becomes active, developers can understand how
/// often users leave and return during the course of a Session. Although Sessions are automatically
/// reported, this event can provide further clarification around the continuous engagement of
/// app-users.
static NSString *const kFIREventAppOpen NS_SWIFT_NAME(AnalyticsEventAppOpen) = @"app_open";
/// E-Commerce Begin Checkout event. This event signifies that a user has begun the process of
/// checking out. Add this event to a funnel with your kFIREventEcommercePurchase event to gauge the
/// effectiveness of your checkout process. Note: If you supply the @c kFIRParameterValue
/// parameter, you must also supply the @c kFIRParameterCurrency parameter so that revenue
/// metrics can be computed accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
/// for travel bookings</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
/// </ul>
static NSString *const kFIREventBeginCheckout NS_SWIFT_NAME(AnalyticsEventBeginCheckout) =
@"begin_checkout";
/// Campaign Detail event. Log this event to supply the referral details of a re-engagement
/// campaign. Note: you must supply at least one of the required parameters kFIRParameterSource,
/// kFIRParameterMedium or kFIRParameterCampaign. Params:
///
/// <ul>
/// <li>@c kFIRParameterSource (NSString)</li>
/// <li>@c kFIRParameterMedium (NSString)</li>
/// <li>@c kFIRParameterCampaign (NSString)</li>
/// <li>@c kFIRParameterTerm (NSString) (optional)</li>
/// <li>@c kFIRParameterContent (NSString) (optional)</li>
/// <li>@c kFIRParameterAdNetworkClickID (NSString) (optional)</li>
/// <li>@c kFIRParameterCP1 (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventCampaignDetails NS_SWIFT_NAME(AnalyticsEventCampaignDetails) =
@"campaign_details";
/// Checkout progress. Params:
///
/// <ul>
/// <li>@c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterCheckoutOption (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventCheckoutProgress NS_SWIFT_NAME(AnalyticsEventCheckoutProgress) =
@"checkout_progress";
/// Earn Virtual Currency event. This event tracks the awarding of virtual currency in your app. Log
/// this along with @c kFIREventSpendVirtualCurrency to better understand your virtual economy.
/// Params:
///
/// <ul>
/// <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
/// <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
/// </ul>
static NSString *const kFIREventEarnVirtualCurrency
NS_SWIFT_NAME(AnalyticsEventEarnVirtualCurrency) = @"earn_virtual_currency";
/// E-Commerce Purchase event. This event signifies that an item was purchased by a user. Note:
/// This is different from the in-app purchase event, which is reported automatically for App
/// Store-based apps. Note: If you supply the @c kFIRParameterValue parameter, you must also
/// supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
/// accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
/// <li>@c kFIRParameterTax (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterShipping (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCoupon (NSString) (optional)</li>
/// <li>@c kFIRParameterLocation (NSString) (optional)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
/// for travel bookings</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
/// </ul>
static NSString *const kFIREventEcommercePurchase NS_SWIFT_NAME(AnalyticsEventEcommercePurchase) =
@"ecommerce_purchase";
/// Generate Lead event. Log this event when a lead has been generated in the app to understand the
/// efficacy of your install and re-engagement campaigns. Note: If you supply the
/// @c kFIRParameterValue parameter, you must also supply the @c kFIRParameterCurrency
/// parameter so that revenue metrics can be computed accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// </ul>
static NSString *const kFIREventGenerateLead NS_SWIFT_NAME(AnalyticsEventGenerateLead) =
@"generate_lead";
/// Join Group event. Log this event when a user joins a group such as a guild, team or family. Use
/// this event to analyze how popular certain groups or social features are in your app. Params:
///
/// <ul>
/// <li>@c kFIRParameterGroupID (NSString)</li>
/// </ul>
static NSString *const kFIREventJoinGroup NS_SWIFT_NAME(AnalyticsEventJoinGroup) = @"join_group";
/// Level Up event. This event signifies that a player has leveled up in your gaming app. It can
/// help you gauge the level distribution of your userbase and help you identify certain levels that
/// are difficult to pass. Params:
///
/// <ul>
/// <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterCharacter (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventLevelUp NS_SWIFT_NAME(AnalyticsEventLevelUp) = @"level_up";
/// Login event. Apps with a login feature can report this event to signify that a user has logged
/// in.
static NSString *const kFIREventLogin NS_SWIFT_NAME(AnalyticsEventLogin) = @"login";
/// Post Score event. Log this event when the user posts a score in your gaming app. This event can
/// help you understand how users are actually performing in your game and it can help you correlate
/// high scores with certain audiences or behaviors. Params:
///
/// <ul>
/// <li>@c kFIRParameterScore (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterLevel (signed 64-bit integer as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCharacter (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventPostScore NS_SWIFT_NAME(AnalyticsEventPostScore) = @"post_score";
/// Present Offer event. This event signifies that the app has presented a purchase offer to a user.
/// Add this event to a funnel with the kFIREventAddToCart and kFIREventEcommercePurchase to gauge
/// your conversion process. Note: If you supply the @c kFIRParameterValue parameter, you must
/// also supply the @c kFIRParameterCurrency parameter so that revenue metrics can be computed
/// accurately. Params:
///
/// <ul>
/// <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
/// <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// </ul>
static NSString *const kFIREventPresentOffer NS_SWIFT_NAME(AnalyticsEventPresentOffer) =
@"present_offer";
/// E-Commerce Purchase Refund event. This event signifies that an item purchase was refunded.
/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
/// Params:
///
/// <ul>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterTransactionID (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventPurchaseRefund NS_SWIFT_NAME(AnalyticsEventPurchaseRefund) =
@"purchase_refund";
/// Remove from cart event. Params:
///
/// <ul>
/// <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
/// <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// </ul>
static NSString *const kFIREventRemoveFromCart NS_SWIFT_NAME(AnalyticsEventRemoveFromCart) =
@"remove_from_cart";
/// Search event. Apps that support search features can use this event to contextualize search
/// operations by supplying the appropriate, corresponding parameters. This event can help you
/// identify the most popular content in your app. Params:
///
/// <ul>
/// <li>@c kFIRParameterSearchTerm (NSString)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
/// hotel bookings</li>
/// <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
/// for travel bookings</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
/// </ul>
static NSString *const kFIREventSearch NS_SWIFT_NAME(AnalyticsEventSearch) = @"search";
/// Select Content event. This general purpose event signifies that a user has selected some content
/// of a certain type in an app. The content can be any object in your app. This event can help you
/// identify popular content and categories of content in your app. Params:
///
/// <ul>
/// <li>@c kFIRParameterContentType (NSString)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// </ul>
static NSString *const kFIREventSelectContent NS_SWIFT_NAME(AnalyticsEventSelectContent) =
@"select_content";
/// Set checkout option. Params:
///
/// <ul>
/// <li>@c kFIRParameterCheckoutStep (unsigned 64-bit integer as NSNumber)</li>
/// <li>@c kFIRParameterCheckoutOption (NSString)</li>
/// </ul>
static NSString *const kFIREventSetCheckoutOption NS_SWIFT_NAME(AnalyticsEventSetCheckoutOption) =
@"set_checkout_option";
/// Share event. Apps with social features can log the Share event to identify the most viral
/// content. Params:
///
/// <ul>
/// <li>@c kFIRParameterContentType (NSString)</li>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// </ul>
static NSString *const kFIREventShare NS_SWIFT_NAME(AnalyticsEventShare) = @"share";
/// Sign Up event. This event indicates that a user has signed up for an account in your app. The
/// parameter signifies the method by which the user signed up. Use this event to understand the
/// different behaviors between logged in and logged out users. Params:
///
/// <ul>
/// <li>@c kFIRParameterSignUpMethod (NSString)</li>
/// </ul>
static NSString *const kFIREventSignUp NS_SWIFT_NAME(AnalyticsEventSignUp) = @"sign_up";
/// Spend Virtual Currency event. This event tracks the sale of virtual goods in your app and can
/// help you identify which virtual goods are the most popular objects of purchase. Params:
///
/// <ul>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterVirtualCurrencyName (NSString)</li>
/// <li>@c kFIRParameterValue (signed 64-bit integer or double as NSNumber)</li>
/// </ul>
static NSString *const kFIREventSpendVirtualCurrency
NS_SWIFT_NAME(AnalyticsEventSpendVirtualCurrency) = @"spend_virtual_currency";
/// Tutorial Begin event. This event signifies the start of the on-boarding process in your app. Use
/// this in a funnel with kFIREventTutorialComplete to understand how many users complete this
/// process and move on to the full app experience.
static NSString *const kFIREventTutorialBegin NS_SWIFT_NAME(AnalyticsEventTutorialBegin) =
@"tutorial_begin";
/// Tutorial End event. Use this event to signify the user's completion of your app's on-boarding
/// process. Add this to a funnel with kFIREventTutorialBegin to gauge the completion rate of your
/// on-boarding process.
static NSString *const kFIREventTutorialComplete NS_SWIFT_NAME(AnalyticsEventTutorialComplete) =
@"tutorial_complete";
/// Unlock Achievement event. Log this event when the user has unlocked an achievement in your
/// game. Since achievements generally represent the breadth of a gaming experience, this event can
/// help you understand how many users are experiencing all that your game has to offer. Params:
///
/// <ul>
/// <li>@c kFIRParameterAchievementID (NSString)</li>
/// </ul>
static NSString *const kFIREventUnlockAchievement NS_SWIFT_NAME(AnalyticsEventUnlockAchievement) =
@"unlock_achievement";
/// View Item event. This event signifies that some content was shown to the user. This content may
/// be a product, a webpage or just a simple image or text. Use the appropriate parameters to
/// contextualize the event. Use this event to discover the most popular items viewed in your app.
/// Note: If you supply the @c kFIRParameterValue parameter, you must also supply the
/// @c kFIRParameterCurrency parameter so that revenue metrics can be computed accurately.
/// Params:
///
/// <ul>
/// <li>@c kFIRParameterItemID (NSString)</li>
/// <li>@c kFIRParameterItemName (NSString)</li>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// <li>@c kFIRParameterItemLocationID (NSString) (optional)</li>
/// <li>@c kFIRParameterPrice (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterQuantity (signed 64-bit integer as NSNumber) (optional)</li>
/// <li>@c kFIRParameterCurrency (NSString) (optional)</li>
/// <li>@c kFIRParameterValue (double as NSNumber) (optional)</li>
/// <li>@c kFIRParameterStartDate (NSString) (optional)</li>
/// <li>@c kFIRParameterEndDate (NSString) (optional)</li>
/// <li>@c kFIRParameterFlightNumber (NSString) (optional) for travel bookings</li>
/// <li>@c kFIRParameterNumberOfPassengers (signed 64-bit integer as NSNumber) (optional)
/// for travel bookings</li>
/// <li>@c kFIRParameterNumberOfNights (signed 64-bit integer as NSNumber) (optional) for
/// travel bookings</li>
/// <li>@c kFIRParameterNumberOfRooms (signed 64-bit integer as NSNumber) (optional) for
/// travel bookings</li>
/// <li>@c kFIRParameterOrigin (NSString) (optional)</li>
/// <li>@c kFIRParameterDestination (NSString) (optional)</li>
/// <li>@c kFIRParameterSearchTerm (NSString) (optional) for travel bookings</li>
/// <li>@c kFIRParameterTravelClass (NSString) (optional) for travel bookings</li>
/// </ul>
static NSString *const kFIREventViewItem NS_SWIFT_NAME(AnalyticsEventViewItem) = @"view_item";
/// View Item List event. Log this event when the user has been presented with a list of items of a
/// certain category. Params:
///
/// <ul>
/// <li>@c kFIRParameterItemCategory (NSString)</li>
/// </ul>
static NSString *const kFIREventViewItemList NS_SWIFT_NAME(AnalyticsEventViewItemList) =
@"view_item_list";
/// View Search Results event. Log this event when the user has been presented with the results of a
/// search. Params:
///
/// <ul>
/// <li>@c kFIRParameterSearchTerm (NSString)</li>
/// </ul>
static NSString *const kFIREventViewSearchResults NS_SWIFT_NAME(AnalyticsEventViewSearchResults) =
@"view_search_results";
/// Level Start event. Log this event when the user starts a new level. Params:
///
/// <ul>
/// <li>@c kFIRParameterLevelName (NSString)</li>
/// </ul>
static NSString *const kFIREventLevelStart NS_SWIFT_NAME(AnalyticsEventLevelStart) =
@"level_start";
/// Level End event. Log this event when the user finishes a level. Params:
///
/// <ul>
/// <li>@c kFIRParameterLevelName (NSString)</li>
/// <li>@c kFIRParameterSuccess (NSString)</li>
/// </ul>
static NSString *const kFIREventLevelEnd NS_SWIFT_NAME(AnalyticsEventLevelEnd) = @"level_end";

View File

@@ -0,0 +1,507 @@
/// @file FIRParameterNames.h
///
/// Predefined event parameter names.
///
/// Params supply information that contextualize Events. You can associate up to 25 unique Params
/// with each Event type. Some Params are suggested below for certain common Events, but you are
/// not limited to these. You may supply extra Params for suggested Events or custom Params for
/// Custom events. Param names can be up to 40 characters long, may only contain alphanumeric
/// characters and underscores ("_"), and must start with an alphabetic character. Param values can
/// be up to 100 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and
/// should not be used.
#import <Foundation/Foundation.h>
/// Game achievement ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterAchievementID : @"10_matches_won",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterAchievementID NS_SWIFT_NAME(AnalyticsParameterAchievementID) =
@"achievement_id";
/// Ad Network Click ID (NSString). Used for network-specific click IDs which vary in format.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterAdNetworkClickID : @"1234567",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterAdNetworkClickID
NS_SWIFT_NAME(AnalyticsParameterAdNetworkClickID) = @"aclid";
/// The store or affiliation from which this transaction occurred (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterAffiliation : @"Google Store",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterAffiliation NS_SWIFT_NAME(AnalyticsParameterAffiliation) =
@"affiliation";
/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to
/// capture campaign information, otherwise can be populated by developer. Highly Recommended
/// (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCampaign : @"winter_promotion",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) =
@"campaign";
/// Character used in game (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCharacter : @"beat_boss",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCharacter NS_SWIFT_NAME(AnalyticsParameterCharacter) =
@"character";
/// The checkout step (1..N) (unsigned 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCheckoutStep : @"1",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCheckoutStep NS_SWIFT_NAME(AnalyticsParameterCheckoutStep) =
@"checkout_step";
/// Some option on a step in an ecommerce flow (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCheckoutOption : @"Visa",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCheckoutOption
NS_SWIFT_NAME(AnalyticsParameterCheckoutOption) = @"checkout_option";
/// Campaign content (NSString).
static NSString *const kFIRParameterContent NS_SWIFT_NAME(AnalyticsParameterContent) = @"content";
/// Type of content selected (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterContentType : @"news article",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterContentType NS_SWIFT_NAME(AnalyticsParameterContentType) =
@"content_type";
/// Coupon code for a purchasable item (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCoupon : @"zz123",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCoupon NS_SWIFT_NAME(AnalyticsParameterCoupon) = @"coupon";
/// Campaign custom parameter (NSString). Used as a method of capturing custom data in a campaign.
/// Use varies by network.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCP1 : @"custom_data",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCP1 NS_SWIFT_NAME(AnalyticsParameterCP1) = @"cp1";
/// The name of a creative used in a promotional spot (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCreativeName : @"Summer Sale",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCreativeName NS_SWIFT_NAME(AnalyticsParameterCreativeName) =
@"creative_name";
/// The name of a creative slot (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCreativeSlot : @"summer_banner2",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCreativeSlot NS_SWIFT_NAME(AnalyticsParameterCreativeSlot) =
@"creative_slot";
/// Purchase currency in 3-letter <a href="http://en.wikipedia.org/wiki/ISO_4217#Active_codes">
/// ISO_4217</a> format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterCurrency : @"USD",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterCurrency NS_SWIFT_NAME(AnalyticsParameterCurrency) =
@"currency";
/// Flight or Travel destination (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterDestination : @"Mountain View, CA",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterDestination NS_SWIFT_NAME(AnalyticsParameterDestination) =
@"destination";
/// The arrival date, check-out date or rental end date for the item. This should be in
/// YYYY-MM-DD format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterEndDate : @"2015-09-14",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterEndDate NS_SWIFT_NAME(AnalyticsParameterEndDate) = @"end_date";
/// Flight number for travel events (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterFlightNumber : @"ZZ800",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterFlightNumber NS_SWIFT_NAME(AnalyticsParameterFlightNumber) =
@"flight_number";
/// Group/clan/guild ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterGroupID : @"g1",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterGroupID NS_SWIFT_NAME(AnalyticsParameterGroupID) = @"group_id";
/// Index of an item in a list (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterIndex : @(1),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterIndex NS_SWIFT_NAME(AnalyticsParameterIndex) = @"index";
/// Item brand (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemBrand : @"Google",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemBrand NS_SWIFT_NAME(AnalyticsParameterItemBrand) =
@"item_brand";
/// Item category (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemCategory : @"t-shirts",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemCategory NS_SWIFT_NAME(AnalyticsParameterItemCategory) =
@"item_category";
/// Item ID (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemID : @"p7654",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemID NS_SWIFT_NAME(AnalyticsParameterItemID) = @"item_id";
/// The Google <a href="https://developers.google.com/places/place-id">Place ID</a> (NSString) that
/// corresponds to the associated item. Alternatively, you can supply your own custom Location ID.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemLocationID : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemLocationID
NS_SWIFT_NAME(AnalyticsParameterItemLocationID) = @"item_location_id";
/// Item name (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemName : @"abc",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemName NS_SWIFT_NAME(AnalyticsParameterItemName) =
@"item_name";
/// The list in which the item was presented to the user (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemList : @"Search Results",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemList NS_SWIFT_NAME(AnalyticsParameterItemList) =
@"item_list";
/// Item variant (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterItemVariant : @"Red",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterItemVariant NS_SWIFT_NAME(AnalyticsParameterItemVariant) =
@"item_variant";
/// Level in game (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterLevel : @(42),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterLevel NS_SWIFT_NAME(AnalyticsParameterLevel) = @"level";
/// Location (NSString). The Google <a href="https://developers.google.com/places/place-id">Place ID
/// </a> that corresponds to the associated event. Alternatively, you can supply your own custom
/// Location ID.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterLocation : @"ChIJiyj437sx3YAR9kUWC8QkLzQ",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterLocation NS_SWIFT_NAME(AnalyticsParameterLocation) =
@"location";
/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended
/// (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterMedium : @"email",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium";
/// Number of nights staying at hotel (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfNights : @(3),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfNights
NS_SWIFT_NAME(AnalyticsParameterNumberOfNights) = @"number_of_nights";
/// Number of passengers traveling (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfPassengers : @(11),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfPassengers
NS_SWIFT_NAME(AnalyticsParameterNumberOfPassengers) = @"number_of_passengers";
/// Number of rooms for travel events (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterNumberOfRooms : @(2),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterNumberOfRooms NS_SWIFT_NAME(AnalyticsParameterNumberOfRooms) =
@"number_of_rooms";
/// Flight or Travel origin (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterOrigin : @"Mountain View, CA",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterOrigin NS_SWIFT_NAME(AnalyticsParameterOrigin) = @"origin";
/// Purchase price (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterPrice : @(1.0),
/// kFIRParameterCurrency : @"USD", // e.g. $1.00 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterPrice NS_SWIFT_NAME(AnalyticsParameterPrice) = @"price";
/// Purchase quantity (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterQuantity : @(1),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterQuantity NS_SWIFT_NAME(AnalyticsParameterQuantity) =
@"quantity";
/// Score in game (signed 64-bit integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterScore : @(4200),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterScore NS_SWIFT_NAME(AnalyticsParameterScore) = @"score";
/// The search string/keywords used (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSearchTerm : @"periodic table",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSearchTerm NS_SWIFT_NAME(AnalyticsParameterSearchTerm) =
@"search_term";
/// Shipping cost (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterShipping : @(9.50),
/// kFIRParameterCurrency : @"USD", // e.g. $9.50 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterShipping NS_SWIFT_NAME(AnalyticsParameterShipping) =
@"shipping";
/// Sign up method (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSignUpMethod : @"google",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSignUpMethod NS_SWIFT_NAME(AnalyticsParameterSignUpMethod) =
@"sign_up_method";
/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban
/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your
/// property. Highly recommended (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSource : @"InMobi",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source";
/// The departure date, check-in date or rental start date for the item. This should be in
/// YYYY-MM-DD format (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterStartDate : @"2015-09-14",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterStartDate NS_SWIFT_NAME(AnalyticsParameterStartDate) =
@"start_date";
/// Tax amount (double as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTax : @(1.0),
/// kFIRParameterCurrency : @"USD", // e.g. $1.00 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTax NS_SWIFT_NAME(AnalyticsParameterTax) = @"tax";
/// If you're manually tagging keyword campaigns, you should use utm_term to specify the keyword
/// (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTerm : @"game",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTerm NS_SWIFT_NAME(AnalyticsParameterTerm) = @"term";
/// A single ID for a ecommerce group transaction (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTransactionID : @"ab7236dd9823",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTransactionID NS_SWIFT_NAME(AnalyticsParameterTransactionID) =
@"transaction_id";
/// Travel class (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterTravelClass : @"business",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterTravelClass NS_SWIFT_NAME(AnalyticsParameterTravelClass) =
@"travel_class";
/// A context-specific numeric value which is accumulated automatically for each event type. This is
/// a general purpose parameter that is useful for accumulating a key metric that pertains to an
/// event. Examples include revenue, distance, time and points. Value should be specified as signed
/// 64-bit integer or double as NSNumber. Notes: Values for pre-defined currency-related events
/// (such as @c kFIREventAddToCart) should be supplied using double as NSNumber and must be
/// accompanied by a @c kFIRParameterCurrency parameter. The valid range of accumulated values is
/// [-9,223,372,036,854.77, 9,223,372,036,854.77]. Supplying a non-numeric value, omitting the
/// corresponding @c kFIRParameterCurrency parameter, or supplying an invalid
/// <a href="https://goo.gl/qqX3J2">currency code</a> for conversion events will cause that
/// conversion to be omitted from reporting.
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterValue : @(3.99),
/// kFIRParameterCurrency : @"USD", // e.g. $3.99 USD
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterValue NS_SWIFT_NAME(AnalyticsParameterValue) = @"value";
/// Name of virtual currency type (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterVirtualCurrencyName : @"virtual_currency_name",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterVirtualCurrencyName
NS_SWIFT_NAME(AnalyticsParameterVirtualCurrencyName) = @"virtual_currency_name";
/// The name of a level in a game (NSString).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterLevelName : @"room_1",
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterLevelName NS_SWIFT_NAME(AnalyticsParameterLevelName) =
@"level_name";
/// The result of an operation. Specify 1 to indicate success and 0 to indicate failure (unsigned
/// integer as NSNumber).
/// <pre>
/// NSDictionary *params = @{
/// kFIRParameterSuccess : @(1),
/// // ...
/// };
/// </pre>
static NSString *const kFIRParameterSuccess NS_SWIFT_NAME(AnalyticsParameterSuccess) = @"success";

View File

@@ -0,0 +1,17 @@
/// @file FIRUserPropertyNames.h
///
/// Predefined user property names.
///
/// A UserProperty is an attribute that describes the app-user. By supplying UserProperties, you can
/// later analyze different behaviors of various segments of your userbase. You may supply up to 25
/// unique UserProperties per app, and you can use the name and value of your choosing for each one.
/// UserProperty names can be up to 24 characters long, may only contain alphanumeric characters and
/// underscores ("_"), and must start with an alphabetic character. UserProperty values can be up to
/// 36 characters long. The "firebase_", "google_", and "ga_" prefixes are reserved and should not
/// be used.
#import <Foundation/Foundation.h>
/// The method used to sign in. For example, "google", "facebook" or "twitter".
static NSString *const kFIRUserPropertySignUpMethod
NS_SWIFT_NAME(AnalyticsUserPropertySignUpMethod) = @"sign_up_method";

View File

@@ -0,0 +1,6 @@
#import "FIRAnalytics+AppDelegate.h"
#import "FIRAnalytics.h"
#import "FIRAnalyticsSwiftNameSupport.h"
#import "FIREventNames.h"
#import "FIRParameterNames.h"
#import "FIRUserPropertyNames.h"

View File

@@ -0,0 +1,10 @@
framework module FirebaseAnalytics {
umbrella header "FirebaseAnalytics.h"
export *
module * { export *}
link "sqlite3"
link "z"
link framework "Security"
link framework "StoreKit"
link framework "SystemConfiguration"
link framework "UIKit"}

View File

@@ -0,0 +1,6 @@
framework module FirebaseCoreDiagnostics {
export *
module * { export *}
link "z"
link framework "Security"
link framework "SystemConfiguration"}

Binary file not shown.

View File

@@ -0,0 +1,154 @@
# v5.0.1
- Restore 4.x level of support for extensions (#1357).
# v5.0.0
- Adds APIs for phone Auth testing to bypass the verification flow (#1192).
- Changes the callback block signature for sign in and create user methods
to provide an AuthDataResult that includes the user and user info (#1123, #1186).
- Removes GoogleToolboxForMac dependency (#1175).
- Removes miscellaneous deprecated APIs (#1188, #1200).
# v4.6.1
- Fixes crash which occurred when certain Firebase IDTokens were being parsed (#1076).
# v4.6.0
- Adds `getIDTokenResultWithCompletion:` and `getIDTokenResultForcingRefresh:completion:` APIs which
call back with an AuthTokenResult object. The Auth token result object contains the ID token JWT string and other properties associated with the token including the decoded available payload claims (#1004).
- Adds the `updateCurrentUser:completion:` API which sets the currentUser on the calling Auth instance to the provided user object (#1018).
- Adds client-side validation to prevent setting `handleCodeInApp` to false when performing
email-link authentication. If `handleCodeInApp` is set to false an invalid argument exception
is thrown (#931).
- Adds support for passing the deep link (which is embedded in the sign-in link sent via email) to the
`signInWithEmail:link:completion:` and `isSignInWithEmailLink:` methods during an
email/link sign-in flow (#1023).
# v4.5.0
- Adds new API which provides a way to determine the sign-in methods associated with an
email address.
- Adds new API which allows authentication using only an email link (Passwordless Authentication
with email link).
# v4.4.4
- Addresses CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF warnings that surface in newer versions of
Xcode and CocoaPods.
- Improves FIRUser documentation with clear message explaining when Firebase Auth attempts to validate
users and what happens when an invalidated user is detected (#694) .
# v4.4.3
- Adds an explicit dependency on CoreGraphics from Firebase Auth.
# v4.4.2
- Fixes bug where the FIRAuthResult object returned following a Phone Number authentication
always contained a nil FIRAdditionalUserInfo object. Now the FIRAdditionalUserInfo object is
never nil and its newUser field is populated correctly.
# v4.4.0
- Adds new APIs which return an AuthDataResult object after successfully creating an
Email/Password user, signing in anonymously, signing in with Email/Password and signing
in with Custom Token. The AuthDataResult object contains the new user and additional
information pertaining to the new user.
# v4.3.2
- Improves error handling for the phone number sign-in reCAPTCHA flow.
- Improves error handling for phone number linking flow.
- Fixes issue where after linking an anonymous user to a phone number the user remained
anonymous.
# v4.3.1
- Internal clean up.
# v4.3.0
- Provides account creation and last sign-in dates as metadata to the user
object.
- Returns more descriptive errors for some error cases of the phone number
sign-in reCAPTCHA flow.
- Fixes an issue that invalid users were not automatically signed out earlier.
- Fixes an issue that ID token listeners were not fired in some cases.
# v4.2.1
- Fixes a threading issue in phone number auth that completion block was not
executed on the main thread in some error cases.
# v4.2.0
- Adds new phone number verification API which makes use of an intelligent reCAPTCHA to verify the application.
# v4.1.1
- Improves some method documentation in headers.
# v4.1.0
- Allows the app to handle continue URL natively, e.g., from password reset
email.
- Allows the app to set language code, e.g., for sending password reset email.
- Fixes an issue that user's phone number did not persist on client.
- Fixes an issue that recover email action code type was reported as unknown.
- Improves app start-up time by moving initialization off from the main
thread.
- Better reports missing email error when creating a new password user.
- Changes console message logging levels to be more consistent with other
Firebase products on the iOS platform.
# 2017-05-17 -- v4.0.0
- Adds Phone Number Authentication.
- Adds support for generic OAuth2 identity providers.
- Adds methods that return additional user data from identity providers if
available when authenticating users.
- Improves session management by automatically refreshing tokens if possible
and signing out users if the session is detected invalidated, for example,
after the user changed password or deleted account from another device.
- Fixes an issue that reauthentication creates new user account if the user
credential is valid but does not match the currently signed in user.
- Fixes an issue that the "password" provider is not immediately listed on the
client side after adding a password to an account.
- Changes factory methods to return non-null FIRAuth instances or raises an
exception, instead of returning nullable instances.
- Changes auth state change listener to only be triggered when the user changes.
- Adds a new listener which is triggered whenever the ID token is changed.
- Switches ERROR_EMAIL_ALREADY_IN_USE to
ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL when the email used in the
signInWithCredential: call is already in use by another account.
- Deprecates FIREmailPasswordAuthProvider in favor of FIREmailAuthProvider.
- Deprecates getTokenWithCompletion in favor of getIDTokenWithCompletion on
FIRUser.
- Changes Swift API names to better align with Swift convention.
# 2017-02-06 -- v3.1.1
- Allows handling of additional errors when sending OOB action emails. The
server can respond with the following new error messages:
INVALID_MESSAGE_PAYLOAD,INVALID_SENDER and INVALID_RECIPIENT_EMAIL.
- Removes incorrect reference to FIRAuthErrorCodeCredentialTooOld in FIRUser.h.
- Provides additional error information from server if available.
# 2016-12-13 -- v3.1.0
- Adds FIRAuth methods that enable the app to follow up with user actions
delivered by email, such as verifying email address or reset password.
- No longer applies the keychain workaround introduced in v3.0.5 on iOS 10.2
simulator or above since the issue has been fixed.
- Fixes nullability compilation warnings when used in Swift.
- Better reports missing password error.
# 2016-10-24 -- v3.0.6
- Switches to depend on open sourced GoogleToolboxForMac and GTMSessionFetcher.
- Improves logging of keychain error when initializing.
# 2016-09-14 -- v3.0.5
- Works around a keychain issue in iOS 10 simulator.
- Reports the correct error for invalid email when signing in with email and
password.
# 2016-07-18 -- v3.0.4
- Fixes a race condition bug that could crash the app with an exception from
NSURLSession on iOS 9.
# 2016-06-20 -- v3.0.3
- Adds documentation for all possible errors returned by each method.
- Improves error handling and messages for a variety of error conditions.
- Whether or not an user is considered anonymous is now consistent with other
platforms.
- A saved signed in user is now siloed between different Firebase projects
within the same app.
# 2016-05-18 -- v3.0.2
- Initial public release.

View File

@@ -0,0 +1,17 @@
# Firebase Auth for iOS
Firebase Auth enables apps to easily support multiple authentication options
for their end users.
Please visit [our developer site](https://firebase.google.com/docs/auth/) for
integration instructions, documentation, support information, and terms of
service.
# Firebase Auth Development
Example/Auth contains a set of samples and tests that integrate with
FirebaseAuth.
The unit tests run without any additional configuration along with the rest of
Firebase. See [Example/Auth/README.md](../../Example/Auth/README.md) for
information about setting up, running, and testing the samples.

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIREmailAuthProvider.h"
#import "FIREmailPasswordAuthCredential.h"
// FIREmailPasswordAuthProviderID is defined in FIRAuthProvider.m.
@implementation FIREmailAuthProvider
- (instancetype)init {
@throw [NSException exceptionWithName:@"Attempt to call unavailable initializer."
reason:@"This class is not meant to be initialized."
userInfo:nil];
}
+ (FIRAuthCredential *)credentialWithEmail:(NSString *)email password:(NSString *)password {
return [[FIREmailPasswordAuthCredential alloc] initWithEmail:email password:password];
}
+ (FIRAuthCredential *)credentialWithEmail:(NSString *)email link:(NSString *)link {
return [[FIREmailPasswordAuthCredential alloc] initWithEmail:email link:link];
}
@end

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIREmailPasswordAuthCredential
@brief Internal implementation of FIRAuthCredential for Email/Password credentials.
*/
@interface FIREmailPasswordAuthCredential : FIRAuthCredential
/** @property email
@brief The user's email address.
*/
@property(nonatomic, readonly) NSString *email;
/** @property password
@brief The user's password.
*/
@property(nonatomic, readonly) NSString *password;
/** @property link
@brief The email sign-in link.
*/
@property(nonatomic, readonly) NSString *link;
/** @fn initWithEmail:password:
@brief Designated initializer.
@param email The user's email address.
@param password The user's password.
*/
- (nullable instancetype)initWithEmail:(NSString *)email password:(NSString *)password
NS_DESIGNATED_INITIALIZER;
/** @fn initWithEmail:link:
@brief Designated initializer.
@param email The user's email address.
@param link The email sign-in link.
*/
- (nullable instancetype)initWithEmail:(NSString *)email link:(NSString *)link
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIREmailPasswordAuthCredential.h"
#import "FIREmailAuthProvider.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
@interface FIREmailPasswordAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIREmailPasswordAuthCredential
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (nullable instancetype)initWithEmail:(NSString *)email password:(NSString *)password {
self = [super initWithProvider:FIREmailAuthProviderID];
if (self) {
_email = [email copy];
_password = [password copy];
}
return self;
}
- (nullable instancetype)initWithEmail:(NSString *)email link:(NSString *)link {
self = [super initWithProvider:FIREmailAuthProviderID];
if (self) {
_email = [email copy];
_link = [link copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Attempt to call prepareVerifyAssertionRequest: on a FIREmailPasswordAuthCredential."];
}
@end

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRFacebookAuthCredential
@brief Internal implementation of FIRAuthCredential for the Facebook IdP.
*/
@interface FIRFacebookAuthCredential : FIRAuthCredential
/** @fn initWithAccessToken:
@brief Designated initializer.
@param accessToken The Access Token obtained from Facebook.
*/
- (nullable instancetype)initWithAccessToken:(NSString *)accessToken NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRFacebookAuthCredential.h"
#import "FIRFacebookAuthProvider.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
@interface FIRFacebookAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIRFacebookAuthCredential {
NSString *_accessToken;
}
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (nullable instancetype)initWithAccessToken:(NSString *)accessToken {
self = [super initWithProvider:FIRFacebookAuthProviderID];
if (self) {
_accessToken = [accessToken copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerAccessToken = _accessToken;
}
@end

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRFacebookAuthProvider.h"
#import "FIRFacebookAuthCredential.h"
#import "FIRAuthExceptionUtils.h"
// FIRFacebookAuthProviderID is defined in FIRAuthProvider.m.
@implementation FIRFacebookAuthProvider
- (instancetype)init {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"This class is not meant to be initialized."];
return nil;
}
+ (FIRAuthCredential *)credentialWithAccessToken:(NSString *)accessToken {
return [[FIRFacebookAuthCredential alloc] initWithAccessToken:accessToken];
}
@end

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRGitHubAuthCredential
@brief Internal implementation of FIRAuthCredential for GitHub credentials.
*/
@interface FIRGitHubAuthCredential : FIRAuthCredential
/** @property token
@brief The GitHub OAuth access token.
*/
@property(nonatomic, readonly) NSString *token;
/** @fn initWithToken:
@brief Designated initializer.
@param token The GitHub OAuth access token.
*/
- (nullable instancetype)initWithToken:(NSString *)token NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRGitHubAuthCredential.h"
#import "FIRGitHubAuthProvider.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
@interface FIRGitHubAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIRGitHubAuthCredential
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (nullable instancetype)initWithToken:(NSString *)token {
self = [super initWithProvider:FIRGitHubAuthProviderID];
if (self) {
_token = [token copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerAccessToken = _token;
}
@end

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRGitHubAuthProvider.h"
#import "FIRGitHubAuthCredential.h"
#import "FIRAuthExceptionUtils.h"
// FIRGitHubAuthProviderID is defined in FIRAuthProvider.m.
@implementation FIRGitHubAuthProvider
- (instancetype)init {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"This class is not meant to be initialized."];
return nil;
}
+ (FIRAuthCredential *)credentialWithToken:(NSString *)token {
return [[FIRGitHubAuthCredential alloc] initWithToken:token];
}
@end

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRGoogleAuthCredential
@brief Internal implementation of FIRAuthCredential for the Google IdP.
*/
@interface FIRGoogleAuthCredential : FIRAuthCredential
/** @fn initWithIDToken:accessToken:
@brief Designated initializer.
@param IDToken The ID Token obtained from Google.
@param accessToken The Access Token obtained from Google.
*/
- (nullable instancetype)initWithIDToken:(NSString *)IDToken accessToken:(NSString *)accessToken
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRGoogleAuthCredential.h"
#import "FIRGoogleAuthProvider.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
@interface FIRGoogleAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIRGoogleAuthCredential {
NSString *_IDToken;
NSString *_accessToken;
}
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (nullable instancetype)initWithIDToken:(NSString *)IDToken accessToken:(NSString *)accessToken {
self = [super initWithProvider:FIRGoogleAuthProviderID];
if (self) {
_IDToken = [IDToken copy];
_accessToken = [accessToken copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerIDToken = _IDToken;
request.providerAccessToken = _accessToken;
}
@end

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRGoogleAuthProvider.h"
#import "FIRGoogleAuthCredential.h"
#import "FIRAuthExceptionUtils.h"
// FIRGoogleAuthProviderID is defined in FIRAuthProvider.m.
@implementation FIRGoogleAuthProvider
- (instancetype)init {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"This class is not meant to be initialized."];
return nil;
}
+ (FIRAuthCredential *)credentialWithIDToken:(NSString *)IDToken
accessToken:(NSString *)accessToken {
return [[FIRGoogleAuthCredential alloc] initWithIDToken:IDToken accessToken:accessToken];
}
@end

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIROAuthCredential
@brief Internal implementation of FIRAuthCredential for generic credentials.
*/
@interface FIROAuthCredential : FIRAuthCredential
/** @property IDToken
@brief The ID Token associated with this credential.
*/
@property(nonatomic, readonly, nullable) NSString *IDToken;
/** @property accessToken
@brief The access token associated with this credential.
*/
@property(nonatomic, readonly, nullable) NSString *accessToken;
/** @fn initWithProviderId:IDToken:accessToken:
@brief Designated initializer.
@param providerID The provider ID associated with the credential being created.
@param IDToken The ID Token associated with the credential being created.
@param accessToken The access token associated with the credential being created.
*/
- (nullable instancetype)initWithProviderID:(NSString *)providerID
IDToken:(nullable NSString*)IDToken
accessToken:(nullable NSString *)accessToken;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIROAuthCredential.h"
#import "FIRVerifyAssertionRequest.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIROAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIROAuthCredential
- (nullable instancetype)initWithProviderID:(NSString *)providerID
IDToken:(nullable NSString *)IDToken
accessToken:(nullable NSString *)accessToken {
self = [super initWithProvider:providerID];
if (self) {
_IDToken = IDToken;
_accessToken = accessToken;
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerIDToken = _IDToken;
request.providerAccessToken = _accessToken;
}
NS_ASSUME_NONNULL_END
@end

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIROAuthProvider.h"
#import "FIROAuthCredential.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIROAuthProvider
+ (FIRAuthCredential *)credentialWithProviderID:(NSString *)providerID
IDToken:(NSString *)IDToken
accessToken:(nullable NSString *)accessToken {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:IDToken
accessToken:accessToken];
}
+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(NSString *)accessToken {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:nil
accessToken:accessToken];
}
NS_ASSUME_NONNULL_END
@end

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRPhoneAuthCredential.h"
#import "FIRPhoneAuthCredential_Internal.h"
#import "FIRAuthCredential_Internal.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRPhoneAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIRPhoneAuthCredential
- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof
phoneNumber:(NSString *)phoneNumber
providerID:(NSString *)providerID {
self = [super initWithProvider:providerID];
if (self) {
_temporaryProof = [temporaryProof copy];
_phoneNumber = [phoneNumber copy];
}
return self;
}
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (instancetype)initWithProviderID:(NSString *)providerID
verificationID:(NSString *)verificationID
verificationCode:(NSString *)verificationCode {
self = [super initWithProvider:providerID];
if (self) {
_verificationID = [verificationID copy];
_verificationCode = [verificationCode copy];
}
return self;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRPhoneAuthCredential.h"
NS_ASSUME_NONNULL_BEGIN
/** @extension FIRPhoneAuthCredential
@brief Internal implementation of FIRAuthCredential for Phone Auth credentials.
*/
@interface FIRPhoneAuthCredential ()
/** @var verificationID
@brief The verification ID obtained from invoking @c verifyPhoneNumber:completion:
*/
@property(nonatomic, readonly, nonnull) NSString *verificationID;
/** @var verificationCode
@brief The verification code provided by the user.
*/
@property(nonatomic, readonly, nonnull) NSString *verificationCode;
/** @var temporaryProof
@brief The a temporary proof code perftaining to this credential, returned from the backend.
*/
@property(nonatomic, readonly, nonnull) NSString *temporaryProof;
/** @var phoneNumber
@brief The a phone number pertaining to this credential, returned from the backend.
*/
@property(nonatomic, readonly, nonnull) NSString *phoneNumber;
/** @var initWithTemporaryProof:phoneNumber:
@brief Designated Initializer.
@param providerID The provider ID associated with the phone auth credential being created.
*/
- (instancetype)initWithTemporaryProof:(NSString *)temporaryProof
phoneNumber:(NSString *)phoneNumber
providerID:(NSString *)providerID NS_DESIGNATED_INITIALIZER;
/** @var initWithProviderID:verificationID:verificationCode:
@brief Designated Initializer.
@param providerID The provider ID associated with the phone auth credential being created.
@param verificationID The verification ID associated witht Phone Auth credential being created.
@param verificationCode The verification code associated witht Phone Auth credential being
created.
*/
- (instancetype)initWithProviderID:(NSString *)providerID
verificationID:(NSString *)verificationID
verificationCode:(NSString *)verificationCode NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,519 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRPhoneAuthProvider.h"
#import <FirebaseCore/FIRLogger.h>
#import "FIRPhoneAuthCredential_Internal.h"
#import <FirebaseCore/FIRApp.h>
#import "FIRAuthAPNSToken.h"
#import "FIRAuthAPNSTokenManager.h"
#import "FIRAuthAppCredential.h"
#import "FIRAuthAppCredentialManager.h"
#import "FIRAuthGlobalWorkQueue.h"
#import "FIRAuth_Internal.h"
#import "FIRAuthURLPresenter.h"
#import "FIRAuthNotificationManager.h"
#import "FIRAuthErrorUtils.h"
#import "FIRAuthBackend.h"
#import "FIRAuthSettings.h"
#import "FIRAuthWebUtils.h"
#import "FirebaseAuthVersion.h"
#import <FirebaseCore/FIROptions.h>
#import "FIRGetProjectConfigRequest.h"
#import "FIRGetProjectConfigResponse.h"
#import "FIRSendVerificationCodeRequest.h"
#import "FIRSendVerificationCodeResponse.h"
#import "FIRVerifyClientRequest.h"
#import "FIRVerifyClientResponse.h"
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRReCAPTCHAURLCallBack
@brief The callback invoked at the end of the flow to fetch a reCAPTCHA URL.
@param reCAPTCHAURL The reCAPTCHA URL.
@param error The error that occured while fetching the reCAPTCHAURL, if any.
*/
typedef void (^FIRReCAPTCHAURLCallBack)(NSURL *_Nullable reCAPTCHAURL, NSError *_Nullable error);
/** @typedef FIRVerifyClientCallback
@brief The callback invoked at the end of a client verification flow.
@param appCredential credential that proves the identity of the app during a phone
authentication flow.
@param error The error that occured while verifying the app, if any.
*/
typedef void (^FIRVerifyClientCallback)(FIRAuthAppCredential *_Nullable appCredential,
NSError *_Nullable error);
/** @typedef FIRFetchAuthDomainCallback
@brief The callback invoked at the end of the flow to fetch the Auth domain.
@param authDomain The Auth domain.
@param error The error that occured while fetching the auth domain, if any.
*/
typedef void (^FIRFetchAuthDomainCallback)(NSString *_Nullable authDomain,
NSError *_Nullable error);
/** @var kAuthDomainSuffix
@brief The suffix of the auth domain pertiaining to a given Firebase project.
*/
static NSString *const kAuthDomainSuffix = @"firebaseapp.com";
/** @var kauthTypeVerifyApp
@brief The auth type to be specified in the app verification request.
*/
static NSString *const kAuthTypeVerifyApp = @"verifyApp";
/** @var kReCAPTCHAURLStringFormat
@brief The format of the URL used to open the reCAPTCHA page during app verification.
*/
NSString *const kReCAPTCHAURLStringFormat = @"https://%@/__/auth/handler?";
@implementation FIRPhoneAuthProvider {
/** @var _auth
@brief The auth instance used for verifying the phone number.
*/
FIRAuth *_auth;
/** @var _callbackScheme
@brief The callback URL scheme used for reCAPTCHA fallback.
*/
NSString *_callbackScheme;
}
/** @fn initWithAuth:
@brief returns an instance of @c FIRPhoneAuthProvider assocaited with the provided auth
instance.
@return An Instance of @c FIRPhoneAuthProvider.
*/
- (nullable instancetype)initWithAuth:(FIRAuth *)auth {
self = [super init];
if (self) {
_auth = auth;
_callbackScheme = [[[_auth.app.options.clientID componentsSeparatedByString:@"."]
reverseObjectEnumerator].allObjects componentsJoinedByString:@"."];
}
return self;
}
- (void)verifyPhoneNumber:(NSString *)phoneNumber
UIDelegate:(nullable id<FIRAuthUIDelegate>)UIDelegate
completion:(nullable FIRVerificationResultCallback)completion {
if (![self isCallbackSchemeRegistered]) {
[NSException raise:NSInternalInconsistencyException
format:@"Please register custom URL scheme '%@' in the app's Info.plist file.",
_callbackScheme];
}
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
FIRVerificationResultCallback callBackOnMainThread = ^(NSString *_Nullable verificationID,
NSError *_Nullable error) {
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(verificationID, error);
});
}
};
[self internalVerifyPhoneNumber:phoneNumber completion:^(NSString *_Nullable verificationID,
NSError *_Nullable error) {
if (!error) {
callBackOnMainThread(verificationID, nil);
return;
}
NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey];
BOOL isInvalidAppCredential = error.code == FIRAuthErrorCodeInternalError &&
underlyingError.code == FIRAuthErrorCodeInvalidAppCredential;
if (error.code != FIRAuthErrorCodeMissingAppToken && !isInvalidAppCredential) {
callBackOnMainThread(nil, error);
return;
}
NSMutableString *eventID = [[NSMutableString alloc] init];
for (int i=0; i<10; i++) {
[eventID appendString:
[NSString stringWithFormat:@"%c", 'a' + arc4random_uniform('z' - 'a' + 1)]];
}
[self reCAPTCHAURLWithEventID:eventID completion:^(NSURL *_Nullable reCAPTCHAURL,
NSError *_Nullable error) {
if (error) {
callBackOnMainThread(nil, error);
return;
}
FIRAuthURLCallbackMatcher callbackMatcher = ^BOOL(NSURL *_Nullable callbackURL) {
return [self isVerifyAppURL:callbackURL eventID:eventID];
};
[self->_auth.authURLPresenter presentURL:reCAPTCHAURL
UIDelegate:UIDelegate
callbackMatcher:callbackMatcher
completion:^(NSURL *_Nullable callbackURL,
NSError *_Nullable error) {
if (error) {
callBackOnMainThread(nil, error);
return;
}
NSError *reCAPTCHAError;
NSString *reCAPTCHAToken = [self reCAPTCHATokenForURL:callbackURL error:&reCAPTCHAError];
if (!reCAPTCHAToken) {
callBackOnMainThread(nil, reCAPTCHAError);
return;
}
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber
appCredential:nil
reCAPTCHAToken:reCAPTCHAToken
requestConfiguration:
self->_auth.requestConfiguration];
[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse
*_Nullable response, NSError *_Nullable error) {
if (error) {
callBackOnMainThread(nil, error);
return;
}
callBackOnMainThread(response.verificationID, nil);
}];
}];
}];
}];
});
}
- (FIRPhoneAuthCredential *)credentialWithVerificationID:(NSString *)verificationID
verificationCode:(NSString *)verificationCode {
return [[FIRPhoneAuthCredential alloc] initWithProviderID:FIRPhoneAuthProviderID
verificationID:verificationID
verificationCode:verificationCode];
}
+ (instancetype)provider {
return [[self alloc]initWithAuth:[FIRAuth auth]];
}
+ (instancetype)providerWithAuth:(FIRAuth *)auth {
return [[self alloc]initWithAuth:auth];
}
#pragma mark - Internal Methods
/** @fn isCallbackSchemeRegistered
@brief Checks whether or not the expected callback scheme has been registered by the app.
@remarks This method is thread-safe.
*/
- (BOOL)isCallbackSchemeRegistered {
NSString *expectedCustomScheme = [_callbackScheme lowercaseString];
NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
for (NSDictionary *urlType in urlTypes) {
NSArray *urlTypeSchemes = urlType[@"CFBundleURLSchemes"];
for (NSString *urlTypeScheme in urlTypeSchemes) {
if ([urlTypeScheme.lowercaseString isEqualToString:expectedCustomScheme]) {
return YES;
}
}
}
return NO;
}
/** @fn reCAPTCHATokenForURL:error:
@brief Parses the reCAPTCHA URL and returns.
@param URL The url to be parsed for a reCAPTCHA token.
@param error The error that occurred if any.
@return The reCAPTCHA token if successful.
*/
- (NSString *)reCAPTCHATokenForURL:(NSURL *)URL error:(NSError **)error {
NSURLComponents *actualURLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
NSArray<NSURLQueryItem *> *queryItems = [actualURLComponents queryItems];
NSString *deepLinkURL = [FIRAuthWebUtils queryItemValue:@"deep_link_id" from:queryItems];
NSData *errorData;
if (deepLinkURL) {
actualURLComponents = [NSURLComponents componentsWithString:deepLinkURL];
queryItems = [actualURLComponents queryItems];
NSString *recaptchaToken = [FIRAuthWebUtils queryItemValue:@"recaptchaToken" from:queryItems];
if (recaptchaToken) {
return recaptchaToken;
}
NSString *firebaseError = [FIRAuthWebUtils queryItemValue:@"firebaseError" from:queryItems];
errorData = [firebaseError dataUsingEncoding:NSUTF8StringEncoding];
} else {
errorData = nil;
}
NSError *jsonError;
NSDictionary *errorDict = [NSJSONSerialization JSONObjectWithData:errorData
options:0
error:&jsonError];
if (jsonError) {
*error = [FIRAuthErrorUtils JSONSerializationErrorWithUnderlyingError:jsonError];
return nil;
}
*error = [FIRAuthErrorUtils URLResponseErrorWithCode:errorDict[@"code"]
message:errorDict[@"message"]];
if (!*error) {
NSString *reason;
if(errorDict[@"code"] && errorDict[@"message"]) {
reason = [NSString stringWithFormat:@"[%@] - %@",errorDict[@"code"], errorDict[@"message"]];
} else {
reason = [NSString stringWithFormat:@"An unknown error occurred with the following "
"response: %@", deepLinkURL];
}
*error = [FIRAuthErrorUtils appVerificationUserInteractionFailureWithReason:reason];
}
return nil;
}
/** @fn isVerifyAppURL:
@brief Parses a URL into all available query items.
@param URL The url to be checked against the authType string.
@return Whether or not the URL matches authType.
*/
- (BOOL)isVerifyAppURL:(nullable NSURL *)URL eventID:(NSString *)eventID {
if (!URL) {
return NO;
}
NSURLComponents *actualURLComponents =
[NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
actualURLComponents.query = nil;
actualURLComponents.fragment = nil;
NSURLComponents *expectedURLComponents = [NSURLComponents new];
expectedURLComponents.scheme = _callbackScheme;
expectedURLComponents.host = @"firebaseauth";
expectedURLComponents.path = @"/link";
if (!([[expectedURLComponents URL] isEqual:[actualURLComponents URL]])) {
return NO;
}
actualURLComponents = [NSURLComponents componentsWithURL:URL resolvingAgainstBaseURL:NO];
NSArray<NSURLQueryItem *> *queryItems = [actualURLComponents queryItems];
NSString *deepLinkURL = [FIRAuthWebUtils queryItemValue:@"deep_link_id" from:queryItems];
if (deepLinkURL == nil) {
return NO;
}
NSURLComponents *deepLinkURLComponents = [NSURLComponents componentsWithString:deepLinkURL];
NSArray<NSURLQueryItem *> *deepLinkQueryItems = [deepLinkURLComponents queryItems];
NSString *deepLinkAuthType = [FIRAuthWebUtils queryItemValue:@"authType" from:deepLinkQueryItems];
NSString *deepLinkEventID = [FIRAuthWebUtils queryItemValue:@"eventId" from:deepLinkQueryItems];
if ([deepLinkAuthType isEqualToString:kAuthTypeVerifyApp] &&
[deepLinkEventID isEqualToString:eventID]) {
return YES;
}
return NO;
}
/** @fn internalVerifyPhoneNumber:completion:
@brief Starts the phone number authentication flow by sending a verifcation code to the
specified phone number.
@param phoneNumber The phone number to be verified.
@param completion The callback to be invoked when the verification flow is finished.
*/
- (void)internalVerifyPhoneNumber:(NSString *)phoneNumber
completion:(nullable FIRVerificationResultCallback)completion {
if (!phoneNumber.length) {
completion(nil, [FIRAuthErrorUtils missingPhoneNumberErrorWithMessage:nil]);
return;
}
[_auth.notificationManager checkNotificationForwardingWithCallback:
^(BOOL isNotificationBeingForwarded) {
if (!isNotificationBeingForwarded) {
completion(nil, [FIRAuthErrorUtils notificationNotForwardedError]);
return;
}
FIRVerificationResultCallback callback = ^(NSString *_Nullable verificationID,
NSError *_Nullable error) {
if (completion) {
completion(verificationID, error);
}
};
[self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber
retryOnInvalidAppCredential:YES
callback:callback];
}];
}
/** @fn verifyClientAndSendVerificationCodeToPhoneNumber:retryOnInvalidAppCredential:callback:
@brief Starts the flow to verify the client via silent push notification.
@param retryOnInvalidAppCredential Whether of not the flow should be retried if an
FIRAuthErrorCodeInvalidAppCredential error is returned from the backend.
@param phoneNumber The phone number to be verified.
@param callback The callback to be invoked on the global work queue when the flow is
finished.
*/
- (void)verifyClientAndSendVerificationCodeToPhoneNumber:(NSString *)phoneNumber
retryOnInvalidAppCredential:(BOOL)retryOnInvalidAppCredential
callback:(FIRVerificationResultCallback)callback {
if (_auth.settings.isAppVerificationDisabledForTesting) {
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber
appCredential:nil
reCAPTCHAToken:nil
requestConfiguration:
_auth.requestConfiguration];
[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse *_Nullable response,
NSError *_Nullable error) {
callback(response.verificationID, error);
}];
return;
}
[self verifyClientWithCompletion:^(FIRAuthAppCredential *_Nullable appCredential,
NSError *_Nullable error) {
if (error) {
callback(nil, error);
return;
}
FIRSendVerificationCodeRequest *request =
[[FIRSendVerificationCodeRequest alloc] initWithPhoneNumber:phoneNumber
appCredential:appCredential
reCAPTCHAToken:nil
requestConfiguration:
self->_auth.requestConfiguration];
[FIRAuthBackend sendVerificationCode:request
callback:^(FIRSendVerificationCodeResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
if (error.code == FIRAuthErrorCodeInvalidAppCredential) {
if (retryOnInvalidAppCredential) {
[self->_auth.appCredentialManager clearCredential];
[self verifyClientAndSendVerificationCodeToPhoneNumber:phoneNumber
retryOnInvalidAppCredential:NO
callback:callback];
return;
}
callback(nil, [FIRAuthErrorUtils unexpectedResponseWithDeserializedResponse:nil
underlyingError:error]);
return;
}
callback(nil, error);
return;
}
callback(response.verificationID, nil);
}];
}];
}
/** @fn verifyClientWithCompletion:completion:
@brief Continues the flow to verify the client via silent push notification.
@param completion The callback to be invoked when the client verification flow is finished.
*/
- (void)verifyClientWithCompletion:(FIRVerifyClientCallback)completion {
if (_auth.appCredentialManager.credential) {
completion(_auth.appCredentialManager.credential, nil);
return;
}
[_auth.tokenManager getTokenWithCallback:^(FIRAuthAPNSToken *_Nullable token,
NSError *_Nullable error) {
if (!token) {
completion(nil, [FIRAuthErrorUtils missingAppTokenErrorWithUnderlyingError:error]);
return;
}
FIRVerifyClientRequest *request =
[[FIRVerifyClientRequest alloc] initWithAppToken:token.string
isSandbox:token.type == FIRAuthAPNSTokenTypeSandbox
requestConfiguration:self->_auth.requestConfiguration];
[FIRAuthBackend verifyClient:request callback:^(FIRVerifyClientResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}
NSTimeInterval timeout = [response.suggestedTimeOutDate timeIntervalSinceNow];
[self->_auth.appCredentialManager
didStartVerificationWithReceipt:response.receipt
timeout:timeout
callback:^(FIRAuthAppCredential *credential) {
if (!credential.secret) {
FIRLogWarning(kFIRLoggerAuth, @"I-AUT000014",
@"Failed to receive remote notification to verify app identity within "
@"%.0f second(s)", timeout);
}
completion(credential, nil);
}];
}];
}];
}
/** @fn reCAPTCHAURLWithEventID:completion:
@brief Constructs a URL used for opening a reCAPTCHA app verification flow using a given event
ID.
@param eventID The event ID used for this purpose.
@param completion The callback invoked after the URL has been constructed or an error
has been encountered.
*/
- (void)reCAPTCHAURLWithEventID:(NSString *)eventID completion:(FIRReCAPTCHAURLCallBack)completion {
[self fetchAuthDomainWithCompletion:^(NSString *_Nullable authDomain,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}
NSString *bundleID = [NSBundle mainBundle].bundleIdentifier;
NSString *clientID = self->_auth.app.options.clientID;
NSString *apiKey = self->_auth.requestConfiguration.APIKey;
NSMutableArray<NSURLQueryItem *> *queryItems = [@[
[NSURLQueryItem queryItemWithName:@"apiKey" value:apiKey],
[NSURLQueryItem queryItemWithName:@"authType" value:kAuthTypeVerifyApp],
[NSURLQueryItem queryItemWithName:@"ibi" value:bundleID ?: @""],
[NSURLQueryItem queryItemWithName:@"clientId" value:clientID],
[NSURLQueryItem queryItemWithName:@"v" value:[FIRAuthBackend authUserAgent]],
[NSURLQueryItem queryItemWithName:@"eventId" value:eventID]
] mutableCopy
];
if (self->_auth.requestConfiguration.languageCode) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:@"hl"value:
self->_auth.requestConfiguration.languageCode]];
}
NSURLComponents *components = [[NSURLComponents alloc] initWithString:
[NSString stringWithFormat:kReCAPTCHAURLStringFormat, authDomain]];
[components setQueryItems:queryItems];
completion([components URL], nil);
}];
}
/** @fn fetchAuthDomainWithCompletion:completion:
@brief Fetches the auth domain associated with the Firebase Project.
@param completion The callback invoked after the auth domain has been constructed or an error
has been encountered.
*/
- (void)fetchAuthDomainWithCompletion:(FIRFetchAuthDomainCallback)completion {
FIRGetProjectConfigRequest *request =
[[FIRGetProjectConfigRequest alloc] initWithRequestConfiguration:_auth.requestConfiguration];
[FIRAuthBackend getProjectConfig:request
callback:^(FIRGetProjectConfigResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}
NSString *authDomain;
for (NSString *domain in response.authorizedDomains) {
NSInteger index = domain.length - kAuthDomainSuffix.length;
if (index >= 2) {
if ([domain hasSuffix:kAuthDomainSuffix] && domain.length >= kAuthDomainSuffix.length + 2) {
authDomain = domain;
break;
}
}
}
if (!authDomain.length) {
completion(nil, [FIRAuthErrorUtils unexpectedErrorResponseWithDeserializedResponse:response]);
return;
}
completion(authDomain, nil);
}];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,48 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthCredential_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRTwitterAuthCredential
@brief Internal implementation of FIRAuthCredential for Twitter credentials.
*/
@interface FIRTwitterAuthCredential : FIRAuthCredential
/** @property token
@brief The Twitter OAuth token.
*/
@property(nonatomic, readonly) NSString *token;
/** @property secret
@brief The Twitter OAuth secret.
*/
@property(nonatomic, readonly) NSString *secret;
/** @fn initWithToken:secret:
@brief Designated initializer.
@param token The Twitter OAuth token.
@param secret The Twitter OAuth secret.
*/
- (nullable instancetype)initWithToken:(NSString *)token secret:(NSString *)secret
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRTwitterAuthCredential.h"
#import "FIRTwitterAuthProvider.h"
#import "FIRAuthExceptionUtils.h"
#import "FIRVerifyAssertionRequest.h"
@interface FIRTwitterAuthCredential ()
- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;
@end
@implementation FIRTwitterAuthCredential
- (nullable instancetype)initWithProvider:(NSString *)provider {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"Please call the designated initializer."];
return nil;
}
- (nullable instancetype)initWithToken:(NSString *)token secret:(NSString *)secret {
self = [super initWithProvider:FIRTwitterAuthProviderID];
if (self) {
_token = [token copy];
_secret = [secret copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerAccessToken = _token;
request.providerOAuthTokenSecret = _secret;
}
@end

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRTwitterAuthProvider.h"
#import "FIRTwitterAuthCredential.h"
#import "FIRAuthExceptionUtils.h"
// FIRTwitterAuthProviderID is defined in FIRAuthProvider.m.
@implementation FIRTwitterAuthProvider
- (instancetype)init {
[FIRAuthExceptionUtils raiseMethodNotImplementedExceptionWithReason:
@"This class is not meant to be initialized."];
return nil;
}
+ (FIRAuthCredential *)credentialWithToken:(NSString *)token secret:(NSString *)secret {
return [[FIRTwitterAuthCredential alloc] initWithToken:token secret:secret];
}
@end

View File

@@ -0,0 +1,45 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRActionCodeSettings.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRActionCodeSettings
- (instancetype)init {
self = [super init];
if (self) {
_iOSBundleID = [NSBundle mainBundle].bundleIdentifier;
}
return self;
}
- (void)setIOSBundleID:(NSString *)iOSBundleID {
_iOSBundleID = [iOSBundleID copy];
}
- (void)setAndroidPackageName:(NSString *)androidPackageName
installIfNotAvailable:(BOOL)installIfNotAvailable
minimumVersion:(nullable NSString *)minimumVersion {
_androidPackageName = [androidPackageName copy];
_androidInstallIfNotAvailable = installIfNotAvailable;
_androidMinimumVersion = [minimumVersion copy];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAdditionalUserInfo_Internal.h"
#import "FIRVerifyAssertionResponse.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRAdditionalUserInfo
/** @var kProviderIDCodingKey
@brief The key used to encode the providerID property for NSSecureCoding.
*/
static NSString *const kProviderIDCodingKey = @"providerID";
/** @var kProfileCodingKey
@brief The key used to encode the profile property for NSSecureCoding.
*/
static NSString *const kProfileCodingKey = @"profile";
/** @var kUsernameCodingKey
@brief The key used to encode the username property for NSSecureCoding.
*/
static NSString *const kUsernameCodingKey = @"username";
/** @var kNewUserKey
@brief The key used to encode the newUser property for NSSecureCoding.
*/
static NSString *const kNewUserKey = @"newUser";
+ (nullable instancetype)userInfoWithVerifyAssertionResponse:
(FIRVerifyAssertionResponse *)verifyAssertionResponse {
return [[self alloc] initWithProviderID:verifyAssertionResponse.providerID
profile:verifyAssertionResponse.profile
username:verifyAssertionResponse.username
isNewUser:verifyAssertionResponse.isNewUser];
}
- (nullable instancetype)initWithProviderID:(nullable NSString *)providerID
profile:(nullable NSDictionary<NSString *, NSObject *> *)profile
username:(nullable NSString *)username
isNewUser:(BOOL)isNewUser {
self = [super init];
if (self) {
_providerID = [providerID copy];
if (profile) {
_profile = [[NSDictionary alloc] initWithDictionary:profile copyItems:YES];
}
_username = [username copy];
_newUser = isNewUser;
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *providerID =
[aDecoder decodeObjectOfClass:[NSString class] forKey:kProviderIDCodingKey];
NSDictionary<NSString *, NSObject *> *profile =
[aDecoder decodeObjectOfClass:[NSDictionary class] forKey:kProfileCodingKey];
NSString *username = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUsernameCodingKey];
NSNumber *isNewUser = [aDecoder decodeObjectOfClass:[NSNumber class] forKey:kNewUserKey];
return [self initWithProviderID:providerID
profile:profile
username:username
isNewUser:isNewUser.boolValue];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_providerID forKey:kProviderIDCodingKey];
[aCoder encodeObject:_profile forKey:kProfileCodingKey];
[aCoder encodeObject:_username forKey:kUsernameCodingKey];
[aCoder encodeObject:[NSNumber numberWithBool:_newUser] forKey:kNewUserKey];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAdditionalUserInfo.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRAdditionalUserInfo () <NSSecureCoding>
/** @fn userInfoWithVerifyAssertionResponse:
@brief A convenience factory method for constructing a @c FIRAdditionalUserInfo instance from
data returned by the verifyAssertion endpoint.
@param verifyAssertionResponse Data returned by the verifyAssertion endpoint.
@return A new instance of @c FIRAdditionalUserInfo using data from the verifyAssertion endpoint.
*/
+ (nullable instancetype)userInfoWithVerifyAssertionResponse:
(FIRVerifyAssertionResponse *)verifyAssertionResponse;
/** @fn initWithProviderID:profile:username:
@brief Designated initializer.
@param providerID The provider identifier.
@param profile Dictionary containing the additional IdP specific information.
@param username The name of the user.
@param isNewUser Indicates whether or not the current user was signed in for the first time.
*/
- (nullable instancetype)initWithProviderID:(nullable NSString *)providerID
profile:(nullable NSDictionary<NSString *, NSObject *> *)profile
username:(nullable NSString *)username
isNewUser:(BOOL)isNewUser NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthAPNSTokenType.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthAPNSToken
@brief A data structure for an APNs token.
*/
@interface FIRAuthAPNSToken : NSObject
/** @property data
@brief The APNs token data.
*/
@property(nonatomic, strong, readonly) NSData *data;
/** @property string
@brief The uppercase hexadecimal string form of the APNs token data.
*/
@property(nonatomic, strong, readonly) NSString *string;
/** @property type
@brief The APNs token type.
*/
@property(nonatomic, assign, readonly) FIRAuthAPNSTokenType type;
/** @fn initWithData:type:
@brief Initializes the instance.
@param data The APNs token data.
@param type The APNs token type.
@return The initialized instance.
*/
- (instancetype)initWithData:(NSData *)data type:(FIRAuthAPNSTokenType)type
NS_DESIGNATED_INITIALIZER;
/** @fn init
@brief Call @c initWithData:type: to get an instance of this class.
*/
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthAPNSToken.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRAuthAPNSToken {
/** @var _string
@brief The lazy-initialized string form of the token data.
*/
NSString *_string;
}
- (instancetype)initWithData:(NSData *)data type:(FIRAuthAPNSTokenType)type {
self = [super init];
if (self) {
_data = [data copy];
_type = type;
}
return self;
}
- (NSString *)string {
if (!_string) {
NSUInteger capacity = _data.length * 2;
NSMutableString *tokenString = [NSMutableString stringWithCapacity:capacity];
const unsigned char *tokenData = _data.bytes;
for (int idx = 0; idx < _data.length; ++idx) {
[tokenString appendFormat:@"%02X", (int)tokenData[idx]];
}
_string = tokenString;
}
return _string;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class FIRAuthAPNSToken;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRAuthAPNSTokenCallback
@brief The type of block to receive an APNs token.
@param token The APNs token if one is available.
@param error The error happened if any.
@remarks Both `token` and `error` being `nil` means the request timed-out.
*/
typedef void (^FIRAuthAPNSTokenCallback)(FIRAuthAPNSToken *_Nullable token,
NSError *_Nullable error);
/** @class FIRAuthAPNSTokenManager
@brief A class to manage APNs token in memory.
*/
@interface FIRAuthAPNSTokenManager : NSObject
/** @property token
@brief The APNs token, if one is available.
@remarks Setting a token with FIRAuthAPNSTokenTypeUnknown will automatically converts it to
a token with the automatically detected type.
*/
@property(nonatomic, strong, nullable) FIRAuthAPNSToken *token;
/** @property timeout
@brief The timeout for registering for remote notification.
@remarks Only tests should access this property.
*/
@property(nonatomic, assign) NSTimeInterval timeout;
/** @fn init
@brief Call @c initWithApplication: to initialize an instance of this class.
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn initWithApplication:bundle
@brief Initializes the instance.
@param application The @c UIApplication to request the token from.
@return The initialized instance.
*/
- (instancetype)initWithApplication:(UIApplication *)application NS_DESIGNATED_INITIALIZER;
/** @fn getTokenWithCallback:
@brief Attempts to get the APNs token.
@param callback The block to be called either immediately or in future, either when a token
becomes available, or when timeout occurs, whichever happens earlier.
*/
- (void)getTokenWithCallback:(FIRAuthAPNSTokenCallback)callback;
/** @fn cancelWithError:
@brief Cancels any pending `getTokenWithCallback:` request.
@param error The error to return.
*/
- (void)cancelWithError:(NSError *)error;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,267 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthAPNSTokenManager.h"
#import <FirebaseCore/FIRLogger.h>
#import "FIRAuthAPNSToken.h"
#import "FIRAuthGlobalWorkQueue.h"
NS_ASSUME_NONNULL_BEGIN
/** @var kRegistrationTimeout
@brief Timeout for registration for remote notification.
@remarks Once we start to handle `application:didFailToRegisterForRemoteNotificationsWithError:`
we probably don't have to use timeout at all.
*/
static const NSTimeInterval kRegistrationTimeout = 5;
/** @var kLegacyRegistrationTimeout
@brief Timeout for registration for remote notification on iOS 7.
*/
static const NSTimeInterval kLegacyRegistrationTimeout = 30;
@implementation FIRAuthAPNSTokenManager {
/** @var _application
@brief The @c UIApplication to request the token from.
*/
UIApplication *_application;
/** @var _pendingCallbacks
@brief The list of all pending callbacks for the APNs token.
*/
NSMutableArray<FIRAuthAPNSTokenCallback> *_pendingCallbacks;
}
- (instancetype)initWithApplication:(UIApplication *)application {
self = [super init];
if (self) {
_application = application;
_timeout = [_application respondsToSelector:@selector(registerForRemoteNotifications)] ?
kRegistrationTimeout : kLegacyRegistrationTimeout;
}
return self;
}
- (void)getTokenWithCallback:(FIRAuthAPNSTokenCallback)callback {
if (_token) {
callback(_token, nil);
return;
}
if (_pendingCallbacks) {
[_pendingCallbacks addObject:callback];
return;
}
_pendingCallbacks =
[[NSMutableArray<FIRAuthAPNSTokenCallback> alloc] initWithObjects:callback, nil];
dispatch_async(dispatch_get_main_queue(), ^{
if ([self->_application respondsToSelector:@selector(registerForRemoteNotifications)]) {
[self->_application registerForRemoteNotifications];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#if TARGET_OS_IOS
[self->_application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert];
#endif // TARGET_OS_IOS
#pragma clang diagnostic pop
}
});
NSArray<FIRAuthAPNSTokenCallback> *applicableCallbacks = _pendingCallbacks;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeout * NSEC_PER_SEC)),
FIRAuthGlobalWorkQueue(), ^{
// Only cancel if the pending callbacks remain the same, i.e., not triggered yet.
if (applicableCallbacks == self->_pendingCallbacks) {
[self callBackWithToken:nil error:nil];
}
});
}
- (void)setToken:(nullable FIRAuthAPNSToken *)token {
if (!token) {
_token = nil;
return;
}
if (token.type == FIRAuthAPNSTokenTypeUnknown) {
static FIRAuthAPNSTokenType detectedTokenType = FIRAuthAPNSTokenTypeUnknown;
if (detectedTokenType == FIRAuthAPNSTokenTypeUnknown) {
detectedTokenType =
[[self class] isProductionApp] ? FIRAuthAPNSTokenTypeProd : FIRAuthAPNSTokenTypeSandbox;
}
token = [[FIRAuthAPNSToken alloc] initWithData:token.data type:detectedTokenType];
}
_token = token;
[self callBackWithToken:token error:nil];
}
- (void)cancelWithError:(NSError *)error {
[self callBackWithToken:nil error:error];
}
#pragma mark - Internal methods
/** @fn callBack
@brief Calls back all pending callbacks with APNs token or error.
@param token The APNs token if one is available.
@param error The error occurred, if any.
*/
- (void)callBackWithToken:(nullable FIRAuthAPNSToken *)token error:(nullable NSError *)error {
if (!_pendingCallbacks) {
return;
}
NSArray<FIRAuthAPNSTokenCallback> *allCallbacks = _pendingCallbacks;
_pendingCallbacks = nil;
for (FIRAuthAPNSTokenCallback callback in allCallbacks) {
callback(token, error);
}
};
/** @fn isProductionApp
@brief Whether or not the app has production (versus sandbox) provisioning profile.
@remarks This method is adapted from @c FIRInstanceID .
*/
+ (BOOL)isProductionApp {
const BOOL defaultAppTypeProd = YES;
NSError *error = nil;
Class envClass = NSClassFromString(@"FIRAppEnvironmentUtil");
SEL isSimulatorSelector = NSSelectorFromString(@"isSimulator");
if ([envClass respondsToSelector:isSimulatorSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if ([envClass performSelector:isSimulatorSelector]) {
#pragma clang diagnostic pop
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000006",
@"Assuming prod APNs token type on simulator.");
return defaultAppTypeProd;
}
}
NSString *path = [[[NSBundle mainBundle] bundlePath]
stringByAppendingPathComponent:@"embedded.mobileprovision"];
// Apps distributed via AppStore or TestFlight use the Production APNS certificates.
SEL isFromAppStoreSelector = NSSelectorFromString(@"isFromAppStore");
if ([envClass respondsToSelector:isFromAppStoreSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if ([envClass performSelector:isFromAppStoreSelector]) {
#pragma clang diagnostic pop
return defaultAppTypeProd;
}
}
SEL isAppStoreReceiptSandboxSelector = NSSelectorFromString(@"isAppStoreReceiptSandbox");
if ([envClass respondsToSelector:isAppStoreReceiptSandboxSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if ([envClass performSelector:isAppStoreReceiptSandboxSelector] && !path.length) {
#pragma clang diagnostic pop
// Distributed via TestFlight
return defaultAppTypeProd;
}
}
NSMutableData *profileData = [NSMutableData dataWithContentsOfFile:path options:0 error:&error];
if (!profileData.length || error) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000007",
@"Error while reading embedded mobileprovision %@", error);
return defaultAppTypeProd;
}
// The "embedded.mobileprovision" sometimes contains characters with value 0, which signals the
// end of a c-string and halts the ASCII parser, or with value > 127, which violates strict 7-bit
// ASCII. Replace any 0s or invalid characters in the input.
uint8_t *profileBytes = (uint8_t *)profileData.bytes;
for (int i = 0; i < profileData.length; i++) {
uint8_t currentByte = profileBytes[i];
if (!currentByte || currentByte > 127) {
profileBytes[i] = '.';
}
}
NSString *embeddedProfile = [[NSString alloc] initWithBytesNoCopy:profileBytes
length:profileData.length
encoding:NSASCIIStringEncoding
freeWhenDone:NO];
if (error || !embeddedProfile.length) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000008",
@"Error while reading embedded mobileprovision %@", error);
return defaultAppTypeProd;
}
NSScanner *scanner = [NSScanner scannerWithString:embeddedProfile];
NSString *plistContents;
if ([scanner scanUpToString:@"<plist" intoString:nil]) {
if ([scanner scanUpToString:@"</plist>" intoString:&plistContents]) {
plistContents = [plistContents stringByAppendingString:@"</plist>"];
}
}
if (!plistContents.length) {
return defaultAppTypeProd;
}
NSData *data = [plistContents dataUsingEncoding:NSUTF8StringEncoding];
if (!data.length) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000009",
@"Couldn't read plist fetched from embedded mobileprovision");
return defaultAppTypeProd;
}
NSError *plistMapError;
id plistData = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable
format:nil
error:&plistMapError];
if (plistMapError || ![plistData isKindOfClass:[NSDictionary class]]) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000010",
@"Error while converting assumed plist to dict %@",
plistMapError.localizedDescription);
return defaultAppTypeProd;
}
NSDictionary *plistMap = (NSDictionary *)plistData;
if ([plistMap valueForKeyPath:@"ProvisionedDevices"]) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000011",
@"Provisioning profile has specifically provisioned devices, "
@"most likely a Dev profile.");
}
NSString *apsEnvironment = [plistMap valueForKeyPath:@"Entitlements.aps-environment"];
FIRLogDebug(kFIRLoggerAuth, @"I-AUT000012",
@"APNS Environment in profile: %@", apsEnvironment);
// No aps-environment in the profile.
if (!apsEnvironment.length) {
FIRLogInfo(kFIRLoggerAuth, @"I-AUT000013",
@"No aps-environment set. If testing on a device APNS is not "
@"correctly configured. Please recheck your provisioning profiles.");
return defaultAppTypeProd;
}
if ([apsEnvironment isEqualToString:@"development"]) {
return NO;
}
return defaultAppTypeProd;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthAppCredential
@brief A class represents a credential that proves the identity of the app.
*/
@interface FIRAuthAppCredential : NSObject <NSSecureCoding>
/** @property receipt
@brief The server acknowledgement of receiving client's claim of identity.
*/
@property(nonatomic, strong, readonly) NSString *receipt;
/** @property secret
@brief The secret that the client received from server via a trusted channel, if ever.
*/
@property(nonatomic, strong, readonly, nullable) NSString *secret;
/** @fn initWithReceipt:secret:
@brief Initializes the instance.
@param receipt The server acknowledgement of receiving client's claim of identity.
@param secret The secret that the client received from server via a trusted channel, if ever.
@return The initialized instance.
*/
- (instancetype)initWithReceipt:(NSString *)receipt secret:(nullable NSString *)secret
NS_DESIGNATED_INITIALIZER;
/** @fn init
@brief Call @c initWithReceipt:secret: to get an instance of this class.
*/
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthAppCredential.h"
NS_ASSUME_NONNULL_BEGIN
/** @var kReceiptKey
@brief The key used to encode the receipt property for NSSecureCoding.
*/
static NSString *const kReceiptKey = @"receipt";
/** @var kSecretKey
@brief The key used to encode the secret property for NSSecureCoding.
*/
static NSString *const kSecretKey = @"secret";
@implementation FIRAuthAppCredential
- (instancetype)initWithReceipt:(NSString *)receipt secret:(nullable NSString *)secret {
self = [super init];
if (self) {
_receipt = [receipt copy];
_secret = [secret copy];
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *receipt = [aDecoder decodeObjectOfClass:[NSString class] forKey:kReceiptKey];
if (!receipt) {
return nil;
}
NSString *secret = [aDecoder decodeObjectOfClass:[NSString class] forKey:kSecretKey];
return [self initWithReceipt:receipt secret:secret];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_receipt forKey:kReceiptKey];
[aCoder encodeObject:_secret forKey:kSecretKey];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@class FIRAuthAppCredential;
@class FIRAuthKeychain;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRAuthAppCredentialCallback
@brief The type of block to receive an app crdential.
@param credential The best available app credential at the time.
*/
typedef void (^FIRAuthAppCredentialCallback)(FIRAuthAppCredential *credential);
/** @class FIRAuthAppCredentialManager
@brief A class to manage app credentials backed by iOS Keychain.
*/
@interface FIRAuthAppCredentialManager : NSObject
/** @property credential
@brief The full credential (which has a secret) to be used by the app, if one is available.
*/
@property(nonatomic, strong, readonly, nullable) FIRAuthAppCredential *credential;
/** @property maximumNumberOfPendingReceipts
@brief The maximum (but not necessarily the minimum) number of pending receipts to be kept.
@remarks Only tests should access this property.
*/
@property(nonatomic, assign, readonly) NSUInteger maximumNumberOfPendingReceipts;
/** @fn init
@brief Call @c initWithKeychain: to initialize an instance of this class.
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn initWithKeychain:
@brief Initializes the instance.
@param keychain The iOS Keychain storage to back up the app credential with.
@return The initialized instance.
*/
- (instancetype)initWithKeychain:(FIRAuthKeychain *)keychain NS_DESIGNATED_INITIALIZER;
/** @fn didStartVerificationWithReceipt:timeout:callback:
@brief Notifies that the app verification process has started.
@param receipt The receipt for verification.
@param timeout The timeout value for how long the callback is waited to be called.
@param callback The block to be called in future either when the verification finishes, or
when timeout occurs, whichever happens earlier.
*/
- (void)didStartVerificationWithReceipt:(NSString *)receipt
timeout:(NSTimeInterval)timeout
callback:(FIRAuthAppCredentialCallback)callback;
/** @fn canFinishVerificationWithReceipt:
@brief Attempts to finish verification.
@param receipt The receipt to match the original receipt obtained when verification started.
@param secret The secret to complete the verification.
@return Whether or not the receipt matches a pending verification, and finishes verification
if it does.
*/
- (BOOL)canFinishVerificationWithReceipt:(NSString *)receipt secret:(NSString *)secret;
/** @fn clearCredential
@brief Clears the saved credential, to be used in the case that it is rejected by the server.
*/
- (void)clearCredential;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthAppCredentialManager.h"
#import "FIRAuthAppCredential.h"
#import "FIRAuthGlobalWorkQueue.h"
#import "FIRAuthKeychain.h"
NS_ASSUME_NONNULL_BEGIN
/** @var kKeychainDataKey
@brief The keychain key for the data.
*/
static NSString *const kKeychainDataKey = @"app_credentials";
/** @var kFullCredentialKey
@brief The data key for the full app credential.
*/
static NSString *const kFullCredentialKey = @"full_credential";
/** @var kPendingReceiptsKey
@brief The data key for the array of pending receipts.
*/
static NSString *const kPendingReceiptsKey = @"pending_receipts";
/** @var kMaximumNumberOfPendingReceipts
@brief The maximum number of partial credentials kept by this class.
*/
static const NSUInteger kMaximumNumberOfPendingReceipts = 32;
@implementation FIRAuthAppCredentialManager {
/** @var _keychain
@brief The keychain for app credentials to load from and to save to.
*/
FIRAuthKeychain *_keychain;
/** @var _pendingReceipts
@brief A list of pending receipts sorted in the order they were recorded.
*/
NSMutableArray<NSString *> *_pendingReceipts;
/** @var _callbacksByReceipt
@brief A map from pending receipts to callbacks.
*/
NSMutableDictionary<NSString *, FIRAuthAppCredentialCallback> *_callbacksByReceipt;
}
- (instancetype)initWithKeychain:(FIRAuthKeychain *)keychain {
self = [super init];
if (self) {
_keychain = keychain;
// Load the credentials from keychain if possible.
NSError *error;
NSData *encodedData = [_keychain dataForKey:kKeychainDataKey error:&error];
if (!error && encodedData) {
NSKeyedUnarchiver *unarchiver =
[[NSKeyedUnarchiver alloc] initForReadingWithData:encodedData];
FIRAuthAppCredential *credential =
[unarchiver decodeObjectOfClass:[FIRAuthAppCredential class]
forKey:kFullCredentialKey];
if ([credential isKindOfClass:[FIRAuthAppCredential class]]) {
_credential = credential;
}
NSSet<Class> *allowedClasses =
[NSSet<Class> setWithObjects:[NSArray class], [NSString class], nil];
NSArray<NSString *> *pendingReceipts =
[unarchiver decodeObjectOfClasses:allowedClasses forKey:kPendingReceiptsKey];
if ([pendingReceipts isKindOfClass:[NSArray class]]) {
_pendingReceipts = [pendingReceipts mutableCopy];
}
}
if (!_pendingReceipts) {
_pendingReceipts = [[NSMutableArray<NSString *> alloc] init];
}
_callbacksByReceipt =
[[NSMutableDictionary<NSString *, FIRAuthAppCredentialCallback> alloc] init];
}
return self;
}
- (NSUInteger)maximumNumberOfPendingReceipts {
return kMaximumNumberOfPendingReceipts;
}
- (void)didStartVerificationWithReceipt:(NSString *)receipt
timeout:(NSTimeInterval)timeout
callback:(FIRAuthAppCredentialCallback)callback {
[_pendingReceipts removeObject:receipt];
if (_pendingReceipts.count >= kMaximumNumberOfPendingReceipts) {
[_pendingReceipts removeObjectAtIndex:0];
}
[_pendingReceipts addObject:receipt];
_callbacksByReceipt[receipt] = callback;
[self saveData];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)),
FIRAuthGlobalWorkQueue(), ^{
[self callBackWithReceipt:receipt];
});
}
- (BOOL)canFinishVerificationWithReceipt:(NSString *)receipt secret:(NSString *)secret {
if (![_pendingReceipts containsObject:receipt]) {
return NO;
}
[_pendingReceipts removeObject:receipt];
_credential = [[FIRAuthAppCredential alloc] initWithReceipt:receipt secret:secret];
[self saveData];
[self callBackWithReceipt:receipt];
return YES;
}
- (void)clearCredential {
_credential = nil;
[self saveData];
}
#pragma mark - Internal methods
/** @fn saveData
@brief Save the data in memory to the keychain ignoring any errors.
*/
- (void)saveData {
NSMutableData *archiveData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:archiveData];
[archiver encodeObject:_credential forKey:kFullCredentialKey];
[archiver encodeObject:_pendingReceipts forKey:kPendingReceiptsKey];
[archiver finishEncoding];
[_keychain setData:archiveData forKey:kKeychainDataKey error:NULL];
}
/** @fn callBackWithReceipt:
@brief Calls the saved callback for the specifc receipt.
@param receipt The receipt associated with the callback.
*/
- (void)callBackWithReceipt:(NSString *)receipt {
FIRAuthAppCredentialCallback callback = _callbacksByReceipt[receipt];
if (!callback) {
return;
}
[_callbacksByReceipt removeObjectForKey:receipt];
if (_credential) {
callback(_credential);
} else {
callback([[FIRAuthAppCredential alloc] initWithReceipt:receipt secret:nil]);
}
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,87 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/** @protocol FIRAuthAppDelegateHandler
@brief The protocol to handle app delegate methods.
*/
@protocol FIRAuthAppDelegateHandler <NSObject>
/** @fn setAPNSToken:
@brief Sets the APNs device token.
@param token The APNs device token.
*/
- (void)setAPNSToken:(NSData *)token;
/** @fn handleAPNSTokenError:
@brief Handles APNs device token error.
@param error The APNs device token error.
*/
- (void)handleAPNSTokenError:(NSError *)error;
/** @fn canHandleNotification:
@brief Checks whether the notification can be handled by the receiver, and handles it if so.
@param notification The notification in question, which will be consumed if returns @c YES.
@return Whether the notification can be (and already has been) handled by the receiver.
*/
- (BOOL)canHandleNotification:(nonnull NSDictionary *)notification;
/** @fn canHandleURL:
@brief Checks whether the URL can be handled by the receiver, and handles it if so.
@param url The URL in question, which will be consumed if returns @c YES.
@return Whether the URL can be (and already has been) handled by the receiver.
*/
- (BOOL)canHandleURL:(nonnull NSURL *)url;
@end
/** @class FIRAuthAppDelegateProxy
@brief A manager for swizzling @c UIApplicationDelegate methods.
*/
@interface FIRAuthAppDelegateProxy : NSObject
/** @fn initWithApplication
@brief Initialize the instance with the given @c UIApplication.
@returns An initialized instance, or @c nil if a proxy cannot be established.
@remarks This method should only be called from tests if called outside of this class.
*/
- (nullable instancetype)initWithApplication:(nullable UIApplication *)application
NS_DESIGNATED_INITIALIZER;
/** @fn init
@brief Call @c sharedInstance to get an instance of this class.
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn addHandler:
@brief Adds a handler for UIApplicationDelegate methods.
@param handler The handler to be added.
*/
- (void)addHandler:(__weak id<FIRAuthAppDelegateHandler>)handler;
/** @fn sharedInstance
@brief Gets the shared instance of this class.
@returns The shared instance of this class.
*/
+ (nullable instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,412 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthAppDelegateProxy.h"
#import <FirebaseCore/FIRAppEnvironmentUtil.h>
#import <objc/runtime.h>
NS_ASSUME_NONNULL_BEGIN
/** @var kProxyEnabledBundleKey
@brief The key in application's bundle plist for whether or not proxy should be enabled.
@remarks This key is a shared constant with Analytics and FCM.
*/
static NSString *const kProxyEnabledBundleKey = @"FirebaseAppDelegateProxyEnabled";
/** @fn noop
@brief A function that does nothing.
@remarks This is used as the placeholder for unimplemented UApplicationDelegate methods,
because once we added a method there is no way to remove it from the class.
*/
#if !OBJC_OLD_DISPATCH_PROTOTYPES
static void noop(void) {
}
#else
static id noop(id object, SEL cmd, ...) {
return nil;
}
#endif
/** @fn isIOS9orLater
@brief Checks whether the iOS version is 9 or later.
@returns Whether the iOS version is 9 or later.
*/
static BOOL isIOS9orLater() {
#if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
if (@available(iOS 9.0, *)) {
return YES;
}
return NO;
#else
// UIApplicationOpenURLOptionsAnnotationKey is only available on iOS 9+.
return &UIApplicationOpenURLOptionsAnnotationKey != NULL;
#endif
}
@implementation FIRAuthAppDelegateProxy {
/** @var _appDelegate
@brief The application delegate whose method is being swizzled.
*/
id<UIApplicationDelegate> _appDelegate;
/** @var _orginalImplementationsBySelector
@brief A map from selectors to original implementations that have been swizzled.
*/
NSMutableDictionary<NSValue *, NSValue *> *_originalImplementationsBySelector;
/** @var _handlers
@brief The array of weak pointers of `id<FIRAuthAppDelegateHandler>`.
*/
NSPointerArray *_handlers;
}
- (nullable instancetype)initWithApplication:(nullable UIApplication *)application {
self = [super init];
if (self) {
id proxyEnabled = [[NSBundle mainBundle] objectForInfoDictionaryKey:kProxyEnabledBundleKey];
if ([proxyEnabled isKindOfClass:[NSNumber class]] && !((NSNumber *)proxyEnabled).boolValue) {
return nil;
}
_appDelegate = application.delegate;
if (![_appDelegate conformsToProtocol:@protocol(UIApplicationDelegate)]) {
return nil;
}
_originalImplementationsBySelector = [[NSMutableDictionary<NSValue *, NSValue *> alloc] init];
_handlers = [[NSPointerArray alloc] initWithOptions:NSPointerFunctionsWeakMemory];
// Swizzle the methods.
__weak FIRAuthAppDelegateProxy *weakSelf = self;
SEL registerDeviceTokenSelector =
@selector(application:didRegisterForRemoteNotificationsWithDeviceToken:);
[self replaceSelector:registerDeviceTokenSelector
withBlock:^(id object, UIApplication* application, NSData *deviceToken) {
[weakSelf object:object
selector:registerDeviceTokenSelector
application:application
didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}];
SEL failToRegisterRemoteNotificationSelector =
@selector(application:didFailToRegisterForRemoteNotificationsWithError:);
[self replaceSelector:failToRegisterRemoteNotificationSelector
withBlock:^(id object, UIApplication* application, NSError *error) {
[weakSelf object:object
selector:failToRegisterRemoteNotificationSelector
application:application
didFailToRegisterForRemoteNotificationsWithError:error];
}];
SEL receiveNotificationSelector = @selector(application:didReceiveRemoteNotification:);
SEL receiveNotificationWithHandlerSelector =
@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
if ([_appDelegate respondsToSelector:receiveNotificationWithHandlerSelector] ||
![_appDelegate respondsToSelector:receiveNotificationSelector]) {
// Replace the modern selector which is available on iOS 7 and above.
[self replaceSelector:receiveNotificationWithHandlerSelector
withBlock:^(id object, UIApplication *application, NSDictionary *notification,
void (^completionHandler)(UIBackgroundFetchResult)) {
[weakSelf object:object
selector:receiveNotificationWithHandlerSelector
application:application
didReceiveRemoteNotification:notification
fetchCompletionHandler:completionHandler];
}];
} else {
// Replace the deprecated selector because this is the only one that the client app uses.
[self replaceSelector:receiveNotificationSelector
withBlock:^(id object, UIApplication *application, NSDictionary *notification) {
[weakSelf object:object
selector:receiveNotificationSelector
application:application
didReceiveRemoteNotification:notification];
}];
}
SEL openURLOptionsSelector = @selector(application:openURL:options:);
SEL openURLAnnotationSelector = @selector(application:openURL:sourceApplication:annotation:);
SEL handleOpenURLSelector = @selector(application:handleOpenURL:);
if (isIOS9orLater() &&
([_appDelegate respondsToSelector:openURLOptionsSelector] ||
(![_appDelegate respondsToSelector:openURLAnnotationSelector] &&
![_appDelegate respondsToSelector:handleOpenURLSelector]))) {
// Replace the modern selector which is avaliable on iOS 9 and above because this is the one
// that the client app uses or the client app doesn't use any of them.
[self replaceSelector:openURLOptionsSelector
withBlock:^BOOL(id object, UIApplication *application, NSURL *url,
NSDictionary *options) {
return [weakSelf object:object
selector:openURLOptionsSelector
application:application
openURL:url
options:options];
}];
} else if ([_appDelegate respondsToSelector:openURLAnnotationSelector] ||
![_appDelegate respondsToSelector:handleOpenURLSelector]) {
// Replace the longer form of the deprecated selectors on iOS 8 and below because this is the
// one that the client app uses or the client app doesn't use either of the applicable ones.
[self replaceSelector:openURLAnnotationSelector
withBlock:^(id object, UIApplication *application, NSURL *url,
NSString *sourceApplication, id annotation) {
return [weakSelf object:object
selector:openURLAnnotationSelector
application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
}];
} else {
// Replace the shorter form of the deprecated selectors on iOS 8 and below because this is
// the only one that the client app uses.
[self replaceSelector:handleOpenURLSelector
withBlock:^(id object, UIApplication *application, NSURL *url) {
return [weakSelf object:object
selector:handleOpenURLSelector
application:application
handleOpenURL:url];
}];
}
// Reset the application delegate to clear the system cache that indicates whether each of the
// openURL: methods is implemented on the application delegate.
application.delegate = nil;
application.delegate = _appDelegate;
}
return self;
}
- (void)dealloc {
for (NSValue *selector in _originalImplementationsBySelector) {
IMP implementation = _originalImplementationsBySelector[selector].pointerValue;
Method method = class_getInstanceMethod([_appDelegate class], selector.pointerValue);
imp_removeBlock(method_setImplementation(method, implementation));
}
}
- (void)addHandler:(__weak id<FIRAuthAppDelegateHandler>)handler {
@synchronized (_handlers) {
[_handlers addPointer:(__bridge void *)handler];
}
}
+ (nullable instancetype)sharedInstance {
static dispatch_once_t onceToken;
static FIRAuthAppDelegateProxy *_Nullable sharedInstance;
// iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication
// responds to it.
static Class applicationClass = nil;
if (![FIRAppEnvironmentUtil isAppExtension]) {
Class cls = NSClassFromString(@"UIApplication");
if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) {
applicationClass = cls;
}
}
UIApplication *application = [applicationClass sharedApplication];
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] initWithApplication:application];
});
return sharedInstance;
}
#pragma mark - UIApplicationDelegate proxy methods.
- (void)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
if (object == _appDelegate) {
for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
[handler setAPNSToken:deviceToken];
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef void (*Implmentation)(id, SEL, UIApplication*, NSData *);
((Implmentation)originalImplementation)(object, selector, application, deviceToken);
}
}
- (void)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
if (object == _appDelegate) {
for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
[handler handleAPNSTokenError:error];
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef void (*Implmentation)(id, SEL, UIApplication *, NSError *);
((Implmentation)originalImplementation)(object, selector, application, error);
}
}
- (void)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)notification
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if (object == _appDelegate) {
for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
if ([handler canHandleNotification:notification]) {
completionHandler(UIBackgroundFetchResultNoData);
return;
};
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *,
void (^)(UIBackgroundFetchResult));
((Implmentation)originalImplementation)(object, selector, application, notification,
completionHandler);
}
}
- (void)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)notification {
if (object == _appDelegate) {
for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
if ([handler canHandleNotification:notification]) {
return;
};
}
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef void (*Implmentation)(id, SEL, UIApplication*, NSDictionary *);
((Implmentation)originalImplementation)(object, selector, application, notification);
}
}
- (BOOL)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary *)options {
if (object == _appDelegate && [self delegateCanHandleURL:url]) {
return YES;
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *, NSDictionary *);
return ((Implmentation)originalImplementation)(object, selector, application, url, options);
}
return NO;
}
- (BOOL)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
if (object == _appDelegate && [self delegateCanHandleURL:url]) {
return YES;
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *, NSString *, id);
return ((Implmentation)originalImplementation)(object, selector, application, url,
sourceApplication, annotation);
}
return NO;
}
- (BOOL)object:(id)object
selector:(SEL)selector
application:(UIApplication *)application
handleOpenURL:(NSURL *)url {
if (object == _appDelegate && [self delegateCanHandleURL:url]) {
return YES;
}
IMP originalImplementation = [self originalImplementationForSelector:selector];
if (originalImplementation && originalImplementation != &noop) {
typedef BOOL (*Implmentation)(id, SEL, UIApplication*, NSURL *);
return ((Implmentation)originalImplementation)(object, selector, application, url);
}
return NO;
}
#pragma mark - Internal Methods
/** @fn delegateCanHandleURL:
@brief Checks for whether any of the delegates can handle the URL.
@param url The URL in question.
@return Whether any of the delegate can handle the URL.
*/
- (BOOL)delegateCanHandleURL:(NSURL *)url {
for (id<FIRAuthAppDelegateHandler> handler in [self handlers]) {
if ([handler canHandleURL:url]) {
return YES;
};
}
return NO;
}
/** @fn handlers
@brief Gets the list of handlers from `_handlers` safely.
*/
- (NSArray<id<FIRAuthAppDelegateHandler>> *)handlers {
@synchronized (_handlers) {
NSMutableArray<id<FIRAuthAppDelegateHandler>> *liveHandlers =
[[NSMutableArray<id<FIRAuthAppDelegateHandler>> alloc] initWithCapacity:_handlers.count];
for (__weak id<FIRAuthAppDelegateHandler> handler in _handlers) {
if (handler) {
[liveHandlers addObject:handler];
}
}
if (liveHandlers.count < _handlers.count) {
[_handlers compact];
}
return liveHandlers;
}
}
/** @fn replaceSelector:withBlock:
@brief replaces the implementation for a method of `_appDelegate` specified by a selector.
@param selector The selector for the method.
@param block The block as the new implementation of the method.
*/
- (void)replaceSelector:(SEL)selector withBlock:(id)block {
Method originalMethod = class_getInstanceMethod([_appDelegate class], selector);
IMP newImplementation = imp_implementationWithBlock(block);
IMP originalImplementation;
if (originalMethod) {
originalImplementation = method_setImplementation(originalMethod, newImplementation) ?: &noop;
} else {
// The original method was not implemented in the class, add it with the new implementation.
struct objc_method_description methodDescription =
protocol_getMethodDescription(@protocol(UIApplicationDelegate), selector, NO, YES);
class_addMethod([_appDelegate class], selector, newImplementation, methodDescription.types);
originalImplementation = &noop;
}
_originalImplementationsBySelector[[NSValue valueWithPointer:selector]] =
[NSValue valueWithPointer:originalImplementation];
}
/** @fn originalImplementationForSelector:
@brief Gets the original implementation for the given selector.
@param selector The selector for the method that has been replaced.
@return The original implementation if there was one.
*/
- (IMP)originalImplementationForSelector:(SEL)selector {
return _originalImplementationsBySelector[[NSValue valueWithPointer:selector]].pointerValue;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthCredential_Internal.h"
@implementation FIRAuthCredential
- (instancetype)init {
@throw [NSException exceptionWithName:@"Attempt to call unavailable initializer."
reason:@"This class is an abstract base class. It's init method "
"should not be called directly."
userInfo:nil];
}
- (nullable instancetype)initWithProvider:(NSString *)provider {
self = [super init];
if (self) {
_provider = [provider copy];
}
return self;
}
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
@throw [NSException exceptionWithName:@"Attempt to call virtual method."
reason:@"This method must be overridden by a subclass."
userInfo:nil];
}
@end

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthCredential.h"
@class FIRVerifyAssertionRequest;
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuthCredential ()
/** @fn initWithProvider:
@brief Designated initializer.
@remarks This is the designated initializer for internal/friend subclasses.
@param provider The provider name.
*/
- (nullable instancetype)initWithProvider:(NSString *)provider NS_DESIGNATED_INITIALIZER;
/** @fn prepareVerifyAssertionRequest:
@brief Called immediately before a request to the verifyAssertion endpoint is made. Implementers
should update the passed request instance with their credentials.
@param request The request to be updated with credentials.
*/
- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthDataResult_Internal.h"
#import "FIRAdditionalUserInfo.h"
#import "FIRUser.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRAuthDataResult
/** @var kAdditionalUserInfoCodingKey
@brief The key used to encode the additionalUserInfo property for NSSecureCoding.
*/
static NSString *const kAdditionalUserInfoCodingKey = @"additionalUserInfo";
/** @var kUserCodingKey
@brief The key used to encode the user property for NSSecureCoding.
*/
static NSString *const kUserCodingKey = @"user";
- (nullable instancetype)initWithUser:(FIRUser *)user
additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo {
self = [super init];
if (self) {
_additionalUserInfo = additionalUserInfo;
_user = user;
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
FIRUser *user =
[aDecoder decodeObjectOfClass:[FIRUser class] forKey:kUserCodingKey];
FIRAdditionalUserInfo *additionalUserInfo =
[aDecoder decodeObjectOfClass:[FIRAdditionalUserInfo class]
forKey:kAdditionalUserInfoCodingKey];
return [self initWithUser:user additionalUserInfo:additionalUserInfo];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_user forKey:kUserCodingKey];
[aCoder encodeObject:_additionalUserInfo forKey:kAdditionalUserInfoCodingKey];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthDataResult.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuthDataResult () <NSSecureCoding>
/** @fn initWithUser:additionalUserInfo:
@brief Designated initializer.
@param user The signed in user reference.
@param additionalUserInfo The additional user info if available.
*/
- (nullable instancetype)initWithUser:(FIRUser *)user
additionalUserInfo:(nullable FIRAdditionalUserInfo *)additionalUserInfo
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthUIDelegate.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthDefaultUIDelegate
@brief Class responsible for providing a default FIRAuthUIDelegte.
@remarks This class should be used in the case that a UIDelegate was expected and necessary to
continue a given flow, but none was provided.
*/
@interface FIRAuthDefaultUIDelegate : NSObject <FIRAuthUIDelegate>
/** @fn defaultUIDelegate
@brief Unavailable. Please use @c +defaultUIDelegate:
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn defaultUIDelegate
@brief Returns a default FIRAuthUIDelegate object.
@return The default FIRAuthUIDelegate object.
*/
+ (id<FIRAuthUIDelegate>)defaultUIDelegate;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthDefaultUIDelegate.h"
#import <FirebaseCore/FIRAppEnvironmentUtil.h>
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuthDefaultUIDelegate ()
/** @fn initWithViewController:
@brief Initializes the instance with a view controller.
@param viewController The view controller as the presenting view controller in @c
FIRAuthUIDelegate.
@return The initialized instance.
*/
- (instancetype)initWithViewController:(UIViewController *)viewController NS_DESIGNATED_INITIALIZER;
@end
@implementation FIRAuthDefaultUIDelegate {
/** @var _viewController
@brief The presenting view controller.
*/
UIViewController *_viewController;
}
- (instancetype)initWithViewController:(UIViewController *)viewController {
self = [super init];
if (self) {
_viewController = viewController;
}
return self;
}
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(nullable void (^)(void))completion {
[_viewController presentViewController:viewControllerToPresent
animated:flag
completion:completion];
}
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(nullable void (^)(void))completion {
[_viewController dismissViewControllerAnimated:flag completion:completion];
}
+ (id<FIRAuthUIDelegate>)defaultUIDelegate {
// iOS App extensions should not call [UIApplication sharedApplication], even if UIApplication
// responds to it.
static Class applicationClass = nil;
if (![FIRAppEnvironmentUtil isAppExtension]) {
Class cls = NSClassFromString(@"UIApplication");
if (cls && [cls respondsToSelector:NSSelectorFromString(@"sharedApplication")]) {
applicationClass = cls;
}
}
UIApplication *application = [applicationClass sharedApplication];
UIViewController *topViewController = application.keyWindow.rootViewController;
while (true){
if (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *nav = (UINavigationController *)topViewController;
topViewController = nav.topViewController;
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
return [[FIRAuthDefaultUIDelegate alloc] initWithViewController:topViewController];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRAuthDispatcherImplBlock
@brief The type of block which can be set as the implementation for @c
dispatchAfterDelay:queue:callback: .
@param delay The delay in seconds after which the task will be scheduled to execute.
@param queue The dispatch queue on which the task will be submitted.
@param task The task (block) to be scheduled for future execution.
*/
typedef void(^FIRAuthDispatcherImplBlock)(NSTimeInterval delay,
dispatch_queue_t queue,
void (^task)(void));
/** @class FIRAuthDispatchAfter
@brief A utility class used to facilitate scheduling tasks to be executed in the future.
*/
@interface FIRAuthDispatcher : NSObject
/** @property dispatchAfterImplementation
@brief Allows custom implementation of dispatchAfterDelay:queue:callback:.
@remarks Set to nil to restore default implementation.
*/
@property(nonatomic, nullable, copy) FIRAuthDispatcherImplBlock dispatchAfterImplementation;
/** @fn dispatchAfterDelay:queue:callback:
@brief Schedules task in the future after a specified delay.
@param delay The delay in seconds after which the task will be scheduled to execute.
@param queue The dispatch queue on which the task will be submitted.
@param task The task (block) to be scheduled for future execution.
*/
- (void)dispatchAfterDelay:(NSTimeInterval)delay
queue:(dispatch_queue_t)queue
task:(void (^)(void))task;
/** @fn sharedInstance
@brief Gets the shared instance of this class.
@returns The shared instance of this clss
*/
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthDispatcher.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRAuthDispatcher
@synthesize dispatchAfterImplementation = _dispatchAfterImplementation;
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
static FIRAuthDispatcher *sharedInstance;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void)dispatchAfterDelay:(NSTimeInterval)delay
queue:(dispatch_queue_t)queue
task:(void (^)(void))task {
if (_dispatchAfterImplementation) {
_dispatchAfterImplementation(delay, queue, task);
return;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), queue, task);
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,504 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@class FIRPhoneAuthCredential;
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthErrorUtils
@brief Utility class used to construct @c NSError instances.
*/
@interface FIRAuthErrorUtils : NSObject
/** @fn RPCRequestEncodingErrorWithUnderlyingError
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeRPCRequestEncodingError
code and a populated @c NSUnderlyingErrorKey in the @c NSError.userInfo dictionary.
@param underlyingError The value of the @c NSUnderlyingErrorKey key.
@remarks This error is used when an @c FIRAuthRPCRequest.unencodedHTTPRequestBodyWithError:
invocation returns an error. The error returned is wrapped in this internal error code.
*/
+ (NSError *)RPCRequestEncodingErrorWithUnderlyingError:(NSError *)underlyingError;
/** @fn JSONSerializationErrorForUnencodableType
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeJSONSerializationError code.
@remarks This error is used when an @c NSJSONSerialization.isValidJSONObject: check fails, not
for when an error is returned from @c NSJSONSerialization.dataWithJSONObject:options:error:.
*/
+ (NSError *)JSONSerializationErrorForUnencodableType;
/** @fn JSONSerializationErrorWithUnderlyingError:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeJSONSerializationError code, and the
@c underlyingError as the @c NSUnderlyingErrorKey value in the @c NSError.userInfo
dictionary.
@param underlyingError The value of the @c NSUnderlyingErrorKey key.
@remarks This error is used when an invocation of
@c NSJSONSerialization.dataWithJSONObject:options:error: returns an error.
*/
+ (NSError *)JSONSerializationErrorWithUnderlyingError:(NSError *)underlyingError;
/** @fn networkErrorWithUnderlyingError:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeNetworkError code, and the
@c underlyingError as the @c NSUnderlyingErrorKey value in the @c NSError.userInfo
dictionary.
@param underlyingError The value of the @c NSUnderlyingErrorKey key. Should be the error from
GTM.
@remarks This error is used when a network request results in an error, and no body data was
returned.
*/
+ (NSError *)networkErrorWithUnderlyingError:(NSError *)underlyingError;
/** @fn unexpectedErrorResponseWithUnderlyingError:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeNetworkError code, and the
@c underlyingError as the @c NSUnderlyingErrorKey value.
@param data The value of the @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo
dictionary.
@param underlyingError The value of the @c NSUnderlyingErrorKey key in the @c NSError.userInfo
dictionary.
@remarks This error is used when a network request results in an error, and unserializable body
data was returned.
*/
+ (NSError *)unexpectedErrorResponseWithData:(NSData *)data
underlyingError:(NSError *)underlyingError;
/** @fn unexpectedErrorResponseWithDeserializedResponse:
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedErrorResponse
code, and a populated @c FIRAuthErrorUserInfoDeserializedResponseKey key in the
@c NSError.userInfo dictionary.
@param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key.
@remarks This error is used when a network request results in an error, and the body data was
deserializable as JSON, but couldn't be decoded as an error.
*/
+ (NSError *)unexpectedErrorResponseWithDeserializedResponse:(id)deserializedResponse;
/** @fn unexpectedResponseWithData:underlyingError:
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse
code, and a populated @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo
dictionary.
@param data The value of the @c FIRAuthErrorUserInfoDataKey key in the @c NSError.userInfo
dictionary.
@param underlyingError The value of the @c NSUnderlyingErrorKey key in the @c NSError.userInfo
dictionary.
@remarks This error is used when a network request is apparently successful, but the body data
couldn't be deserialized as JSON.
*/
+ (NSError *)unexpectedResponseWithData:(NSData *)data
underlyingError:(NSError *)underlyingError;;
/** @fn unexpectedResponseWithDeserializedResponse:
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse
code, and a populated @c FIRAuthErrorUserInfoDeserializedResponseKey key in the
@c NSError.userInfo dictionary.
@param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key.
@remarks This error is used when a network request is apparently successful, the body data was
successfully deserialized as JSON, but the JSON wasn't a dictionary.
*/
+ (NSError *)unexpectedResponseWithDeserializedResponse:(id)deserializedResponse;
/** @fn unexpectedResponseWithDeserializedResponse:underlyingError:
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeUnexpectedResponse
code, and populated @c FIRAuthErrorUserInfoDeserializedResponseKey and
@c NSUnderlyingErrorKey keys in the @c NSError.userInfo dictionary.
@param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key.
@param underlyingError The value of the @c NSUnderlyingErrorKey key.
@remarks This error is used when a network request was apparently successful, the body data was
successfully deserialized as JSON, but the data type of the response was unexpected.
*/
+ (NSError *)unexpectedResponseWithDeserializedResponse:(nullable id)deserializedResponse
underlyingError:(NSError *)underlyingError;
/** @fn RPCResponseDecodingErrorWithDeserializedResponse:underlyingError:
@brief Constructs an @c NSError with the @c FIRAuthInternalErrorCodeRPCResponseDecodingError
code, and populated @c FIRAuthErrorUserInfoDeserializedResponseKey and
@c NSUnderlyingErrorKey keys in the @c NSError.userInfo dictionary.
@param deserializedResponse The value of the @c FIRAuthErrorUserInfoDeserializedResponseKey key.
@param underlyingError The value of the @c NSUnderlyingErrorKey key.
@remarks This error is used when an invocation of @c FIRAuthRPCResponse.setWithDictionary:error:
resulted in an error.
*/
+ (NSError *)RPCResponseDecodingErrorWithDeserializedResponse:(id)deserializedResponse
underlyingError:(NSError *)underlyingError;
/** @fn emailAlreadyInUseErrorWithEmail:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeEmailExists code.
@param email The email address that is already in use.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)emailAlreadyInUseErrorWithEmail:(nullable NSString *)email;
/** @fn userDisabledErrorWithMessageWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserDisabled code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)userDisabledErrorWithMessage:(nullable NSString *)message;
/** @fn wrongPasswordErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeWrongPassword code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)wrongPasswordErrorWithMessage:(nullable NSString *)message;
/** @fn tooManyRequestsErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeTooManyRequests Code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)tooManyRequestsErrorWithMessage:(nullable NSString *)message;
/** @fn invalidCustomTokenErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidCustomToken code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidCustomTokenErrorWithMessage:(nullable NSString *)message;
/** @fn customTokenMistmatchErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeCustomTokenMismatch code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)customTokenMistmatchErrorWithMessage:(nullable NSString *)message;
/** @fn invalidCredentialErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidCredential code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidCredentialErrorWithMessage:(nullable NSString *)message;
/** @fn requiresRecentLoginError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeRequiresRecentLogin code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)requiresRecentLoginErrorWithMessage:(nullable NSString *)message;
/** @fn invalidUserTokenErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidUserToken code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidUserTokenErrorWithMessage:(nullable NSString *)message;
/** @fn invalidEmailErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidEmail code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidEmailErrorWithMessage:(nullable NSString *)message;
/** @fn accountExistsWithDifferentCredentialErrorWithEmail:
@brief Constructs an @c NSError with the @c FIRAuthErrorAccountExistsWithDifferentCredential
code.
@param Email The email address that is already associated with an existing account
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)accountExistsWithDifferentCredentialErrorWithEmail:(nullable NSString *)Email;
/** @fn providerAlreadyLinkedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeProviderAlreadyLinked code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)providerAlreadyLinkedError;
/** @fn noSuchProviderError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeNoSuchProvider code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)noSuchProviderError;
/** @fn userTokenExpiredErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserTokenExpired code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)userTokenExpiredErrorWithMessage:(nullable NSString *)message;
/** @fn userNotFoundErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserNotFound code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)userNotFoundErrorWithMessage:(nullable NSString *)message;
/** @fn invalidLocalAPIKeyErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidAPIKey code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidAPIKeyError;
/** @fn userMismatchError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeUserMismatch code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)userMismatchError;
/** @fn credentialAlreadyInUseErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeCredentialAlreadyInUse code.
@param message Error message from the backend, if any.
@param credential Auth credential to be added to the Error User Info dictionary.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)credentialAlreadyInUseErrorWithMessage:(nullable NSString *)message
credential:(nullable FIRPhoneAuthCredential *)credential;
/** @fn operationNotAllowedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeOperationNotAllowed code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)operationNotAllowedErrorWithMessage:(nullable NSString *)message;
/** @fn weakPasswordErrorWithServerResponseReason:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeWeakPassword code.
@param serverResponseReason A more detailed explanation string from server response.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)weakPasswordErrorWithServerResponseReason:(NSString *)serverResponseReason;
/** @fn appNotAuthorizedError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeAppNotAuthorized code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)appNotAuthorizedError;
/** @fn expiredActionCodeErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeExpiredActionCode code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)expiredActionCodeErrorWithMessage:(nullable NSString *)message;
/** @fn invalidActionCodeErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidActionCode code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidActionCodeErrorWithMessage:(nullable NSString *)message;
/** @fn invalidMessagePayloadError:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidMessagePayload code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidMessagePayloadErrorWithMessage:(nullable NSString *)message;
/** @fn invalidSenderErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidSender code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidSenderErrorWithMessage:(nullable NSString *)message;
/** @fn invalidRecipientEmailError:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidRecipientEmail code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidRecipientEmailErrorWithMessage:(nullable NSString *)message;
/** @fn missingIosBundleIDErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingIosBundleID code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingIosBundleIDErrorWithMessage:(nullable NSString *)message;
/** @fn missingAndroidPackageNameErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingAndroidPackageName code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingAndroidPackageNameErrorWithMessage:(nullable NSString *)message;
/** @fn unauthorizedDomainErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeUnauthorizedDomain code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)unauthorizedDomainErrorWithMessage:(nullable NSString *)message;
/** @fn invalidContinueURIErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidContinueURI code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidContinueURIErrorWithMessage:(nullable NSString *)message;
/** @fn missingContinueURIErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingContinueURI code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingContinueURIErrorWithMessage:(nullable NSString *)message;
/** @fn missingEmailErrorWithMessage
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingEmail code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingEmailErrorWithMessage:(nullable NSString *)message;
/** @fn missingPhoneNumberErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingPhoneNumber code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingPhoneNumberErrorWithMessage:(nullable NSString *)message;
/** @fn invalidPhoneNumberErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidPhoneNumber code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidPhoneNumberErrorWithMessage:(nullable NSString *)message;
/** @fn missingVerificationCodeErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingVerificationCode code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingVerificationCodeErrorWithMessage:(nullable NSString *)message;
/** @fn invalidVerificationCodeErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidVerificationCode code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidVerificationCodeErrorWithMessage:(nullable NSString *)message;
/** @fn missingVerificationIDErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingVerificationID code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingVerificationIDErrorWithMessage:(nullable NSString *)message;
/** @fn invalidVerificationIDErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeInvalidVerificationID code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidVerificationIDErrorWithMessage:(nullable NSString *)message;
/** @fn sessionExpiredErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeSessionExpired code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)sessionExpiredErrorWithMessage:(nullable NSString *)message;
/** @fn missingAppCredentialWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorMissingCredential code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingAppCredentialWithMessage:(nullable NSString *)message;
/** @fn invalidAppCredentialWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorInvalidCredential code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)invalidAppCredentialWithMessage:(nullable NSString *)message;
/** @fn quotaExceededErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeQuotaExceeded code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)quotaExceededErrorWithMessage:(nullable NSString *)message;
/** @fn missingAppTokenErrorWithUnderlyingError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeMissingAppToken code.
@param underlyingError The underlying error, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)missingAppTokenErrorWithUnderlyingError:(nullable NSError *)underlyingError;
/** @fn notificationNotForwardedError
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeNotificationNotForwarded code.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)notificationNotForwardedError;
/** @fn appNotVerifiedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeAppNotVerified code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)appNotVerifiedErrorWithMessage:(nullable NSString *)message;
/** @fn captchaCheckFailedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCaptchaCheckFailed code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)captchaCheckFailedErrorWithMessage:(nullable NSString *)message;
/** @fn webContextAlreadyPresentedErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeWebContextAlreadyPresented code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)webContextAlreadyPresentedErrorWithMessage:(nullable NSString *)message;
/** @fn webContextCancelledErrorWithMessage:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeWebContextCancelled code.
@param message Error message from the backend, if any.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)webContextCancelledErrorWithMessage:(nullable NSString *)message;
/** @fn appVerificationUserInteractionFailureWithReason:
@brief Constructs an @c NSError with the @c
FIRAuthErrorCodeAppVerificationUserInteractionFailure code.
@param reason Reason for error, returned via URL response.
@return The NSError instance associated with the given FIRAuthError.
*/
+ (NSError *)appVerificationUserInteractionFailureWithReason:(NSString *)reason;
/** @fn URLResponseErrorWithCode:message:
@brief Constructs an @c NSError with the code and message provided.
@param message Error message from the backend, if any.
@return The nullable NSError instance associated with the given error message, if one is found.
*/
+ (NSError *)URLResponseErrorWithCode:(NSString *)code message:(nullable NSString *)message;
/** @fn nullUserErrorWithMessage:
@brief Constructs an @c NSError with the code and message provided.
@param message Error message from the backend, if any.
@return The nullable NSError instance associated with the given error message, if one is found.
*/
+ (NSError *)nullUserErrorWithMessage:(nullable NSString *)message;
/** @fn keychainErrorWithFunction:status:
@brief Constructs an @c NSError with the @c FIRAuthErrorCodeKeychainError code.
@param keychainFunction The keychain function which was invoked and yielded an unexpected
response. The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo
dictionary will contain a string partially comprised of this value.
@param status The response status from the invoked keychain function. The
@c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo dictionary will contain
a string partially comprised of this value.
*/
+ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status;
@end
NS_ASSUME_NONNULL_END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthExceptionUtils
@brief Utility class used to raise standardized Auth related exceptions.
*/
@interface FIRAuthExceptionUtils : NSObject
/** @fn raiseInvalidParameterExceptionWithReason:
@brief raises the "invalid parameter" exception
@param reason string will contain a description of the error.
*/
+ (void)raiseInvalidParameterExceptionWithReason:(nullable NSString *)reason;
/** @fn raiseMethodNotImplementedExceptionWithReason:
@brief raises the "method not implemented" exception
@param reason string will contain a description of the error.
@see FIRMethodNotImplementedException
*/
+ (void)raiseMethodNotImplementedExceptionWithReason:(nullable NSString *)reason;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthExceptionUtils.h"
/** @var FIRMethodNotImplementedException
@brief The name of the "Method Not Implemented" exception.
*/
static NSString *const FIRMethodNotImplementedException = @"FIRMethodNotImplementedException";
@implementation FIRAuthExceptionUtils
+ (void)raiseInvalidParameterExceptionWithReason:(NSString *)reason {
[NSException raise:NSInvalidArgumentException format:@"%@", reason];
}
+ (void)raiseMethodNotImplementedExceptionWithReason:(nullable NSString *)reason {
NSException *exception =
[NSException exceptionWithName:FIRMethodNotImplementedException reason:reason userInfo:nil];
[exception raise];
}
@end

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** @fn FIRAuthGlobalWorkQueue
@brief Retrieves the global serial work queue for Firebase Auth.
@return The global serial dispatch queue.
@remarks To ensure thread safety, all auth code must be executed in either this global work
queue, or a serial queue that has its target queue set to this work queue. All public method
implementations that may involve contested code shall dispatch to this work queue as the
first thing they do.
*/
extern dispatch_queue_t FIRAuthGlobalWorkQueue(void);
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthGlobalWorkQueue.h"
dispatch_queue_t FIRAuthGlobalWorkQueue() {
static dispatch_once_t once;
static dispatch_queue_t queue;
dispatch_once(&once, ^{
queue = dispatch_queue_create("com.google.firebase.auth.globalWorkQueue", NULL);
});
return queue;
}

View File

@@ -0,0 +1,440 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthErrors.h"
/** @var FIRAuthPublicErrorCodeFlag
@brief Bitmask value indicating the error represents a public error code when this bit is
zeroed. Error codes which don't contain this flag will be wrapped in an @c NSError whose
code is @c FIRAuthErrorCodeInternalError.
*/
static const NSInteger FIRAuthPublicErrorCodeFlag = 1 << 20;
/** @var FIRAuthInternalErrorDomain
@brief The Firebase Auth error domain for internal errors.
*/
extern NSString *const FIRAuthInternalErrorDomain;
/** @var FIRAuthErrorUserInfoDeserializedResponseKey
@brief Errors with the code @c FIRAuthErrorCodeUnexpectedResponseError,
@c FIRAuthErrorCodeUnexpectedErrorResponseError, and
@c FIRAuthInternalErrorCodeRPCResponseDecodingError may contain an @c NSError.userInfo
dictionary which contains this key. The value associated with this key is an object of
unspecified contents containing the deserialized server response.
*/
extern NSString *const FIRAuthErrorUserInfoDeserializedResponseKey;
/** @var FIRAuthErrorUserInfoDataKey
@brief Errors with the code @c FIRAuthErrorCodeUnexpectedResponseError or
@c FIRAuthErrorCodeUnexpectedErrorResponseError may contain an @c NSError.userInfo
dictionary which contains this key. The value associated with this key is an @c NSString
which represents the response from a server to an RPC which could not be deserialized.
*/
extern NSString *const FIRAuthErrorUserInfoDataKey;
/** @var FIRAuthInternalErrorCode
@brief Error codes used internally by Firebase Auth.
@remarks All errors are generated using an internal error code. These errors are automatically
converted to the appropriate public version of the @c NSError by the methods in
@c FIRAuthErrorUtils
*/
typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) {
/** @var FIRAuthInternalErrorCodeNetworkError
@brief Indicates a network error occurred (such as a timeout, interrupted connection, or
unreachable host.)
@remarks These types of errors are often recoverable with a retry.
See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details about
the network error which occurred.
*/
FIRAuthInternalErrorCodeNetworkError = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNetworkError,
/** @var FIRAuthInternalErrorCodeEmailAlreadyInUse
@brief The email used to attempt a sign-up already exists.
*/
FIRAuthInternalErrorCodeEmailAlreadyInUse =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeEmailAlreadyInUse,
/** @var FIRAuthInternalErrorCodeUserDisabled
@brief Indicates the user's account is disabled on the server side.
*/
FIRAuthInternalErrorCodeUserDisabled = FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserDisabled,
/** @var FIRAuthInternalErrorCodeWrongPassword
@brief Indicates the user attempted sign in with a wrong password
*/
FIRAuthInternalErrorCodeWrongPassword =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWrongPassword,
/** @var FIRAuthInternalErrorCodeKeychainError
@brief Indicates an error occurred accessing the keychain.
@remarks The @c NSLocalizedFailureReasonErrorKey field in the @c NSError.userInfo dictionary
will contain more information about the error encountered.
*/
FIRAuthInternalErrorCodeKeychainError =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeKeychainError,
/** @var FIRAuthInternalErrorCodeInternalError
@brief An internal error occurred.
@remarks This value is here for consistency. It's also used to make the implementation of
wrapping internal errors simpler.
*/
FIRAuthInternalErrorCodeInternalError =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInternalError,
/** @var FIRAuthInternalErrorCodeTooManyRequests
@brief Indicates that too many requests were made to a server method.
*/
FIRAuthInternalErrorCodeTooManyRequests =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeTooManyRequests,
/** @var FIRAuthInternalErrorCodeInvalidCustomToken
@brief Indicates a validation error with the custom token.
*/
FIRAuthInternalErrorCodeInvalidCustomToken =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidCustomToken,
/** @var FIRAuthInternalErrorCodeCredentialMismatch
@brief Indicates the service account and the API key belong to different projects.
*/
FIRAuthInternalErrorCodeCustomTokenMismatch =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeCustomTokenMismatch,
/** @var FIRAuthInternalErrorCodeInvalidCredential
@brief Indicates the IDP token or requestUri is invalid.
*/
FIRAuthInternalErrorCodeInvalidCredential =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidCredential,
/** @var FIRAuthInternalErrorCodeRequiresRecentLogin
@brief Indicates the user has attemped to change email or password more than 5 minutes after
signing in.
*/
FIRAuthInternalErrorCodeRequiresRecentLogin =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeRequiresRecentLogin,
/** @var FIRAuthInternalErrorCodeInvalidUserToken
@brief Indicates user's saved auth credential is invalid, the user needs to sign in again.
*/
FIRAuthInternalErrorCodeInvalidUserToken =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidUserToken,
/** @var FIRAuthInternalErrorCodeInvalidEmail
@brief Indicates the email identifier is invalid.
*/
FIRAuthInternalErrorCodeInvalidEmail =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidEmail,
/** @var FIRAuthInternalErrorCodeAccountExistsWithDifferentCredential
@brief Indicates account linking is needed.
*/
FIRAuthInternalErrorCodeAccountExistsWithDifferentCredential =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAccountExistsWithDifferentCredential,
/** @var FIRAuthInternalErrorCodeProviderAlreadyLinked
@brief Indicates an attempt to link a provider to which we are already linked.
*/
FIRAuthInternalErrorCodeProviderAlreadyLinked =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeProviderAlreadyLinked,
/** @var FIRAuthInternalErrorCodeNoSuchProvider
@brief Indicates an attempt to unlink a provider that is not is not linked.
*/
FIRAuthInternalErrorCodeNoSuchProvider =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNoSuchProvider,
/** @var FIRAuthInternalErrorCodeUserTokenExpired
@brief Indicates the token issue time is older than account's valid_since time.
*/
FIRAuthInternalErrorCodeUserTokenExpired =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserTokenExpired,
/** @var FIRAuthInternalErrorCodeUserNotFound
@brief Indicates the user account was been found.
*/
FIRAuthInternalErrorCodeUserNotFound =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserNotFound,
/** @var FIRAuthInternalErrorCodeInvalidAPIKey
@brief Indicates an invalid API Key was supplied in the request.
*/
FIRAuthInternalErrorCodeInvalidAPIKey =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidAPIKey,
/** @var FIRAuthInternalErrorCodeOperationNotAllowed
@brief Indicates that admin disabled sign-in with the specified IDP.
*/
FIRAuthInternalErrorCodeOperationNotAllowed =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeOperationNotAllowed,
/** @var FIRAuthInternalErrorCodeUserMismatch
@brief Indicates that user attempted to reauthenticate with a user other than the current
user.
*/
FIRAuthInternalErrorCodeUserMismatch =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUserMismatch,
/** @var FIRAuthInternalErrorCodeCredentialAlreadyInUse
@brief Indicates an attempt to link with a credential that has already been linked with a
different Firebase account.
*/
FIRAuthInternalErrorCodeCredentialAlreadyInUse =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeCredentialAlreadyInUse,
/** @var FIRAuthInternalErrorCodeWeakPassword
@brief Indicates an attempt to set a password that is considered too weak.
*/
FIRAuthInternalErrorCodeWeakPassword =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWeakPassword,
/** @var FIRAuthInternalErrorCodeAppNotAuthorized
@brief Indicates the App is not authorized to use Firebase Authentication with the
provided API Key.
*/
FIRAuthInternalErrorCodeAppNotAuthorized =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAppNotAuthorized,
/** @var FIRAuthInternalErrorCodeExpiredActionCode
@brief Indicates the OOB code is expired.
*/
FIRAuthInternalErrorCodeExpiredActionCode =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeExpiredActionCode,
/** @var FIRAuthInternalErrorCodeInvalidActionCode
@brief Indicates the OOB code is invalid.
*/
FIRAuthInternalErrorCodeInvalidActionCode =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidActionCode,
/** Indicates that there are invalid parameters in the payload during a "send password reset email
* " attempt.
*/
FIRAuthInternalErrorCodeInvalidMessagePayload =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidMessagePayload,
/** Indicates that the sender email is invalid during a "send password reset email" attempt.
*/
FIRAuthInternalErrorCodeInvalidSender =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidSender,
/** Indicates that the recipient email is invalid.
*/
FIRAuthInternalErrorCodeInvalidRecipientEmail =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidRecipientEmail,
/** Indicates that the iOS bundle ID is missing when a iOS App Store ID is provided.
*/
FIRAuthinternalErrorCodeMissingIosBundleID =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingIosBundleID,
/** Indicates that the android package name is missing when the @c androidInstallApp flag is set
to true.
*/
FIRAuthInternalErrorCodeMissingAndroidPackageName =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingAndroidPackageName,
/** Indicates that the domain specified in the continue URL is not whitelisted in the Firebase
console.
*/
FIRAuthInternalErrorCodeUnauthorizedDomain =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeUnauthorizedDomain,
/** Indicates that the domain specified in the continue URI is not valid.
*/
FIRAuthInternalErrorCodeInvalidContinueURI =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidContinueURI,
/** Indicates that a continue URI was not provided in a request to the backend which requires
one.
*/
FIRAuthInternalErrorCodeMissingContinueURI =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingContinueURI,
/** Indicates that an email address was expected but one was not provided.
*/
FIRAuthInternalErrorCodeMissingEmail =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingEmail,
/** Indicates that a phone number was not provided in a call to @c verifyPhoneNumber:completion:.
*/
FIRAuthInternalErrorCodeMissingPhoneNumber =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingPhoneNumber,
/** Indicates that an invalid phone number was provided in a call to @c
verifyPhoneNumber:completion:.
*/
FIRAuthInternalErrorCodeInvalidPhoneNumber =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidPhoneNumber,
/** Indicates that the phone auth credential was created with an empty verification code.
*/
FIRAuthInternalErrorCodeMissingVerificationCode =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingVerificationCode,
/** Indicates that an invalid verification code was used in the verifyPhoneNumber request.
*/
FIRAuthInternalErrorCodeInvalidVerificationCode =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidVerificationCode,
/** Indicates that the phone auth credential was created with an empty verification ID.
*/
FIRAuthInternalErrorCodeMissingVerificationID =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingVerificationID,
/** Indicates that the APNS device token is missing in the verifyClient request.
*/
FIRAuthInternalErrorCodeMissingAppCredential =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingAppCredential,
/** Indicates that an invalid APNS device token was used in the verifyClient request.
*/
FIRAuthInternalErrorCodeInvalidAppCredential =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidAppCredential,
/** Indicates that the reCAPTCHA token is not valid.
*/
FIRAuthInternalErrorCodeCaptchaCheckFailed =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeCaptchaCheckFailed,
/** Indicates that an invalid verification ID was used in the verifyPhoneNumber request.
*/
FIRAuthInternalErrorCodeInvalidVerificationID =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidVerificationID,
/** Indicates that the quota of SMS messages for a given project has been exceeded.
*/
FIRAuthInternalErrorCodeQuotaExceeded =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeQuotaExceeded,
/** Indicates that an attempt was made to present a new web context while one was already being
presented.
*/
FIRAuthInternalErrorCodeWebContextAlreadyPresented =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWebContextAlreadyPresented,
/** Indicates that the URL presentation was cancelled prematurely by the user.
*/
FIRAuthInternalErrorCodeWebContextCancelled =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWebContextCancelled,
/** Indicates a general failure during the app verification flow.
*/
FIRAuthInternalErrorCodeAppVerificationUserInteractionFailure =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAppVerificationUserInteractionFailure,
/** Indicates that the clientID used to invoke a web flow is invalid.
*/
FIRAuthInternalErrorCodeInvalidClientID =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeInvalidClientID,
/** Indicates that a network request within a SFSafariViewController or UIWebview failed.
*/
FIRAuthInternalErrorCodeWebNetworkRequestFailed =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWebNetworkRequestFailed,
/** Indicates that an internal error occured within a SFSafariViewController or UIWebview.
*/
FIRAuthInternalErrorCodeWebInternalError =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeWebInternalError,
// The enum values between 17046 and 17051 are reserved and should NOT be used for new error
// codes.
/** Indicates that the SMS code has expired
*/
FIRAuthInternalErrorCodeSessionExpired =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeSessionExpired,
FIRAuthInternalErrorCodeMissingAppToken =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingAppToken,
FIRAuthInternalErrorCodeNotificationNotForwarded =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNotificationNotForwarded,
FIRAuthInternalErrorCodeAppNotVerified =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeAppNotVerified,
/** Indicates that a non-null user was expected as an argmument to the operation but a null
user was provided.
*/
FIRAuthInternalErrorCodeNullUser =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeNullUser,
/** @var FIRAuthInternalErrorCodeRPCRequestEncodingError
@brief Indicates an error encoding the RPC request.
@remarks This is typically due to some sort of unexpected input value.
See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details.
*/
FIRAuthInternalErrorCodeRPCRequestEncodingError = 1,
/** @var FIRAuthInternalErrorCodeJSONSerializationError
@brief Indicates an error serializing an RPC request.
@remarks This is typically due to some sort of unexpected input value.
If an @c NSJSONSerialization.isValidJSONObject: check fails, the error will contain no
@c NSUnderlyingError key in the @c NSError.userInfo dictionary. If an error was
encountered calling @c NSJSONSerialization.dataWithJSONObject:options:error:, the
resulting error will be associated with the @c NSUnderlyingError key in the
@c NSError.userInfo dictionary.
*/
FIRAuthInternalErrorCodeJSONSerializationError = 2,
/** @var FIRAuthInternalErrorCodeUnexpectedErrorResponse
@brief Indicates an HTTP error occurred and the data returned either couldn't be deserialized
or couldn't be decoded.
@remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details
about the HTTP error which occurred.
If the response could be deserialized as JSON then the @c NSError.userInfo dictionary will
contain a value for the key @c FIRAuthErrorUserInfoDeserializedResponseKey which is the
deserialized response value.
If the response could not be deserialized as JSON then the @c NSError.userInfo dictionary
will contain values for the @c NSUnderlyingErrorKey and @c FIRAuthErrorUserInfoDataKey
keys.
*/
FIRAuthInternalErrorCodeUnexpectedErrorResponse = 3,
/** @var FIRAuthInternalErrorCodeUnexpectedResponse
@brief Indicates the HTTP response indicated the request was a successes, but the response
contains something other than a JSON-encoded dictionary, or the data type of the response
indicated it is different from the type of response we expected.
@remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary.
If this key is present in the dictionary, it may contain an error from
@c NSJSONSerialization error (indicating the response received was of the wrong data
type).
See the @c FIRAuthErrorUserInfoDeserializedResponseKey value in the @c NSError.userInfo
dictionary. If the response could be deserialized, it's deserialized representation will
be associated with this key. If the @c NSUnderlyingError value in the @c NSError.userInfo
dictionary is @c nil, this indicates the JSON didn't represent a dictionary.
*/
FIRAuthInternalErrorCodeUnexpectedResponse = 4,
/** @var FIRAuthInternalErrorCodeRPCResponseDecodingError
@brief Indicates an error decoding the RPC response.
This is typically due to some sort of unexpected response value from the server.
@remarks See the @c NSUnderlyingError value in the @c NSError.userInfo dictionary for details.
See the @c FIRErrorUserInfoDecodedResponseKey value in the @c NSError.userInfo dictionary.
The deserialized representation of the response will be associated with this key.
*/
FIRAuthInternalErrorCodeRPCResponseDecodingError = 5,
};

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
@brief The protocol for permanant data storage.
*/
@protocol FIRAuthStorage <NSObject>
/** @fn initWithService:
@brief Initialize a @c FIRAuthStorage instance.
@param service The name of the storage service to use.
@return An initialized @c FIRAuthStorage instance for the specified service.
*/
- (id<FIRAuthStorage>)initWithService:(NSString *)service;
/** @fn dataForKey:error:
@brief Gets the data for @c key in the storage. The key is set for the attribute
@c kSecAttrAccount of a generic password query.
@param key The key to use.
@param error The address to store any error that occurs during the process, if not NULL.
If the operation was successful, its content is set to @c nil .
@return The data stored in the storage for @c key, if any.
*/
- (nullable NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error;
/** @fn setData:forKey:error:
@brief Sets the data for @c key in the storage. The key is set for the attribute
@c kSecAttrAccount of a generic password query.
@param data The data to store.
@param key The key to use.
@param error The address to store any error that occurs during the process, if not NULL.
@return Whether the operation succeeded or not.
*/
- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error;
/** @fn removeDataForKey:error:
@brief Removes the data for @c key in the storage. The key is set for the attribute
@c kSecAttrAccount of a generic password query.
@param key The key to use.
@param error The address to store any error that occurs during the process, if not NULL.
@return Whether the operation succeeded or not.
*/
- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error;
@end
/** @class FIRAuthKeychain
@brief The utility class to manipulate data in iOS Keychain.
*/
@interface FIRAuthKeychain : NSObject <FIRAuthStorage>
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,256 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthKeychain.h"
#import <Security/Security.h>
#import "FIRAuthErrorUtils.h"
#import "FIRAuthUserDefaultsStorage.h"
#if FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
#import <UIKit/UIKit.h>
/** @var kOSVersionMatcherForUsingUserDefaults
@brief The regular expression to match all OS versions that @c FIRAuthUserDefaultsStorage is
used instead if available.
*/
static NSString *const kOSVersionMatcherForUsingUserDefaults = @"^10\\.[01](\\..*)?$";
#endif // FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
/** @var kAccountPrefix
@brief The prefix string for keychain item account attribute before the key.
@remarks A number "1" is encoded in the prefix in case we need to upgrade the scheme in future.
*/
static NSString *const kAccountPrefix = @"firebase_auth_1_";
@implementation FIRAuthKeychain {
/** @var _service
@brief The name of the keychain service.
*/
NSString *_service;
/** @var _legacyItemDeletedForKey
@brief Indicates whether or not this class knows that the legacy item for a particular key has
been deleted.
@remarks This dictionary is to avoid unecessary keychain operations against legacy items.
*/
NSMutableDictionary *_legacyEntryDeletedForKey;
}
- (id<FIRAuthStorage>)initWithService:(NSString *)service {
#if FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
NSString *OSVersion = [UIDevice currentDevice].systemVersion;
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:kOSVersionMatcherForUsingUserDefaults
options:0
error:NULL];
if ([regex numberOfMatchesInString:OSVersion options:0 range:NSMakeRange(0, OSVersion.length)]) {
return (id<FIRAuthStorage>)[[FIRAuthUserDefaultsStorage alloc] initWithService:service];
}
#endif // FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
self = [super init];
if (self) {
_service = [service copy];
_legacyEntryDeletedForKey = [[NSMutableDictionary alloc] init];
}
return self;
}
- (NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error {
if (!key.length) {
[NSException raise:NSInvalidArgumentException
format:@"%@", @"The key cannot be nil or empty."];
return nil;
}
NSData *data = [self itemWithQuery:[self genericPasswordQueryWithKey:key] error:error];
if (error && *error) {
return nil;
}
if (data) {
return data;
}
// Check for legacy form.
if (_legacyEntryDeletedForKey[key]) {
return nil;
}
data = [self itemWithQuery:[self legacyGenericPasswordQueryWithKey:key] error:error];
if (error && *error) {
return nil;
}
if (!data) {
// Mark legacy data as non-existing so we don't have to query it again.
_legacyEntryDeletedForKey[key] = @YES;
return nil;
}
// Move the data to current form.
if (![self setData:data forKey:key error:error]) {
return nil;
}
[self deleteLegacyItemWithKey:key];
return data;
}
- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error {
if (!key.length) {
[NSException raise:NSInvalidArgumentException
format:@"%@", @"The key cannot be nil or empty."];
return NO;
}
NSDictionary *attributes = @{
(__bridge id)kSecValueData : data,
(__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
};
return [self setItemWithQuery:[self genericPasswordQueryWithKey:key]
attributes:attributes
error:error];
}
- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error {
if (!key.length) {
[NSException raise:NSInvalidArgumentException
format:@"%@", @"The key cannot be nil or empty."];
return NO;
}
if (![self deleteItemWithQuery:[self genericPasswordQueryWithKey:key] error:error]) {
return NO;
}
// Legacy form item, if exists, also needs to be removed, otherwise it will be exposed when
// current form item is removed, leading to incorrect semantics.
[self deleteLegacyItemWithKey:key];
return YES;
}
#pragma mark - Private
- (NSData *)itemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error {
NSMutableDictionary *returningQuery = [query mutableCopy];
returningQuery[(__bridge id)kSecReturnData] = @YES;
returningQuery[(__bridge id)kSecReturnAttributes] = @YES;
// Using a match limit of 2 means that we can check whether there is more than one item.
// If we used a match limit of 1 we would never find out.
returningQuery[(__bridge id)kSecMatchLimit] = @2;
CFArrayRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)returningQuery,
(CFTypeRef *)&result);
if (status == noErr && result != NULL) {
NSArray *items = (__bridge_transfer NSArray *)result;
if (items.count != 1) {
if (error) {
*error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching"
status:status];
}
return nil;
}
if (error) {
*error = nil;
}
NSDictionary *item = items[0];
return item[(__bridge id)kSecValueData];
}
if (status == errSecItemNotFound) {
if (error) {
*error = nil;
}
} else {
if (error) {
*error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemCopyMatching" status:status];
}
}
return nil;
}
- (BOOL)setItemWithQuery:(NSDictionary *)query
attributes:(NSDictionary *)attributes
error:(NSError **_Nullable)error {
NSMutableDictionary *combined = [attributes mutableCopy];
[combined addEntriesFromDictionary:query];
BOOL hasItem = NO;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)combined, NULL);
if (status == errSecDuplicateItem) {
hasItem = YES;
status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes);
}
if (status == noErr) {
return YES;
}
if (error) {
NSString *function = hasItem ? @"SecItemUpdate" : @"SecItemAdd";
*error = [FIRAuthErrorUtils keychainErrorWithFunction:function status:status];
}
return NO;
}
- (BOOL)deleteItemWithQuery:(NSDictionary *)query error:(NSError **_Nullable)error {
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
if (status == noErr || status == errSecItemNotFound) {
return YES;
}
if (error) {
*error = [FIRAuthErrorUtils keychainErrorWithFunction:@"SecItemDelete" status:status];
}
return NO;
}
/** @fn deleteLegacyItemsWithKey:
@brief Deletes legacy item from the keychain if it is not already known to be deleted.
@param key The key for the item.
*/
- (void)deleteLegacyItemWithKey:(NSString *)key {
if (_legacyEntryDeletedForKey[key]) {
return;
}
NSDictionary *query = [self legacyGenericPasswordQueryWithKey:key];
SecItemDelete((__bridge CFDictionaryRef)query);
_legacyEntryDeletedForKey[key] = @YES;
}
/** @fn genericPasswordQueryWithKey:
@brief Returns a keychain query of generic password to be used to manipulate key'ed value.
@param key The key for the value being manipulated, used as the account field in the query.
*/
- (NSDictionary *)genericPasswordQueryWithKey:(NSString *)key {
return @{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrAccount : [kAccountPrefix stringByAppendingString:key],
(__bridge id)kSecAttrService : _service,
};
}
/** @fn legacyGenericPasswordQueryWithKey:
@brief Returns a keychain query of generic password without service field, which is used by
previous version of this class.
@param key The key for the value being manipulated, used as the account field in the query.
*/
- (NSDictionary *)legacyGenericPasswordQueryWithKey:(NSString *)key {
return @{
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrAccount : key,
};
}
@end

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class FIRAuthAppCredentialManager;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRAuthNotificationForwardingCallback
@brief The type of block to receive whether or not remote notifications are being forwarded.
@param isNotificationBeingForwarded Whether or not remote notifications are being forwarded.
*/
typedef void (^FIRAuthNotificationForwardingCallback)(BOOL isNotificationBeingForwarded);
/** @class FIRAuthNotificationManager
*/
@interface FIRAuthNotificationManager : NSObject
/** @property timeout
@brief The timeout for checking for notification forwarding.
@remarks Only tests should access this property.
*/
@property(nonatomic, assign) NSTimeInterval timeout;
/** @fn initWithApplication:appCredentialManager:
@brief Initializes the instance.
@param application The application.
@param appCredentialManager The object to handle app credentials delivered via notification.
@return The initialized instance.
*/
- (instancetype)initWithApplication:(UIApplication *)application
appCredentialManager:(FIRAuthAppCredentialManager *)appCredentialManager
NS_DESIGNATED_INITIALIZER;
/** @fn init
@brief please use initWithAppCredentialManager: instead.
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn checkNotificationForwardingWithCallback:
@brief Checks whether or not remote notifications are being forwarded to this class.
@param callback The block to be called either immediately or in future once a result
is available.
*/
- (void)checkNotificationForwardingWithCallback:(FIRAuthNotificationForwardingCallback)callback;
/** @fn canHandleNotification:
@brief Attempts to handle the remote notification.
@param notification The notification in question.
@return Whether or the notification has been handled.
*/
- (BOOL)canHandleNotification:(NSDictionary *)notification;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,177 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthNotificationManager.h"
#import <FirebaseCore/FIRLogger.h>
#import "FIRAuthAppCredential.h"
#import "FIRAuthAppCredentialManager.h"
#import "FIRAuthGlobalWorkQueue.h"
NS_ASSUME_NONNULL_BEGIN
/** @var kNotificationKey
@brief The key to locate payload data in the remote notification.
*/
static NSString *const kNotificationDataKey = @"com.google.firebase.auth";
/** @var kNotificationReceiptKey
@brief The key for the receipt in the remote notification payload data.
*/
static NSString *const kNotificationReceiptKey = @"receipt";
/** @var kNotificationSecretKey
@brief The key for the secret in the remote notification payload data.
*/
static NSString *const kNotificationSecretKey = @"secret";
/** @var kNotificationProberKey
@brief The key for marking the prober in the remote notification payload data.
*/
static NSString *const kNotificationProberKey = @"warning";
/** @var kProbingTimeout
@brief Timeout for probing whether the app delegate forwards the remote notification to us.
*/
static const NSTimeInterval kProbingTimeout = 1;
@implementation FIRAuthNotificationManager {
/** @var _application
@brief The application.
*/
UIApplication *_application;
/** @var _appCredentialManager
@brief The object to handle app credentials delivered via notification.
*/
FIRAuthAppCredentialManager *_appCredentialManager;
/** @var _hasCheckedNotificationForwarding
@brief Whether notification forwarding has been checked or not.
*/
BOOL _hasCheckedNotificationForwarding;
/** @var _isNotificationBeingForwarded
@brief Whether or not notification is being forwarded
*/
BOOL _isNotificationBeingForwarded;
/** @var _pendingCallbacks
@brief All pending callbacks while a check is being performed.
*/
NSMutableArray<FIRAuthNotificationForwardingCallback> *_pendingCallbacks;
}
- (instancetype)initWithApplication:(UIApplication *)application
appCredentialManager:(FIRAuthAppCredentialManager *)appCredentialManager {
self = [super init];
if (self) {
_application = application;
_appCredentialManager = appCredentialManager;
_timeout = kProbingTimeout;
}
return self;
}
- (void)checkNotificationForwardingWithCallback:(FIRAuthNotificationForwardingCallback)callback {
if (_pendingCallbacks) {
[_pendingCallbacks addObject:callback];
return;
}
if (_hasCheckedNotificationForwarding) {
callback(_isNotificationBeingForwarded);
return;
}
_hasCheckedNotificationForwarding = YES;
_pendingCallbacks =
[[NSMutableArray<FIRAuthNotificationForwardingCallback> alloc] initWithObjects:callback, nil];
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary *proberNotification = @{
kNotificationDataKey : @{
kNotificationProberKey : @"This fake notification should be forwarded to Firebase Auth."
}
};
if ([self->_application.delegate respondsToSelector:
@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]) {
[self->_application.delegate application:self->_application
didReceiveRemoteNotification:proberNotification
fetchCompletionHandler:^(UIBackgroundFetchResult result) {}];
#if !TARGET_OS_TV
} else if ([self->_application.delegate respondsToSelector:
@selector(application:didReceiveRemoteNotification:)]) {
[self->_application.delegate application:self->_application
didReceiveRemoteNotification:proberNotification];
#endif
} else {
FIRLogWarning(kFIRLoggerAuth, @"I-AUT000015",
@"The UIApplicationDelegate must handle remote notification for phone number "
@"authentication to work.");
}
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_timeout * NSEC_PER_SEC)),
FIRAuthGlobalWorkQueue(), ^{
[self callBack];
});
}
- (BOOL)canHandleNotification:(NSDictionary *)notification {
NSDictionary *data = notification[kNotificationDataKey];
if ([data isKindOfClass:[NSString class]]) {
// Deserialize in case the data is a JSON string.
NSData *JSONData = [((NSString *)data) dataUsingEncoding:NSUTF8StringEncoding];
data = [NSJSONSerialization JSONObjectWithData:JSONData options:0 error:NULL];
}
if (![data isKindOfClass:[NSDictionary class]]) {
return NO;
}
if (data[kNotificationProberKey]) {
if (!_pendingCallbacks) {
// The prober notification probably comes from another instance, so pass it along.
return NO;
}
_isNotificationBeingForwarded = YES;
[self callBack];
return YES;
}
NSString *receipt = data[kNotificationReceiptKey];
if (![receipt isKindOfClass:[NSString class]]) {
return NO;
}
NSString *secret = data[kNotificationSecretKey];
if (![receipt isKindOfClass:[NSString class]]) {
return NO;
}
return [_appCredentialManager canFinishVerificationWithReceipt:receipt secret:secret];
}
#pragma mark - Internal methods
/** @fn callBack
@brief Calls back all pending callbacks with the result of notification forwarding check.
*/
- (void)callBack {
if (!_pendingCallbacks) {
return;
}
NSArray<FIRAuthNotificationForwardingCallback> *allCallbacks = _pendingCallbacks;
_pendingCallbacks = nil;
for (FIRAuthNotificationForwardingCallback callback in allCallbacks) {
callback(_isNotificationBeingForwarded);
}
};
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
@brief Indicates the type of operation performed for RPCs that support the operation
parameter.
*/
typedef NS_ENUM(NSInteger, FIRAuthOperationType) {
/** Indicates that the operation type is uspecified.
*/
FIRAuthOperationTypeUnspecified = 0,
/** Indicates that the operation type is sign in or sign up.
*/
FIRAuthOperationTypeSignUpOrSignIn = 1,
/** Indicates that the operation type is reauthentication.
*/
FIRAuthOperationTypeReauth = 2,
/** Indicates that the operation type is update.
*/
FIRAuthOperationTypeUpdate = 3,
/** Indicates that the operation type is link.
*/
FIRAuthOperationTypeLink = 4,
};
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#pragma mark - Provider ID constants
// Declared 'extern' in FIRGoogleAuthProvider.h
NSString *const FIRGoogleAuthProviderID = @"google.com";
// Declared 'extern' in FIRFacebookAuthProvider.h
NSString *const FIRFacebookAuthProviderID = @"facebook.com";
// Declared 'extern' in FIREmailAuthProvider.h
NSString *const FIREmailAuthProviderID = @"password";
// Declared 'extern' in FIREmailAuthProvider.h
NSString *const FIREmailPasswordAuthProviderID = @"password";
// Declared 'extern' in FIRTwitterAuthProvider.h
NSString *const FIRTwitterAuthProviderID = @"twitter.com";
// Declared 'extern' in FIRGitHubAuthProvider.h
NSString *const FIRGitHubAuthProviderID = @"github.com";
// Declared 'extern' in FIRPhoneAuthProvider.h
NSString *const FIRPhoneAuthProviderID = @"phone";
#pragma mark - sign-in methods constants
// Declared 'extern' in FIRGoogleAuthProvider.h
NSString *const FIRGoogleAuthSignInMethod = @"google.com";
// Declared 'extern' in FIREmailAuthProvider.h
NSString *const FIREmailPasswordAuthSignInMethod = @"password";
// Declared 'extern' in FIREmailAuthProvider.h
NSString *const FIREmailLinkAuthSignInMethod = @"emailLink";
// Declared 'extern' in FIRTwitterAuthProvider.h
NSString *const FIRTwitterAuthSignInMethod = @"twitter.com";
// Declared 'extern' in FIRFacebookAuthProvider.h
NSString *const FIRFacebookAuthSignInMethod = @"facebook.com";
// Declared 'extern' in FIRGitHubAuthProvider.h
NSString *const FIRGitHubAuthSignInMethod = @"github.com";
// Declared 'extern' in FIRPhoneAuthProvider.h
NSString *const FIRPhoneAuthSignInMethod = @"phone";

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRAuthSerialTaskCompletionBlock
@brief The type of method a @c FIRAuthSerialTask must call when it is complete.
*/
typedef void (^FIRAuthSerialTaskCompletionBlock)(void);
/** @typedef FIRAuthSerialTask
@brief Represents a unit of work submitted to a task queue.
@param complete The task MUST call the complete method when done.
*/
typedef void (^FIRAuthSerialTask)(FIRAuthSerialTaskCompletionBlock complete);
/** @class FIRAuthSerialTaskQueue
@brief An easy to use serial task queue which supports a callback-based completion notification
system for easy asyncronous call chaining.
*/
@interface FIRAuthSerialTaskQueue : NSObject
/** @fn enqueueTask:
@brief Enqueues a task for serial execution in the queue.
@remarks The task MUST call the complete method when done. This method is thread-safe.
The task block won't be executed concurrently with any other blocks in other task queues or
the global work queue as returned by @c FIRAuthGlobalWorkQueue , but an uncompleted task
(e.g. task block finished executation before complete method is called at a later time)
does not affect other task queues or the global work queue.
*/
- (void)enqueueTask:(FIRAuthSerialTask)task;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthSerialTaskQueue.h"
#import "FIRAuthGlobalWorkQueue.h"
@implementation FIRAuthSerialTaskQueue {
/** @var _dispatchQueue
@brief The asyncronous dispatch queue into which tasks are enqueued and processed
serially.
*/
dispatch_queue_t _dispatchQueue;
}
- (instancetype)init {
self = [super init];
if (self) {
_dispatchQueue = dispatch_queue_create("com.google.firebase.auth.serialTaskQueue", NULL);
dispatch_set_target_queue(_dispatchQueue, FIRAuthGlobalWorkQueue());
}
return self;
}
- (void)enqueueTask:(FIRAuthSerialTask)task {
// This dispatch queue will run tasks serially in FIFO order, as long as it's not suspended.
dispatch_async(self->_dispatchQueue, ^{
// But as soon as a task is started, stop other tasks from running until the task calls it's
// completion handler, which allows the queue to resume processing of tasks. This allows the
// task to perform other asyncronous actions on other dispatch queues and "get back to us" when
// all of their sub-tasks are complete.
dispatch_suspend(self->_dispatchQueue);
task(^{
dispatch_resume(self->_dispatchQueue);
});
});
}
@end

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthSettings.h"
@implementation FIRAuthSettings
- (instancetype)init {
self = [super init];
if (self) {
_appVerificationDisabledForTesting = NO;
}
return self;
}
@end

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthTokenResult_Internal.h"
NS_ASSUME_NONNULL_BEGIN
/** @var kExpirationDateKey
@brief The key used to encode the expirationDate property for NSSecureCoding.
*/
static NSString *const kExpirationDateKey = @"expiratinDate";
/** @var kTokenKey
@brief The key used to encode the token property for NSSecureCoding.
*/
static NSString *const kTokenKey = @"token";
/** @var kAuthDateKey
@brief The key used to encode the authDate property for NSSecureCoding.
*/
static NSString *const kAuthDateKey = @"authDate";
/** @var kIssuedDateKey
@brief The key used to encode the issuedDate property for NSSecureCoding.
*/
static NSString *const kIssuedDateKey = @"issuedDate";
/** @var kSignInProviderKey
@brief The key used to encode the signInProvider property for NSSecureCoding.
*/
static NSString *const kSignInProviderKey = @"signInProvider";
/** @var kClaimsKey
@brief The key used to encode the claims property for NSSecureCoding.
*/
static NSString *const kClaimsKey = @"claims";
@implementation FIRAuthTokenResult
- (instancetype)initWithToken:(NSString *)token
expirationDate:(NSDate *)expirationDate
authDate:(NSDate *)authDate
issuedAtDate:(NSDate *)issuedAtDate
signInProvider:(NSString *)signInProvider
claims:(NSDictionary *)claims {
self = [super init];
if (self) {
_token = token;
_expirationDate = expirationDate;
_authDate = authDate;
_issuedAtDate = issuedAtDate;
_signInProvider = signInProvider;
_claims = claims;
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *token =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kTokenKey];
NSDate *expirationDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kExpirationDateKey];
NSDate *authDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kAuthDateKey];
NSDate *issuedAtDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kAuthDateKey];
NSString *signInProvider =
[aDecoder decodeObjectOfClass:[NSString class] forKey:kSignInProviderKey];
NSDictionary<NSString *, NSString *> *claims =
[aDecoder decodeObjectOfClass:[NSDictionary<NSString *, NSString *> class] forKey:kClaimsKey];
return [self initWithToken:token
expirationDate:expirationDate
authDate:authDate
issuedAtDate:issuedAtDate
signInProvider:signInProvider
claims:claims];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_token forKey:kTokenKey];
[aCoder encodeObject:_expirationDate forKey:kExpirationDateKey];
[aCoder encodeObject:_authDate forKey:kAuthDateKey];
[aCoder encodeObject:_issuedAtDate forKey:kIssuedDateKey];
[aCoder encodeObject:_signInProvider forKey:kSignInProviderKey];
[aCoder encodeObject:_claims forKey:kClaimsKey];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuthTokenResult.h"
NS_ASSUME_NONNULL_BEGIN
/** @extension FIRAuthAPNSTokenResult
@brief An internal class used to expose internal methods of FIRAuthAPNSTokenResult.
*/
@interface FIRAuthTokenResult () <NSSecureCoding>
- (instancetype)initWithToken:(NSString *)token
expirationDate:(NSDate *)expirationDate
authDate:(NSDate *)authDate
issuedAtDate:(NSDate *)issuedAtDate
signInProvider:(NSString *)signInProvider
claims:(NSDictionary *)claims;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@protocol FIRAuthUIDelegate;
/** @typedef FIRAuthURLPresentationCompletion
@brief The type of block invoked when the URLPresentation completes.
@param callbackURL The callback URL if the presentation ends with a matching callback.
@param error The error if the presentation fails to start or ends with an error.
*/
typedef void (^FIRAuthURLPresentationCompletion)(NSURL *_Nullable callbackURL,
NSError *_Nullable error);
/** @typedef FIRAuthCallbackMatcher
@brief The type of block invoked for checking whether a callback URL matches.
@param callbackURL The callback URL to check for match.
@return Whether or not the specific callback URL matches or not.
*/
typedef BOOL (^FIRAuthURLCallbackMatcher)(NSURL * _Nullable callbackURL);
/** @class FIRAuthURLPresenter
@brief A Class responsible for presenting URL via SFSafariViewController or UIWebView.
*/
@interface FIRAuthURLPresenter : NSObject
/** @fn presentURL:UIDelegate:callbackMatcher:completion:
@brief Presents an URL to interact with user.
@param URL The URL to present.
@param UIDelegate The UI delegate to present view controller.
@param completion A block to be called either synchronously if the presentation fails to start,
or asynchronously in future on an unspecified thread once the presentation finishes.
*/
- (void)presentURL:(NSURL *)URL
UIDelegate:(nullable id<FIRAuthUIDelegate>)UIDelegate
callbackMatcher:(FIRAuthURLCallbackMatcher)callbackMatcher
completion:(FIRAuthURLPresentationCompletion)completion;
/** @fn canHandleURL:
@brief Determines if a URL was produced by the currently presented URL.
@param URL The URL to handle.
@return Whether the URL could be handled or not.
*/
- (BOOL)canHandleURL:(NSURL *)URL;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,190 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthURLPresenter.h"
#import <SafariServices/SafariServices.h>
#import "FIRAuthDefaultUIDelegate.h"
#import "FIRAuthErrorUtils.h"
#import "FIRAuthGlobalWorkQueue.h"
#import "FIRAuthUIDelegate.h"
#import "FIRAuthWebViewController.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuthURLPresenter () <SFSafariViewControllerDelegate,
FIRAuthWebViewControllerDelegate>
@end
// Disable unguarded availability warnings because SFSafariViewController is been used throughout
// the code, including as an iVar, which cannot be simply excluded by @available check.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
@implementation FIRAuthURLPresenter {
/** @var _isPresenting
@brief Whether or not some web-based content is being presented.
*/
BOOL _isPresenting;
/** @var _callbackMatcher
@brief The callback URL matcher for the current presentation, if one is active.
*/
FIRAuthURLCallbackMatcher _Nullable _callbackMatcher;
/** @var _safariViewController
@brief The SFSafariViewController used for the current presentation, if any.
*/
SFSafariViewController *_Nullable _safariViewController;
/** @var _webViewController
@brief The FIRAuthWebViewController used for the current presentation, if any.
*/
FIRAuthWebViewController *_Nullable _webViewController;
/** @var _UIDelegate
@brief The UIDelegate used to present the SFSafariViewController.
*/
id<FIRAuthUIDelegate> _UIDelegate;
/** @var _completion
@brief The completion handler for the current presentaion, if one is active.
@remarks This variable is also used as a flag to indicate a presentation is active.
*/
FIRAuthURLPresentationCompletion _Nullable _completion;
}
- (void)presentURL:(NSURL *)URL
UIDelegate:(nullable id<FIRAuthUIDelegate>)UIDelegate
callbackMatcher:(FIRAuthURLCallbackMatcher)callbackMatcher
completion:(FIRAuthURLPresentationCompletion)completion {
if (_isPresenting) {
// Unable to start a new presentation on top of another.
_completion(nil, [FIRAuthErrorUtils webContextAlreadyPresentedErrorWithMessage:nil]);
return;
}
_isPresenting = YES;
_callbackMatcher = callbackMatcher;
_completion = completion;
dispatch_async(dispatch_get_main_queue(), ^() {
self->_UIDelegate = UIDelegate ?: [FIRAuthDefaultUIDelegate defaultUIDelegate];
if ([SFSafariViewController class]) {
self->_safariViewController = [[SFSafariViewController alloc] initWithURL:URL];
self->_safariViewController.delegate = self;
[self->_UIDelegate presentViewController:self->_safariViewController
animated:YES
completion:nil];
return;
} else {
self->_webViewController = [[FIRAuthWebViewController alloc] initWithURL:URL delegate:self];
UINavigationController *navController =
[[UINavigationController alloc] initWithRootViewController:self->_webViewController];
[self->_UIDelegate presentViewController:navController animated:YES completion:nil];
}
});
}
- (BOOL)canHandleURL:(NSURL *)URL {
if (_isPresenting && _callbackMatcher && _callbackMatcher(URL)) {
[self finishPresentationWithURL:URL error:nil];
return YES;
}
return NO;
}
#pragma mark - SFSafariViewControllerDelegate
- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller {
dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
if (controller == self->_safariViewController) {
self->_safariViewController = nil;
//TODO:Ensure that the SFSafariViewController is actually removed from the screen before
//invoking finishPresentationWithURL:error:
[self finishPresentationWithURL:nil
error:[FIRAuthErrorUtils webContextCancelledErrorWithMessage:nil]];
}
});
}
#pragma mark - FIRAuthwebViewControllerDelegate
- (BOOL)webViewController:(FIRAuthWebViewController *)webViewController canHandleURL:(NSURL *)URL {
__block BOOL result = NO;
dispatch_sync(FIRAuthGlobalWorkQueue(), ^() {
if (webViewController == self->_webViewController) {
result = [self canHandleURL:URL];
}
});
return result;
}
- (void)webViewControllerDidCancel:(FIRAuthWebViewController *)webViewController {
dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
if (webViewController == self->_webViewController) {
[self finishPresentationWithURL:nil
error:[FIRAuthErrorUtils webContextCancelledErrorWithMessage:nil]];
}
});
}
- (void)webViewController:(FIRAuthWebViewController *)webViewController
didFailWithError:(NSError *)error {
dispatch_async(FIRAuthGlobalWorkQueue(), ^() {
if (webViewController == self->_webViewController) {
[self finishPresentationWithURL:nil error:error];
}
});
}
#pragma mark - Private methods
/** @fn finishPresentationWithURL:error:
@brief Finishes the presentation for a given URL, if any.
@param URL The URL to finish presenting.
@param error The error with which to finish presenting, if any.
*/
- (void)finishPresentationWithURL:(nullable NSURL *)URL
error:(nullable NSError *)error {
_callbackMatcher = nil;
id<FIRAuthUIDelegate> UIDelegate = _UIDelegate;
_UIDelegate = nil;
FIRAuthURLPresentationCompletion completion = _completion;
_completion = nil;
void (^finishBlock)(void) = ^() {
self->_isPresenting = NO;
completion(URL, error);
};
SFSafariViewController *safariViewController = _safariViewController;
_safariViewController = nil;
FIRAuthWebViewController *webViewController = _webViewController;
_webViewController = nil;
if (safariViewController || webViewController) {
dispatch_async(dispatch_get_main_queue(), ^() {
[UIDelegate dismissViewControllerAnimated:YES completion:^() {
dispatch_async(FIRAuthGlobalWorkQueue(), finishBlock);
}];
});
} else {
finishBlock();
}
}
#pragma clang diagnostic pop // ignored "-Wunguarded-availability"
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
// This class is only available in the simulator.
#if TARGET_OS_SIMULATOR
#ifndef FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
#define FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE 1
#endif
#endif
#if FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
#import "FIRAuthKeychain.h"
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthUserDefaultsStorage
@brief The utility class to storage data in NSUserDefaults.
*/
@interface FIRAuthUserDefaultsStorage : NSObject <FIRAuthStorage>
/** @fn clear
@brief Clears all data from the storage.
@remarks This method is only supposed to be called from tests.
*/
- (void)clear;
@end
NS_ASSUME_NONNULL_END
#endif // FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthUserDefaultsStorage.h"
#if FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE
NS_ASSUME_NONNULL_BEGIN
static NSString *const kPersistentDomainNamePrefix = @"com.google.Firebase.Auth.";
@implementation FIRAuthUserDefaultsStorage {
/** @var _persistentDomainName
@brief The name of the persistent domain in user defaults.
*/
NSString *_persistentDomainName;
/** @var _storage
@brief The backing NSUserDefaults storage for this instance.
*/
NSUserDefaults *_storage;
}
- (id<FIRAuthStorage>)initWithService:(NSString *)service {
self = [super init];
if (self) {
_persistentDomainName = [kPersistentDomainNamePrefix stringByAppendingString:service];
_storage = [[NSUserDefaults alloc] init];
}
return self;
}
- (nullable NSData *)dataForKey:(NSString *)key error:(NSError **_Nullable)error {
if (error) {
*error = nil;
}
NSDictionary<NSString *, id> *allData = [_storage persistentDomainForName:_persistentDomainName];
return allData[key];
}
- (BOOL)setData:(NSData *)data forKey:(NSString *)key error:(NSError **_Nullable)error {
NSMutableDictionary<NSString *, id> *allData =
[([_storage persistentDomainForName:_persistentDomainName] ?: @{}) mutableCopy];
allData[key] = data;
[_storage setPersistentDomain:allData forName:_persistentDomainName];
return YES;
}
- (BOOL)removeDataForKey:(NSString *)key error:(NSError **_Nullable)error {
NSMutableDictionary<NSString *, id> *allData =
[[_storage persistentDomainForName:_persistentDomainName] mutableCopy];
[allData removeObjectForKey:key];
[_storage setPersistentDomain:allData forName:_persistentDomainName];
return YES;
}
- (void)clear {
[_storage setPersistentDomain:@{} forName:_persistentDomainName];
}
@end
NS_ASSUME_NONNULL_END
#endif // FIRAUTH_USER_DEFAULTS_STORAGE_AVAILABLE

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@class FIRAuthRequestConfiguration;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRFetchAuthDomainCallback
@brief The callback invoked at the end of the flow to fetch the Auth domain.
@param authDomain The Auth domain.
@param error The error that occured while fetching the auth domain, if any.
*/
typedef void (^FIRFetchAuthDomainCallback)(NSString *_Nullable authDomain,
NSError *_Nullable error);
/** @class FIRAuthURLUtils
@brief A utility class used to facilitate the creation of auth related URLs.
*/
@interface FIRAuthWebUtils : NSObject
/** @fn randomStringWithLength:
@brief Generates a random string of a specified length.
*/
+ (NSString *)randomStringWithLength:(NSUInteger)length;
/** @fn isCallbackSchemeRegisteredForCustomURLScheme:
@brief Checks whether or not the provided custom URL scheme has been registered by the app.
@param URLScheme The custom URL scheme to be checked against all custom URL schemes registered by the app.
@return whether or not the provided custom URL scheme has been registered by the app.
*/
+ (BOOL)isCallbackSchemeRegisteredForCustomURLScheme:(NSString *)URLScheme;
/** @fn fetchAuthDomainWithCompletion:completion:
@brief Fetches the auth domain associated with the Firebase Project.
@param completion The callback invoked after the auth domain has been constructed or an error
has been encountered.
*/
+ (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
completion:(FIRFetchAuthDomainCallback)completion;
/** @fn queryItemValue:from:
@brief Utility function to get a value from a NSURLQueryItem array.
@param name The key.
@param queryList The NSURLQueryItem array.
@return The value for the key.
*/
+ (NSString *)queryItemValue:(NSString *)name from:(NSArray<NSURLQueryItem *> *)queryList;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,100 @@
/*
* Copyright 2018 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthWebUtils.h"
#import "FIRAuthBackend.h"
#import "FIRAuthErrorUtils.h"
#import "FIRGetProjectConfigRequest.h"
#import "FIRGetProjectConfigResponse.h"
/** @var kAuthDomainSuffix
@brief The suffix of the auth domain pertiaining to a given Firebase project.
*/
static NSString *const kAuthDomainSuffix = @"firebaseapp.com";
@implementation FIRAuthWebUtils
+ (NSString *)randomStringWithLength:(NSUInteger)length {
NSMutableString *randomString = [[NSMutableString alloc] init];
for (int i=0; i < length; i++) {
[randomString appendString:
[NSString stringWithFormat:@"%c", 'a' + arc4random_uniform('z' - 'a' + 1)]];
}
return randomString;
}
+ (BOOL)isCallbackSchemeRegisteredForCustomURLScheme:(NSString *)URLScheme {
NSString *expectedCustomScheme = [URLScheme lowercaseString];
NSArray *urlTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
for (NSDictionary *urlType in urlTypes) {
NSArray *urlTypeSchemes = urlType[@"CFBundleURLSchemes"];
for (NSString *urlTypeScheme in urlTypeSchemes) {
if ([urlTypeScheme.lowercaseString isEqualToString:expectedCustomScheme]) {
return YES;
}
}
}
return NO;
}
+ (void)fetchAuthDomainWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
completion:(FIRFetchAuthDomainCallback)completion {
FIRGetProjectConfigRequest *request =
[[FIRGetProjectConfigRequest alloc] initWithRequestConfiguration:requestConfiguration];
[FIRAuthBackend getProjectConfig:request
callback:^(FIRGetProjectConfigResponse *_Nullable response,
NSError *_Nullable error) {
if (error) {
completion(nil, error);
return;
}
NSString *authDomain;
for (NSString *domain in response.authorizedDomains) {
NSInteger index = domain.length - kAuthDomainSuffix.length;
if (index >= 2) {
if ([domain hasSuffix:kAuthDomainSuffix] && domain.length >= kAuthDomainSuffix.length + 2) {
authDomain = domain;
break;
}
}
}
if (!authDomain.length) {
completion(nil, [FIRAuthErrorUtils unexpectedErrorResponseWithDeserializedResponse:response]);
return;
}
completion(authDomain, nil);
}];
}
/** @fn queryItemValue:from:
@brief Utility function to get a value from a NSURLQueryItem array.
@param name The key.
@param queryList The NSURLQueryItem array.
@return The value for the key.
*/
+ (NSString *)queryItemValue:(NSString *)name from:(NSArray<NSURLQueryItem *> *)queryList {
for (NSURLQueryItem *item in queryList) {
if ([item.name isEqualToString:name]) {
return item.value;
}
}
return nil;
}
@end

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/** @class FIRAuthWebView
@brief A class reponsible for creating a UIWebview for use within Firebase Auth.
*/
@interface FIRAuthWebView : UIView
/** @property webView
* @brief The web view.
*/
@property(nonatomic, weak) UIWebView *webView;
/** @property spinner
* @brief The spinner that indicates web view loading.
*/
@property(nonatomic, weak) UIActivityIndicatorView *spinner;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthWebView.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRAuthWebView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
[self initializeSubviews];
}
return self;
}
/** @fn initializeSubviews
@brief Initializes the subviews of this view.
*/
- (void)initializeSubviews {
UIWebView *webView = [self createWebView];
UIActivityIndicatorView *spinner = [self createSpinner];
// The order of the following controls z-order.
[self addSubview:webView];
[self addSubview:spinner];
[self layoutSubviews];
_webView = webView;
_spinner = spinner;
}
- (void)layoutSubviews {
CGFloat height = self.bounds.size.height;
CGFloat width = self.bounds.size.width;
_webView.frame = CGRectMake(0, 0, width, height);
_spinner.center = _webView.center;
}
/** @fn createWebView
@brief Creates a web view to be used by this view.
@return The newly created web view.
*/
- (UIWebView *)createWebView {
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero];
// Trickery to make the web view not do weird things (like showing a black background when
// the prompt in the navigation bar animates changes.)
webView.opaque = NO;
webView.backgroundColor = [UIColor clearColor];
webView.scrollView.opaque = NO;
webView.scrollView.backgroundColor = [UIColor clearColor];
webView.scrollView.bounces = NO;
webView.scrollView.alwaysBounceVertical = NO;
webView.scrollView.alwaysBounceHorizontal = NO;
return webView;
}
/** @fn createSpinner
@brief Creates a spinner to be used by this view.
@return The newly created spinner.
*/
- (UIActivityIndicatorView *)createSpinner {
UIActivityIndicatorViewStyle spinnerStyle = UIActivityIndicatorViewStyleGray;
UIActivityIndicatorView *spinner =
[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:spinnerStyle];
return spinner;
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <UIKit/UIKit.h>
@class FIRAuthWebViewController;
NS_ASSUME_NONNULL_BEGIN
/** @protocol FIRAuthWebViewControllerDelegate
@brief Defines a delegate for FIRAuthWebViewController
*/
@protocol FIRAuthWebViewControllerDelegate <NSObject>
/** @fn webViewController:canHandleURL:
@brief Determines if a URL should be handled by the delegate.
@param URL The URL to handle.
@return Whether the URL could be handled or not.
*/
- (BOOL)webViewController:(FIRAuthWebViewController *)webViewController canHandleURL:(NSURL *)URL;
/** @fn webViewControllerDidCancel:
@brief Notifies the delegate that the web view controller is being cancelled by the user.
@param webViewController The web view controller in question.
*/
- (void)webViewControllerDidCancel:(FIRAuthWebViewController *)webViewController;
/** @fn webViewController:didFailWithError:
@brief Notifies the delegate that the web view controller failed to load a page.
@param webViewController The web view controller in question.
@param error The error that has occurred.
*/
- (void)webViewController:(FIRAuthWebViewController *)webViewController
didFailWithError:(NSError *)error;
@end
/** @class FIRAuthWebViewController
@brief Reponsible for creating a UIViewController for presenting a FIRAutWebView.
*/
@interface FIRAuthWebViewController : UIViewController
/** @fn initWithNibName:bundle:
* @brief Please call initWithURL:delegate:
*/
- (instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
/** @fn initWithCoder:
* @brief Please call initWithURL:delegate:
*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder NS_UNAVAILABLE;
- (instancetype)initWithURL:(NSURL *)URL
delegate:(__weak id<FIRAuthWebViewControllerDelegate>)delegate
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,111 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRAuthWebViewController.h"
#import "FIRAuthWebView.h"
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuthWebViewController () <UIWebViewDelegate>
@end
@implementation FIRAuthWebViewController {
/** @var _URL
@brief The initial URL to display.
*/
NSURL *_URL;
/** @var _delegate
@brief The delegate to call.
*/
__weak id<FIRAuthWebViewControllerDelegate> _delegate;
/** @var _webView;
@brief The web view instance for easier access.
*/
__weak FIRAuthWebView *_webView;
}
- (instancetype)initWithURL:(NSURL *)URL
delegate:(__weak id<FIRAuthWebViewControllerDelegate>)delegate {
self = [super initWithNibName:nil bundle:nil];
if (self) {
_URL = URL;
_delegate = delegate;
}
return self;
}
#pragma mark - Lifecycle
- (void)loadView {
FIRAuthWebView *webView = [[FIRAuthWebView alloc] initWithFrame:[UIScreen mainScreen].bounds];
webView.webView.delegate = self;
self.view = webView;
_webView = webView;
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
target:self
action:@selector(cancel)];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Loads the requested URL in the web view.
[_webView.webView loadRequest:[NSURLRequest requestWithURL:_URL]];
}
#pragma mark - UI Targets
- (void)cancel {
[_delegate webViewControllerDidCancel:self];
}
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
return ![_delegate webViewController:self canHandleURL:request.URL];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
// Show & animate the activity indicator.
_webView.spinner.hidden = NO;
[_webView.spinner startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// Hide & stop the activity indicator.
_webView.spinner.hidden = YES;
[_webView.spinner stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorCancelled) {
// It's okay for the page to be redirected before it is completely loaded. See b/32028062 .
return;
}
// Forward notification to our delegate.
[self webViewDidFinishLoad:webView];
[_delegate webViewController:self didFailWithError:error];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,120 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRAuth.h"
@class FIRAuthRequestConfiguration;
#if TARGET_OS_IOS
@class FIRAuthAPNSTokenManager;
@class FIRAuthAppCredentialManager;
@class FIRAuthNotificationManager;
@class FIRAuthURLPresenter;
#endif
NS_ASSUME_NONNULL_BEGIN
@interface FIRAuth ()
/** @property requestConfiguration
@brief The configuration object comprising of paramters needed to make a request to Firebase
Auth's backend.
*/
@property(nonatomic, copy, readonly) FIRAuthRequestConfiguration *requestConfiguration;
#if TARGET_OS_IOS
/** @property tokenManager
@brief The manager for APNs tokens used by phone number auth.
*/
@property(nonatomic, strong, readonly) FIRAuthAPNSTokenManager *tokenManager;
/** @property appCredentailManager
@brief The manager for app credentials used by phone number auth.
*/
@property(nonatomic, strong, readonly) FIRAuthAppCredentialManager *appCredentialManager;
/** @property notificationManager
@brief The manager for remote notifications used by phone number auth.
*/
@property(nonatomic, strong, readonly) FIRAuthNotificationManager *notificationManager;
/** @property authURLPresenter
@brief An object that takes care of presenting URLs via the auth instance.
*/
@property(nonatomic, strong, readonly) FIRAuthURLPresenter *authURLPresenter;
#endif // TARGET_OS_IOS
/** @fn initWithAPIKey:appName:
@brief Designated initializer.
@param APIKey The Google Developers Console API key for making requests from your app.
@param appName The name property of the previously created @c FIRApp instance.
*/
- (nullable instancetype)initWithAPIKey:(NSString *)APIKey
appName:(NSString *)appName NS_DESIGNATED_INITIALIZER;
/** @fn getUID
@brief Gets the identifier of the current user, if any.
@return The identifier of the current user, or nil if there is no current user.
*/
- (nullable NSString *)getUID;
/** @fn updateKeychainWithUser:error:
@brief Updates the keychain for the given user.
@param user The user to be updated.
@param error The error caused the method to fail if the method returns NO.
@return Whether updating keychain has succeeded or not.
@remarks Called by @c FIRUser when user info or token changes occur.
*/
- (BOOL)updateKeychainWithUser:(FIRUser *)user error:(NSError *_Nullable *_Nullable)error;
/** @fn internalSignInWithCredential:callback:
@brief Convenience method for @c internalSignInAndRetrieveDataWithCredential:callback:
This method doesn't return additional identity provider data.
*/
- (void)internalSignInWithCredential:(FIRAuthCredential *)credential
callback:(FIRAuthResultCallback)callback;
/** @fn internalSignInAndRetrieveDataWithCredential:callback:
@brief Asynchronously signs in Firebase with the given 3rd party credentials (e.g. a Facebook
login Access Token, a Google ID Token/Access Token pair, etc.) and returns additional
identity provider data.
@param credential The credential supplied by the IdP.
@param isReauthentication Indicates whether or not the current invocation originated from an
attempt to reauthenticate.
@param callback A block which is invoked when the sign in finishes (or is cancelled.) Invoked
asynchronously on the auth global work queue in the future.
@remarks This is the internal counterpart of this method, which uses a callback that does not
update the current user.
*/
- (void)internalSignInAndRetrieveDataWithCredential:(FIRAuthCredential *)credential
isReauthentication:(BOOL)isReauthentication
callback:(nullable FIRAuthDataResultCallback)callback;
/** @fn signOutByForceWithUserID:error:
@brief Signs out the current user.
@param userID The ID of the user to force sign out.
@param error An optional out parameter for error results.
@return @YES when the sign out request was successful. @NO otherwise.
*/
- (BOOL)signOutByForceWithUserID:(NSString *)userID error:(NSError *_Nullable *_Nullable)error;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
@class FIRAuthRequestConfiguration;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRFetchAccessTokenCallback
@brief The callback used to return the value of attempting to fetch an access token.
In the event the operation was successful @c token will be set and @c error will be @c nil.
In the event of failure @c token will be @c nil and @c error will be set.
@c tokenUpdated indicates whether either the access or the refresh token has been updated.
The token returned should be considered ephemeral and not cached. It should be used immediately
and discarded. All operations that need this token should call fetchAccessToken and do their
work from the callback.
*/
typedef void(^FIRFetchAccessTokenCallback)(NSString *_Nullable token,
NSError *_Nullable error,
BOOL tokenUpdated);
/** @class FIRSecureTokenService
@brief Provides services for token exchanges and refreshes.
*/
@interface FIRSecureTokenService : NSObject <NSSecureCoding>
/** @property requestConfiguration
@brief The configuration for making requests to server.
*/
@property(nonatomic, strong) FIRAuthRequestConfiguration *requestConfiguration;
/** @property rawAccessToken
@brief The cached access token.
@remarks This method is specifically for providing the access token to internal clients during
deserialization and sign-in events, and should not be used to retrieve the access token by
anyone else.
*/
@property(nonatomic, copy, readonly) NSString *rawAccessToken;
/** @property refreshToken
@brief The refresh token for the user, or @c nil if the user has yet completed sign-in flow.
@remarks This property needs to be set manually after the instance is decoded from archive.
*/
@property(nonatomic, copy, readonly, nullable) NSString *refreshToken;
/** @property accessTokenExpirationDate
@brief The expiration date of the cached access token.
*/
@property(nonatomic, copy, readonly, nullable) NSDate *accessTokenExpirationDate;
/** @fn initWithRequestConfiguration:authorizationCode:
@brief Creates a @c FIRSecureTokenService with an authroization code.
@param requestConfiguration The configuration for making requests to server.
@param authorizationCode An authorization code which needs to be exchanged for STS tokens.
*/
- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
authorizationCode:(NSString *)authorizationCode;
/** @fn initWithRequestConfiguration:accessToken:accessTokenExpirationDate:refreshToken
@brief Creates a @c FIRSecureTokenService with access and refresh tokens.
@param requestConfiguration The configuration for making requests to server.
@param accessToken The STS access token.
@param accessTokenExpirationDate The approximate expiration date of the access token.
@param refreshToken The STS refresh token.
*/
- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
accessToken:(nullable NSString *)accessToken
accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate
refreshToken:(NSString *)refreshToken;
/** @fn fetchAccessTokenForcingRefresh:callback:
@brief Fetch a fresh ephemeral access token for the ID associated with this instance. The token
received in the callback should be considered short lived and not cached.
@param forceRefresh Forces the token to be refreshed.
@param callback Callback block that will be called to return either the token or an error.
Invoked asyncronously on the auth global work queue in the future.
*/
- (void)fetchAccessTokenForcingRefresh:(BOOL)forceRefresh
callback:(FIRFetchAccessTokenCallback)callback;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,206 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRSecureTokenService.h"
#import "FIRAuth.h"
#import "FIRAuthKeychain.h"
#import "FIRAuthSerialTaskQueue.h"
#import "FIRAuthBackend.h"
#import "FIRAuthRequestConfiguration.h"
#import "FIRSecureTokenRequest.h"
#import "FIRSecureTokenResponse.h"
/** @var kAPIKeyCodingKey
@brief The key used to encode the APIKey for NSSecureCoding.
*/
static NSString *const kAPIKeyCodingKey = @"APIKey";
/** @var kRefreshTokenKey
@brief The key used to encode the refresh token for NSSecureCoding.
*/
static NSString *const kRefreshTokenKey = @"refreshToken";
/** @var kAccessTokenKey
@brief The key used to encode the access token for NSSecureCoding.
*/
static NSString *const kAccessTokenKey = @"accessToken";
/** @var kAccessTokenExpirationDateKey
@brief The key used to encode the access token expiration date for NSSecureCoding.
*/
static NSString *const kAccessTokenExpirationDateKey = @"accessTokenExpirationDate";
/** @var kFiveMinutes
@brief Five minutes (in seconds.)
*/
static const NSTimeInterval kFiveMinutes = 5 * 60;
@interface FIRSecureTokenService ()
- (instancetype)init NS_DESIGNATED_INITIALIZER;
@end
@implementation FIRSecureTokenService {
/** @var _taskQueue
@brief Used to serialize all requests for access tokens.
*/
FIRAuthSerialTaskQueue *_taskQueue;
/** @var _authorizationCode
@brief An authorization code which needs to be exchanged for Secure Token Service tokens.
*/
NSString *_Nullable _authorizationCode;
/** @var _accessToken
@brief The currently cached access token. Or |nil| if no token is currently cached.
*/
NSString *_Nullable _accessToken;
}
- (instancetype)init {
self = [super init];
if (self) {
_taskQueue = [[FIRAuthSerialTaskQueue alloc] init];
}
return self;
}
- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
authorizationCode:(NSString *)authorizationCode {
self = [self init];
if (self) {
_requestConfiguration = requestConfiguration;
_authorizationCode = [authorizationCode copy];
}
return self;
}
- (instancetype)initWithRequestConfiguration:(FIRAuthRequestConfiguration *)requestConfiguration
accessToken:(nullable NSString *)accessToken
accessTokenExpirationDate:(nullable NSDate *)accessTokenExpirationDate
refreshToken:(NSString *)refreshToken {
self = [self init];
if (self) {
_requestConfiguration = requestConfiguration;
_accessToken = [accessToken copy];
_accessTokenExpirationDate = [accessTokenExpirationDate copy];
_refreshToken = [refreshToken copy];
}
return self;
}
- (void)fetchAccessTokenForcingRefresh:(BOOL)forceRefresh
callback:(FIRFetchAccessTokenCallback)callback {
[_taskQueue enqueueTask:^(FIRAuthSerialTaskCompletionBlock complete) {
if (!forceRefresh && [self hasValidAccessToken]) {
complete();
callback(self->_accessToken, nil, NO);
} else {
[self requestAccessToken:^(NSString *_Nullable token,
NSError *_Nullable error,
BOOL tokenUpdated) {
complete();
callback(token, error, tokenUpdated);
}];
}
}];
}
- (NSString *)rawAccessToken {
return _accessToken;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *refreshToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kRefreshTokenKey];
NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:kAccessTokenKey];
NSDate *accessTokenExpirationDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kAccessTokenExpirationDateKey];
if (!refreshToken) {
return nil;
}
self = [self init];
if (self) {
_refreshToken = refreshToken;
_accessToken = accessToken;
_accessTokenExpirationDate = accessTokenExpirationDate;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
// The API key is encoded even it is not used in decoding to be compatible with previous versions
// of the library.
[aCoder encodeObject:_requestConfiguration.APIKey forKey:kAPIKeyCodingKey];
// Authorization code is not encoded because it is not long-lived.
[aCoder encodeObject:_refreshToken forKey:kRefreshTokenKey];
[aCoder encodeObject:_accessToken forKey:kAccessTokenKey];
[aCoder encodeObject:_accessTokenExpirationDate forKey:kAccessTokenExpirationDateKey];
}
#pragma mark - Private methods
/** @fn requestAccessToken:
@brief Makes a request to STS for an access token.
@details This handles both the case that the token has not been granted yet and that it just
needs to be refreshed. The caller is responsible for making sure that this is occurring in
a @c _taskQueue task.
@param callback Called when the fetch is complete. Invoked asynchronously on the main thread in
the future.
@remarks Because this method is guaranteed to only be called from tasks enqueued in
@c _taskQueue, we do not need any @synchronized guards around access to _accessToken/etc.
since only one of those tasks is ever running at a time, and those tasks are the only
access to and mutation of these instance variables.
*/
- (void)requestAccessToken:(FIRFetchAccessTokenCallback)callback {
FIRSecureTokenRequest *request;
if (_refreshToken.length) {
request = [FIRSecureTokenRequest refreshRequestWithRefreshToken:_refreshToken
requestConfiguration:_requestConfiguration];
} else {
request = [FIRSecureTokenRequest authCodeRequestWithCode:_authorizationCode
requestConfiguration:_requestConfiguration];
}
[FIRAuthBackend secureToken:request
callback:^(FIRSecureTokenResponse *_Nullable response,
NSError *_Nullable error) {
BOOL tokenUpdated = NO;
NSString *newAccessToken = response.accessToken;
if (newAccessToken.length && ![newAccessToken isEqualToString:self->_accessToken]) {
self->_accessToken = [newAccessToken copy];
self->_accessTokenExpirationDate = response.approximateExpirationDate;
tokenUpdated = YES;
}
NSString *newRefreshToken = response.refreshToken;
if (newRefreshToken.length &&
![newRefreshToken isEqualToString:self->_refreshToken]) {
self->_refreshToken = [newRefreshToken copy];
tokenUpdated = YES;
}
callback(newAccessToken, error, tokenUpdated);
}];
}
- (BOOL)hasValidAccessToken {
return _accessToken && [_accessTokenExpirationDate timeIntervalSinceNow] > kFiveMinutes;
}
@end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRUserInfo.h"
@class FIRGetAccountInfoResponseProviderUserInfo;
NS_ASSUME_NONNULL_BEGIN
@interface FIRUserInfoImpl : NSObject <FIRUserInfo, NSSecureCoding>
/** @fn userInfoWithGetAccountInfoResponseProviderUserInfo:
@brief A convenience factory method for constructing a @c FIRUserInfo instance from data
returned by the getAccountInfo endpoint.
@param providerUserInfo Data returned by the getAccountInfo endpoint.
@return A new instance of @c FIRUserInfo using data from the getAccountInfo endpoint.
*/
+ (nullable instancetype)userInfoWithGetAccountInfoResponseProviderUserInfo:
(FIRGetAccountInfoResponseProviderUserInfo *)providerUserInfo;
/** @fn init
@brief This class should not be initialized manually.
@see FIRUser.providerData
*/
- (instancetype)init NS_UNAVAILABLE;
/** @fn initWithProviderID:userID:displayName:photoURL:email:
@brief Designated initializer.
@param providerID The provider identifier.
@param userID The unique user ID for the user (the value of the @c uid field in the token.)
@param displayName The name of the user.
@param photoURL The URL of the user's profile photo.
@param email The user's email address.
@param phoneNumber The user's phone number.
*/
- (nullable instancetype)initWithProviderID:(NSString *)providerID
userID:(NSString *)userID
displayName:(nullable NSString *)displayName
photoURL:(nullable NSURL *)photoURL
email:(nullable NSString *)email
phoneNumber:(nullable NSString *)phoneNumber
NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,127 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRUserInfoImpl.h"
#import "FIRGetAccountInfoResponse.h"
/** @var kProviderIDCodingKey
@brief The key used to encode the providerID property for NSSecureCoding.
*/
static NSString *const kProviderIDCodingKey = @"providerID";
/** @var kUserIDCodingKey
@brief The key used to encode the userID property for NSSecureCoding.
*/
static NSString *const kUserIDCodingKey = @"userID";
/** @var kDisplayNameCodingKey
@brief The key used to encode the displayName property for NSSecureCoding.
*/
static NSString *const kDisplayNameCodingKey = @"displayName";
/** @var kProfileURLCodingKey
@brief The key used to encode the profileURL property for NSSecureCoding.
*/
static NSString *const kProfileURLCodingKey = @"profileURL";
/** @var kPhotoURLCodingKey
@brief The key used to encode the photoURL property for NSSecureCoding.
*/
static NSString *const kPhotoURLCodingKey = @"photoURL";
/** @var kEmailCodingKey
@brief The key used to encode the email property for NSSecureCoding.
*/
static NSString *const kEmailCodingKey = @"email";
/** @var kPhoneNumberCodingKey
@brief The key used to encode the phoneNumber property for NSSecureCoding.
*/
static NSString *const kPhoneNumberCodingKey = @"phoneNumber";
@implementation FIRUserInfoImpl
@synthesize providerID = _providerID;
@synthesize uid = _userID;
@synthesize displayName = _displayName;
@synthesize photoURL = _photoURL;
@synthesize email = _email;
@synthesize phoneNumber = _phoneNumber;
+ (nullable instancetype)userInfoWithGetAccountInfoResponseProviderUserInfo:
(FIRGetAccountInfoResponseProviderUserInfo *)providerUserInfo {
return [[self alloc] initWithProviderID:providerUserInfo.providerID
userID:providerUserInfo.federatedID
displayName:providerUserInfo.displayName
photoURL:providerUserInfo.photoURL
email:providerUserInfo.email
phoneNumber:providerUserInfo.phoneNumber];
}
- (nullable instancetype)initWithProviderID:(NSString *)providerID
userID:(NSString *)userID
displayName:(nullable NSString *)displayName
photoURL:(nullable NSURL *)photoURL
email:(nullable NSString *)email
phoneNumber:(nullable NSString *)phoneNumber {
self = [super init];
if (self) {
_providerID = [providerID copy];
_userID = [userID copy];
_displayName = [displayName copy];
_photoURL = [photoURL copy];
_email = [email copy];
_phoneNumber = [phoneNumber copy];
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *providerID =
[aDecoder decodeObjectOfClass:[NSString class] forKey:kProviderIDCodingKey];
NSString *userID = [aDecoder decodeObjectOfClass:[NSString class] forKey:kUserIDCodingKey];
NSString *displayName =
[aDecoder decodeObjectOfClass:[NSString class] forKey:kDisplayNameCodingKey];
NSURL *photoURL = [aDecoder decodeObjectOfClass:[NSURL class] forKey:kPhotoURLCodingKey];
NSString *email = [aDecoder decodeObjectOfClass:[NSString class] forKey:kEmailCodingKey];
NSString *phoneNumber =
[aDecoder decodeObjectOfClass:[NSString class] forKey:kPhoneNumberCodingKey];
return [self initWithProviderID:providerID
userID:userID
displayName:displayName
photoURL:photoURL
email:email
phoneNumber:phoneNumber];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_providerID forKey:kProviderIDCodingKey];
[aCoder encodeObject:_userID forKey:kUserIDCodingKey];
[aCoder encodeObject:_displayName forKey:kDisplayNameCodingKey];
[aCoder encodeObject:_photoURL forKey:kPhotoURLCodingKey];
[aCoder encodeObject:_email forKey:kEmailCodingKey];
[aCoder encodeObject:_phoneNumber forKey:kPhoneNumberCodingKey];
}
@end

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRUserMetadata_Internal.h"
NS_ASSUME_NONNULL_BEGIN
@implementation FIRUserMetadata
/** @var kCreationDateCodingKey
@brief The key used to encode the creationDate property for NSSecureCoding.
*/
static NSString *const kCreationDateCodingKey = @"creationDate";
/** @var kLastSignInDateCodingKey
@brief The key used to encode the lastSignInDate property for NSSecureCoding.
*/
static NSString *const kLastSignInDateCodingKey = @"lastSignInDate";
- (instancetype)initWithCreationDate:(nullable NSDate *)creationDate
lastSignInDate:(nullable NSDate *)lastSignInDate {
self = [super init];
if (self) {
_creationDate = [creationDate copy];
_lastSignInDate = [lastSignInDate copy];
}
return self;
}
#pragma mark - NSSecureCoding
+ (BOOL)supportsSecureCoding {
return YES;
}
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSDate *creationDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kCreationDateCodingKey];
NSDate *lastSignInDate =
[aDecoder decodeObjectOfClass:[NSDate class] forKey:kLastSignInDateCodingKey];
return [self initWithCreationDate:creationDate lastSignInDate:lastSignInDate];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_creationDate forKey:kCreationDateCodingKey];
[aCoder encodeObject:_lastSignInDate forKey:kLastSignInDateCodingKey];
}
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import "FIRUserMetadata.h"
NS_ASSUME_NONNULL_BEGIN
/** @extension FIRUserMetadata
@brief An internal class used to expose internal methods of FIRUserMetadata.
*/
@interface FIRUserMetadata () <NSSecureCoding>
/** @fn initWithCreationDate:lastSignInDate:
@brief Designated initializer.
@param creationDate The creation date of the corresponding user.
@param lastSignInDate The date of the last recorded sign-in of the corresponding user.
*/
- (instancetype)initWithCreationDate:(nullable NSDate *)creationDate
lastSignInDate:(nullable NSDate *)lastSignInDate NS_DESIGNATED_INITIALIZER;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FIRUser.h"
@class FIRAuth;
@class FIRAuthRequestConfiguration;
NS_ASSUME_NONNULL_BEGIN
/** @typedef FIRRetrieveUserCallback
@brief The type of block that is invoked when the construction of a user succeeds or fails.
@param user The user that was constructed, or nil if user construction failed.
@param error The error which occurred, or nil if the request was successful.
*/
typedef void(^FIRRetrieveUserCallback)(FIRUser *_Nullable user, NSError *_Nullable error);
@interface FIRUser () <NSSecureCoding>
/** @property rawAccessToken
@brief The cached access token.
@remarks This method is specifically for providing the access token to internal clients during
deserialization and sign-in events, and should not be used to retrieve the access token by
anyone else.
*/
@property(nonatomic, copy, readonly) NSString *rawAccessToken;
/** @property auth
@brief A weak reference to a FIRAuth instance associated with this instance.
*/
@property(nonatomic, weak) FIRAuth *auth;
/** @property auth
@brief A strong reference to a requestConfiguration instance associated with this user instance.
*/
@property(nonatomic, strong) FIRAuthRequestConfiguration *requestConfiguration;
/** @var accessTokenExpirationDate
@brief The expiration date of the cached access token.
*/
@property(nonatomic, copy, readonly) NSDate *accessTokenExpirationDate;
/** @fn retrieveUserWithAuth:accessToken:accessTokenExpirationDate:refreshToken:callback:
@brief Constructs a user with Secure Token Service tokens, and obtains user details from the
getAccountInfo endpoint.
@param auth The associated FIRAuth instance.
@param accessToken The Secure Token Service access token.
@param accessTokenExpirationDate The approximate expiration date of the access token.
@param refreshToken The Secure Token Service refresh token.
@param anonymous Whether or not the user is anonymous.
@param callback A block which is invoked when the construction succeeds or fails. Invoked
asynchronously on the auth global work queue in the future.
*/
+ (void)retrieveUserWithAuth:(FIRAuth *)auth
accessToken:(NSString *)accessToken
accessTokenExpirationDate:(NSDate *)accessTokenExpirationDate
refreshToken:(NSString *)refreshToken
anonymous:(BOOL)anonymous
callback:(FIRRetrieveUserCallback)callback;
/** @fn internalGetTokenForcingRefresh:callback:
@brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
@param forceRefresh Forces a token refresh. Useful if the token becomes invalid for some reason
other than an expiration.
@param callback The block to invoke when the token is available. Invoked asynchronously on the
global work thread in the future.
*/
- (void)internalGetTokenForcingRefresh:(BOOL)forceRefresh
callback:(nonnull FIRAuthTokenCallback)callback;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2017 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "FirebaseAuthVersion.h"
// Convert the macro to a string
#define STR(x) STR_EXPAND(x)
#define STR_EXPAND(x) #x
const double FirebaseAuthVersionNum = FIRAuth_MINOR_VERSION;
const unsigned char *const FirebaseAuthVersionStr =
(const unsigned char *const)STR(FIRAuth_VERSION);

Some files were not shown because too many files have changed in this diff Show More