Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions Firebase/Auth/Source/AuthProvider/OAuth/FIROAuthCredential.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

@interface FIROAuthCredential ()

@property(nonatomic, nullable) NSString *rawNonce;

- (nullable instancetype)initWithProvider:(NSString *)provider NS_UNAVAILABLE;

@end
Expand All @@ -40,12 +42,14 @@ - (nullable instancetype)initWithProvider:(NSString *)provider {

- (instancetype)initWithProviderID:(NSString *)providerID
IDToken:(nullable NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce
accessToken:(nullable NSString *)accessToken
secret:(nullable NSString *)secret
pendingToken:(nullable NSString *)pendingToken {
self = [super initWithProvider:providerID];
if (self) {
_IDToken = IDToken;
_rawNonce = rawNonce;
_accessToken = accessToken;
_pendingToken = pendingToken;
_secret = secret;
Expand All @@ -56,8 +60,12 @@ - (instancetype)initWithProviderID:(NSString *)providerID
- (instancetype)initWithProviderID:(NSString *)providerID
sessionID:(NSString *)sessionID
OAuthResponseURLString:(NSString *)OAuthResponseURLString {
self =
[self initWithProviderID:providerID IDToken:nil accessToken:nil secret:nil pendingToken:nil];
self = [self initWithProviderID:providerID
IDToken:nil
rawNonce:nil
accessToken:nil
secret:nil
pendingToken:nil];
if (self) {
_OAuthResponseURLString = OAuthResponseURLString;
_sessionID = sessionID;
Expand All @@ -71,6 +79,7 @@ - (nullable instancetype)initWithVerifyAssertionResponse:(FIRVerifyAssertionResp
response.oauthSecretToken.length) {
return [self initWithProviderID:response.providerID
IDToken:response.oauthIDToken
rawNonce:nil
accessToken:response.oauthAccessToken
secret:response.oauthSecretToken
pendingToken:response.pendingToken];
Expand All @@ -80,6 +89,7 @@ - (nullable instancetype)initWithVerifyAssertionResponse:(FIRVerifyAssertionResp

- (void)prepareVerifyAssertionRequest:(FIRVerifyAssertionRequest *)request {
request.providerIDToken = _IDToken;
request.providerRawNonce = _rawNonce;
request.providerAccessToken = _accessToken;
request.requestURI = _OAuthResponseURLString;
request.sessionID = _sessionID;
Expand All @@ -95,11 +105,13 @@ + (BOOL)supportsSecureCoding {

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
NSString *IDToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"IDToken"];
NSString *rawNonce = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"rawNonce"];
NSString *accessToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"accessToken"];
NSString *pendingToken = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"pendingToken"];
NSString *secret = [aDecoder decodeObjectOfClass:[NSString class] forKey:@"secret"];
self = [self initWithProviderID:self.provider
IDToken:IDToken
rawNonce:rawNonce
accessToken:accessToken
secret:secret
pendingToken:pendingToken];
Expand All @@ -108,6 +120,7 @@ - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {

- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.IDToken forKey:@"IDToken"];
[aCoder encodeObject:self.IDToken forKey:@"rawNonce"];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be self.rawNonce instead of self.IDToken?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Fixed here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but where was it fixed? (I can't wait to use this!)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Michael, may I know how serious this bug is in your case? It helps us better understanding our developers. Thanks!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't used this yet, I was looking through the code because I plan to use this feature in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix will be in the next release. For now, the feature should be good enough to use.

[aCoder encodeObject:self.accessToken forKey:@"accessToken"];
[aCoder encodeObject:self.pendingToken forKey:@"pendingToken"];
[aCoder encodeObject:self.secret forKey:@"secret"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@ NS_ASSUME_NONNULL_BEGIN
@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 rawNonce The raw nonce associated with the Auth credential being created.
@param accessToken The access token associated with the credential being created.
@param secret The secret associated with the credential being created.
@param pendingToken The pending token associated with the credential being created.
*/
- (instancetype)initWithProviderID:(NSString *)providerID
IDToken:(nullable NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce
accessToken:(nullable NSString *)accessToken
secret:(nullable NSString *)secret
pendingToken:(nullable NSString *)pendingToken NS_DESIGNATED_INITIALIZER;
Expand Down
25 changes: 25 additions & 0 deletions Firebase/Auth/Source/AuthProvider/OAuth/FIROAuthProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ + (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(nullable NSString *)accessToken {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:IDToken
rawNonce:nil
accessToken:accessToken
secret:nil
pendingToken:nil];
Expand All @@ -80,11 +81,35 @@ + (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(NSString *)accessToken {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:nil
rawNonce:nil
accessToken:accessToken
secret:nil
pendingToken:nil];
}

+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
IDToken:(NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce
accessToken:(nullable NSString *)accessToken {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:IDToken
rawNonce:rawNonce
accessToken:accessToken
secret:nil
pendingToken:nil];
}

+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
IDToken:(NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce {
return [[FIROAuthCredential alloc] initWithProviderID:providerID
IDToken:IDToken
rawNonce:rawNonce
accessToken:nil
secret:nil
pendingToken:nil];
}

+ (instancetype)providerWithProviderID:(NSString *)providerID {
return [[self alloc]initWithProviderID:providerID auth:[FIRAuth auth]];
}
Expand Down
9 changes: 9 additions & 0 deletions Firebase/Auth/Source/Backend/FIRAuthBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,11 @@
*/
static NSString *const kSessionExpiredErrorMessage = @"SESSION_EXPIRED";

/** @var kMissingOrInvalidNonceErrorMessage
@brief This is the error message the server will respond with if the nonce is missing or invalid.
*/
static NSString *const kMissingOrInvalidNonceErrorMessage = @"MISSING_OR_INVALID_NONCE";

/** @var kMissingAppTokenErrorMessage
@brief This is the error message the server will respond with if the APNS token is missing in a
verifyClient request.
Expand Down Expand Up @@ -1176,6 +1181,10 @@ + (nullable NSError *)clientErrorWithServerErrorMessage:(NSString *)serverErrorM
return [FIRAuthErrorUtils captchaCheckFailedErrorWithMessage:serverErrorMessage];
}

if ([shortErrorMessage isEqualToString:kMissingOrInvalidNonceErrorMessage]) {
return [FIRAuthErrorUtils missingOrInvalidNonceErrorWithMessage:serverDetailErrorMessage];
}

// In this case we handle an error that might be specified in the underlying errors dictionary,
// the error message in determined based on the @c reason key in the dictionary.
if (errorDictionary[kErrorsKey]) {
Expand Down
5 changes: 5 additions & 0 deletions Firebase/Auth/Source/Backend/RPC/FIRVerifyAssertionRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property(nonatomic, copy, nullable) NSString *providerIDToken;

/** @property providerRawNonce
@brief An raw nonce from the IDP.
*/
@property(nonatomic, copy, nullable) NSString *providerRawNonce;

/** @property returnIDPCredential
@brief Whether the response should return the IDP credential directly.
*/
Expand Down
10 changes: 10 additions & 0 deletions Firebase/Auth/Source/Backend/RPC/FIRVerifyAssertionRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
*/
static NSString *const kProviderIDTokenKey = @"id_token";

/** @var kProviderNonceKey
@brief The key for the "nonce" value in the request.
*/
static NSString *const kProviderNonceKey = @"nonce";

/** @var kProviderAccessTokenKey
@brief The key for the "access_token" value in the request.
*/
Expand Down Expand Up @@ -115,6 +120,11 @@ - (nullable id)unencodedHTTPRequestBodyWithError:(NSError *_Nullable *_Nullable)
value:_providerIDToken]];
}

if (_providerRawNonce) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderNonceKey
value:_providerRawNonce]];
}

if (_providerAccessToken) {
[queryItems addObject:[NSURLQueryItem queryItemWithName:kProviderAccessTokenKey
value:_providerAccessToken]];
Expand Down
4 changes: 4 additions & 0 deletions Firebase/Auth/Source/Public/FIRAuthErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ typedef NS_ENUM(NSInteger, FIRAuthErrorCode) {
*/
FIRAuthErrorCodeGameKitNotLinked = 17076,

/** Indicates that the nonce is missing or invalid.
*/
FIRAuthErrorCodeMissingOrInvalidNonce = 17094,

/** Indicates an error for when the client identifier is missing.
*/
FIRAuthErrorCodeMissingClientIdentifier = 17993,
Expand Down
29 changes: 29 additions & 0 deletions Firebase/Auth/Source/Public/FIROAuthProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,35 @@ NS_SWIFT_NAME(OAuthProvider)
+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
accessToken:(NSString *)accessToken;

/** @fn credentialWithProviderID:IDToken:rawNonce:accessToken:
@brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID, ID
token, raw nonce and access token.

@param providerID The provider ID associated with the Auth credential being created.
@param IDToken The IDToken associated with the Auth credential being created.
@param rawNonce The raw nonce associated with the Auth credential being created.
@param accessToken The accessstoken associated with the Auth credential be created, if
available.
@return A FIRAuthCredential for the specified provider ID, ID token and access token.
*/
+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
IDToken:(NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce
accessToken:(nullable NSString *)accessToken;

/** @fn credentialWithProviderID:IDToken:rawNonce:
@brief Creates an `FIRAuthCredential` for that OAuth 2 provider identified by providerID using
an ID token and raw nonce.

@param providerID The provider ID associated with the Auth credential being created.
@param IDToken The IDToken associated with the Auth credential being created.
@param rawNonce The raw nonce associated with the Auth credential being created.
@return A FIRAuthCredential.
*/
+ (FIROAuthCredential *)credentialWithProviderID:(NSString *)providerID
IDToken:(NSString *)IDToken
rawNonce:(nullable NSString *)rawNonce;

/** @fn init
@brief This class is not meant to be initialized.
*/
Expand Down
7 changes: 7 additions & 0 deletions Firebase/Auth/Source/Utilities/FIRAuthErrorUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
+ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status;

/** @fn missingOrInvalidNonceErrorWithMessage:
@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 *)missingOrInvalidNonceErrorWithMessage:(nullable NSString *)message;

@end

NS_ASSUME_NONNULL_END
14 changes: 14 additions & 0 deletions Firebase/Auth/Source/Utilities/FIRAuthErrorUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@
static NSString *const kFIRAuthErrorMessageRejectedCredential =
@"The request contains malformed or mismatching credentials.";

/** @var kFIRAuthErrorMessageMissingOrInvalidNonce
@brief Error message constant describing @c FIRAuthErrorCodeMissingOrInvalidNonce errors.
*/
static NSString *const kFIRAuthErrorMessageMissingOrInvalidNonce =
@"The request contains malformed or mismatched credentials.";

/** @var FIRAuthErrorDescription
@brief The error descrioption, based on the error code.
@remarks No default case so that we get a compiler warning if a new value was added to the enum.
Expand Down Expand Up @@ -599,6 +605,8 @@
return kFIRAuthErrorMessageDynamicLinkNotActivated;
case FIRAuthErrorCodeRejectedCredential:
return kFIRAuthErrorMessageRejectedCredential;
case FIRAuthErrorCodeMissingOrInvalidNonce:
return kFIRAuthErrorMessageMissingOrInvalidNonce;
}
}

Expand Down Expand Up @@ -738,6 +746,8 @@
return @"ERROR_DYNAMIC_LINK_NOT_ACTIVATED";
case FIRAuthErrorCodeRejectedCredential:
return @"ERROR_REJECTED_CREDENTIAL";
case FIRAuthErrorCodeMissingOrInvalidNonce:
return @"ERROR_MISSING_OR_INVALID_NONCE";
}
}

Expand Down Expand Up @@ -1179,6 +1189,10 @@ + (NSError *)invalidDynamicLinkDomainErrorWithMessage:(nullable NSString *)messa
return [self errorWithCode:FIRAuthInternalErrorCodeInvalidDynamicLinkDomain message:message];
}

+ (NSError *)missingOrInvalidNonceErrorWithMessage:(nullable NSString *)message {
return [self errorWithCode:FIRAuthInternalErrorCodeMissingOrInvalidNonce message:message];
}

+ (NSError *)keychainErrorWithFunction:(NSString *)keychainFunction status:(OSStatus)status {
NSString *failureReason = [NSString stringWithFormat:@"%@ (%li)", keychainFunction, (long)status];
return [self errorWithCode:FIRAuthInternalErrorCodeKeychainError userInfo:@{
Expand Down
5 changes: 5 additions & 0 deletions Firebase/Auth/Source/Utilities/FIRAuthInternalErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,11 @@ typedef NS_ENUM(NSInteger, FIRAuthInternalErrorCode) {
FIRAuthInternalErrorCodeGameKitNotLinked =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeGameKitNotLinked,

/** Indicates that the nonce is missing or invalid.
*/
FIRAuthInternalErrorCodeMissingOrInvalidNonce =
FIRAuthPublicErrorCodeFlag | FIRAuthErrorCodeMissingOrInvalidNonce,

/** Indicates that a non-null user was expected as an argmument to the operation but a null
user was provided.
*/
Expand Down