aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Auth
diff options
context:
space:
mode:
authorGravatar Zsika Phillip <protocol86@users.noreply.github.com>2018-03-29 18:16:45 -0700
committerGravatar GitHub <noreply@github.com>2018-03-29 18:16:45 -0700
commitea490a2c6492e41e892397e044477f778ce358b8 (patch)
tree2d94cb515dc84d77da8574e03e2165b0aa8ebab1 /Firebase/Auth
parent744f9daf43c06d920966773c5d6607377b6a6230 (diff)
Custom claims client api (#1004)
* Adds custom claims API to client * Ammends branch Adds: - Deprecation messages - Fixes auth result keys - Ammends sample app - Adds unit tests * fixes typo switches “to” to “so”
Diffstat (limited to 'Firebase/Auth')
-rw-r--r--Firebase/Auth/Source/FIRAuthTokenResult.m110
-rw-r--r--Firebase/Auth/Source/FIRAuthTokenResult_Internal.h37
-rw-r--r--Firebase/Auth/Source/FIRUser.m73
-rw-r--r--Firebase/Auth/Source/Public/FIRAuthTokenResult.h66
-rw-r--r--Firebase/Auth/Source/Public/FIRUser.h49
-rw-r--r--Firebase/Auth/Source/Public/FirebaseAuth.h1
6 files changed, 333 insertions, 3 deletions
diff --git a/Firebase/Auth/Source/FIRAuthTokenResult.m b/Firebase/Auth/Source/FIRAuthTokenResult.m
new file mode 100644
index 0000000..81e9920
--- /dev/null
+++ b/Firebase/Auth/Source/FIRAuthTokenResult.m
@@ -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
diff --git a/Firebase/Auth/Source/FIRAuthTokenResult_Internal.h b/Firebase/Auth/Source/FIRAuthTokenResult_Internal.h
new file mode 100644
index 0000000..2914f2a
--- /dev/null
+++ b/Firebase/Auth/Source/FIRAuthTokenResult_Internal.h
@@ -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
diff --git a/Firebase/Auth/Source/FIRUser.m b/Firebase/Auth/Source/FIRUser.m
index a77db75..fc7930f 100644
--- a/Firebase/Auth/Source/FIRUser.m
+++ b/Firebase/Auth/Source/FIRUser.m
@@ -29,6 +29,7 @@
#import "FIRAuth_Internal.h"
#import "FIRAuthBackend.h"
#import "FIRAuthRequestConfiguration.h"
+#import "FIRAuthTokenResult_Internal.h"
#import "FIRDeleteAccountRequest.h"
#import "FIRDeleteAccountResponse.h"
#import "FIREmailAuthProvider.h"
@@ -784,18 +785,88 @@ static void callInMainThreadWithAuthDataResultAndError(
- (void)getIDTokenForcingRefresh:(BOOL)forceRefresh
completion:(nullable FIRAuthTokenCallback)completion {
+ [self getIDTokenResultForcingRefresh:forceRefresh
+ completion:^(FIRAuthTokenResult *_Nullable tokenResult,
+ NSError *_Nullable error) {
+
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(tokenResult.token, error);
+ });
+ }
+ }];
+}
+
+- (void)getIDTokenResultWithCompletion:(nullable FIRAuthTokenResultCallback)completion {
+ [self getIDTokenResultForcingRefresh:NO
+ completion:^(FIRAuthTokenResult *_Nullable tokenResult,
+ NSError *_Nullable error) {
+ if (completion) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ completion(tokenResult, error);
+ });
+ }
+ }];
+}
+
+- (void)getIDTokenResultForcingRefresh:(BOOL)forceRefresh
+ completion:(nullable FIRAuthTokenResultCallback)completion {
dispatch_async(FIRAuthGlobalWorkQueue(), ^{
[self internalGetTokenForcingRefresh:forceRefresh
callback:^(NSString *_Nullable token, NSError *_Nullable error) {
+ FIRAuthTokenResult *tokenResult;
+ if (token) {
+ tokenResult = [self parseIDToken:token error:&error];
+ }
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
- completion(token, error);
+ completion(tokenResult, error);
});
}
}];
});
}
+- (FIRAuthTokenResult *)parseIDToken:(NSString *)token error:(NSError **)error {
+ error = nil;
+ NSArray *tokenStringArray = [token componentsSeparatedByString:@"."];
+ // The token payload is always the second index of the array.
+ NSMutableString *tokenPayload = [[NSMutableString alloc] initWithString:tokenStringArray[1]];
+
+ // Pad the token payload with "=" signs if the payload's length is not a multple of 4.
+ int remainder = tokenPayload.length % 4 != 0;
+ if (remainder) {
+ while (remainder --) {
+ [tokenPayload appendString:@"="];
+ }
+ }
+ NSData *decodedTokenPayloadData =
+ [[NSData alloc] initWithBase64EncodedString:tokenPayload
+ options:NSDataBase64DecodingIgnoreUnknownCharacters];
+ NSDictionary *tokenPayloadDictionary =
+ [NSJSONSerialization JSONObjectWithData:decodedTokenPayloadData
+ options:kNilOptions
+ error:error];
+ if (error) {
+ return nil;
+ }
+
+ NSDate *expDate =
+ [NSDate dateWithTimeIntervalSinceNow:[tokenPayloadDictionary[@"exp"] doubleValue]];
+ NSDate *authDate =
+ [NSDate dateWithTimeIntervalSinceNow:[tokenPayloadDictionary[@"auth_time"] doubleValue]];
+ NSDate *issuedDate =
+ [NSDate dateWithTimeIntervalSinceNow:[tokenPayloadDictionary[@"iat"] doubleValue]];
+ FIRAuthTokenResult *result =
+ [[FIRAuthTokenResult alloc] initWithToken:token
+ expirationDate:expDate
+ authDate:authDate
+ issuedAtDate:issuedDate
+ signInProvider:tokenPayloadDictionary[@"sign_in_provider"]
+ claims:tokenPayloadDictionary];
+ return result;
+}
+
- (void)getTokenForcingRefresh:(BOOL)forceRefresh
completion:(nullable FIRAuthTokenCallback)completion {
[self getIDTokenForcingRefresh:forceRefresh completion:completion];
diff --git a/Firebase/Auth/Source/Public/FIRAuthTokenResult.h b/Firebase/Auth/Source/Public/FIRAuthTokenResult.h
new file mode 100644
index 0000000..11487dc
--- /dev/null
+++ b/Firebase/Auth/Source/Public/FIRAuthTokenResult.h
@@ -0,0 +1,66 @@
+/*
+ * 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>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/** @class FIRAuthTokenResult
+ @brief A data class containing the ID token JWT string and other properties associated with the
+ token including the decoded payload claims if available.
+ */
+NS_SWIFT_NAME(AuthTokenResult)
+@interface FIRAuthTokenResult : NSObject
+
+/** @property token
+ @brief Stores the JWT string of the ID token.
+ */
+@property (nonatomic, readonly) NSString *token;
+
+/** @property expirationDate
+ @brief Stores the ID token's expiration date.
+ */
+@property (nonatomic, readonly) NSDate *expirationDate;
+
+/** @property authDate
+ @brief Stores the ID token's authentication date.
+ @remarks This is the date the user was signed in and NOT the date the token was refreshed.
+ */
+@property (nonatomic, readonly) NSDate *authDate;
+
+/** @property issuedAtDate
+ @brief Stores the date that the ID token was issued.
+ @remarks This is the date last refreshed and NOT the last authentication date.
+ */
+@property (nonatomic, readonly) NSDate *issuedAtDate;
+
+/** @property signInProvider
+ @brief Stores sign-in provider through which the token was obtained.
+ @remarks This does not necesssarily map to provider IDs.
+ */
+@property (nonatomic, readonly) NSString *signInProvider;
+
+/** @property claims
+ @brief Stores the entire payload of claims found on the ID token. This includes the standard
+ reserved claims as well as custom claims set by the developer via the Admin SDK.
+ */
+@property (nonatomic, readonly) NSDictionary<NSString *, NSString *> *claims;
+
+
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Firebase/Auth/Source/Public/FIRUser.h b/Firebase/Auth/Source/Public/FIRUser.h
index 0cf872f..7198eac 100644
--- a/Firebase/Auth/Source/Public/FIRUser.h
+++ b/Firebase/Auth/Source/Public/FIRUser.h
@@ -20,6 +20,7 @@
#import "FIRAuthDataResult.h"
#import "FIRUserInfo.h"
+@class FIRAuthTokenResult;
@class FIRPhoneAuthCredential;
@class FIRUserProfileChangeRequest;
@class FIRUserMetadata;
@@ -39,6 +40,21 @@ NS_ASSUME_NONNULL_BEGIN
typedef void (^FIRAuthTokenCallback)(NSString *_Nullable token, NSError *_Nullable error)
NS_SWIFT_NAME(AuthTokenCallback);
+/** @typedef FIRAuthTokenResultCallback
+ @brief The type of block called when a token is ready for use.
+ @see FIRUser.getIDTokenResultWithCompletion:
+ @see FIRUser.getIDTokenResultForcingRefresh:withCompletion:
+
+ @param tokenResult Optionally; an object containing the raw access token string as well as other
+ useful data pertaining to the token.
+ @param error Optionally; the error which occurred - or nil if the request was successful.
+
+ @remarks One of: `token` or `error` will always be non-nil.
+ */
+typedef void (^FIRAuthTokenResultCallback)(FIRAuthTokenResult *_Nullable tokenResult,
+ NSError *_Nullable error)
+ NS_SWIFT_NAME(AuthTokenResultCallback);
+
/** @typedef FIRUserProfileChangeCallback
@brief The type of block called when a user profile change has finished.
@@ -250,6 +266,34 @@ NS_SWIFT_NAME(User)
- (void)reauthenticateAndRetrieveDataWithCredential:(FIRAuthCredential *) credential
completion:(nullable FIRAuthDataResultCallback) completion;
+/** @fn getIDTokenResultWithCompletion:
+ @brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
+
+ @param completion Optionally; the block invoked when the token is available. Invoked
+ asynchronously on the main thread in the future.
+
+ @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods.
+ */
+- (void)getIDTokenResultWithCompletion:(nullable FIRAuthTokenResultCallback)completion
+ NS_SWIFT_NAME(getIDTokenResult(completion:));
+
+/** @fn getIDTokenResultForcingRefresh:completion:
+ @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 completion Optionally; the block invoked when the token is available. Invoked
+ asynchronously on the main thread in the future.
+
+ @remarks The authentication token will be refreshed (by making a network request) if it has
+ expired, or if `forceRefresh` is YES.
+
+ @remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods.
+ */
+- (void)getIDTokenResultForcingRefresh:(BOOL)forceRefresh
+ completion:(nullable FIRAuthTokenResultCallback)completion
+ NS_SWIFT_NAME(getIDTokenResult(forcingRefresh:completion:));
+
/** @fn getIDTokenWithCompletion:
@brief Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
@@ -259,7 +303,7 @@ NS_SWIFT_NAME(User)
@remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods.
*/
- (void)getIDTokenWithCompletion:(nullable FIRAuthTokenCallback)completion
- NS_SWIFT_NAME(getIDToken(completion:));
+ NS_SWIFT_NAME(getIDToken(completion:)) __attribute__((deprecated));
/** @fn getTokenWithCompletion:
@brief Please use `getIDTokenWithCompletion:` instead.
@@ -286,7 +330,8 @@ NS_SWIFT_NAME(User)
@remarks See `FIRAuthErrors` for a list of error codes that are common to all API methods.
*/
- (void)getIDTokenForcingRefresh:(BOOL)forceRefresh
- completion:(nullable FIRAuthTokenCallback)completion;
+ completion:(nullable FIRAuthTokenCallback)completion
+ __attribute__((deprecated));
/** @fn getTokenForcingRefresh:completion:
@brief Please use getIDTokenForcingRefresh:completion instead.
diff --git a/Firebase/Auth/Source/Public/FirebaseAuth.h b/Firebase/Auth/Source/Public/FirebaseAuth.h
index 409ac73..cd7e4a4 100644
--- a/Firebase/Auth/Source/Public/FirebaseAuth.h
+++ b/Firebase/Auth/Source/Public/FirebaseAuth.h
@@ -22,6 +22,7 @@
#import "FIRAuthCredential.h"
#import "FIRAuthDataResult.h"
#import "FIRAuthErrors.h"
+#import "FIRAuthTokenResult.h"
#import "FirebaseAuthVersion.h"
#import "FIREmailAuthProvider.h"
#import "FIRFacebookAuthProvider.h"