AppAuth-iOS icon indicating copy to clipboard operation
AppAuth-iOS copied to clipboard

NSInvalidArgumentException while refreshing a token initialized only by a OIDTokenRequest

Open netrager opened this issue 5 years ago • 4 comments

Describe the bug NSInvalidArgumentException while refreshing a token initialized only by a OIDTokenRequest. The API tries to add a nil value for parameter client_id inside "OIDURLQueryComponent addParameter:value". This is caused by using the "_lastAuthorizationResponse" for creating a new OIDTokenRequest inside "OIDAuthState tokenRefreshRequestWithAdditionalParameters", which is nil in this case.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil' *** First throw call stack: ( 0 CoreFoundation 0x00007fff23e3cf0e __exceptionPreprocess + 350 1 libobjc.A.dylib 0x00007fff50ba89b2 objc_exception_throw + 48 2 CoreFoundation 0x00007fff23ecfa51 _CFThrowFormattedException + 194 3 CoreFoundation 0x00007fff23ece563 -[__NSArrayM insertObject:atIndex:].cold.1 + 35 4 CoreFoundation 0x00007fff23d50dcf -[__NSArrayM insertObject:atIndex:] + 1167 5 AppAuth 0x000000010cb49552 -[OIDURLQueryComponent addParameter:value:] + 242 6 AppAuth 0x000000010cb46c98 -[OIDTokenRequest URLRequest] + 888 7 AppAuth 0x000000010cb31049 +[OIDAuthorizationService performTokenRequest:originalAuthorizationResponse:callback:] + 137 8 AppAuth 0x000000010cb372c7 -[OIDAuthState performActionWithFreshTokens:additionalRefreshParameters:dispatchQueue:] + 1447 9 AppAuth 0x000000010cb36ce8 -[OIDAuthState performActionWithFreshTokens:additionalRefreshParameters:] + 152 10 AppAuth 0x000000010cb36c31 -[OIDAuthState performActionWithFreshTokens:] + 65 11 ProfiBeraterAppDev 0x000000010a770b4c $s18ProfiBeraterAppDev11ProfileViewC10handleTestyyF + 1468 12 ProfiBeraterAppDev 0x000000010a77264b $s18ProfiBeraterAppDev11ProfileViewC10handleTestyyFTo + 43 13 UIKitCore 0x00007fff48c8cca1 -[UIApplication sendAction:to:from:forEvent:] + 83 14 UIKitCore 0x00007fff4863bcde -[UIControl sendAction:to:forEvent:] + 223 15 UIKitCore 0x00007fff4863c026 -[UIControl _sendActionsForEvents:withEvent:] + 396 16 UIKitCore 0x00007fff4863af97 -[UIControl touchesEnded:withEvent:] + 497 17 UIKitCore 0x00007fff488154a5 _UIGestureEnvironmentUpdate + 9331 18 UIKitCore 0x00007fff48812ff4 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 467 19 UIKitCore 0x00007fff48812d7c -[UIGestureEnvironment _updateForEvent:window:] + 225 20 UIKitCore 0x00007fff48cca2fb -[UIWindow sendEvent:] + 4479 21 UIKitCore 0x00007fff48ca4755 -[UIApplication sendEvent:] + 356 22 UIKit 0x00000001126450b8 -[UIApplicationAccessibility sendEvent:] + 85 23 UIKitCore 0x00007fff48d2f552 __dispatchPreprocessedEventFromEventQueue + 7628 24 UIKitCore 0x00007fff48d32716 __handleEventQueueInternal + 6584 25 UIKitCore 0x00007fff48d28fb9 __handleHIDEventFetcherDrain + 88 26 CoreFoundation 0x00007fff23da0d31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 27 CoreFoundation 0x00007fff23da0c5c __CFRunLoopDoSource0 + 76 28 CoreFoundation 0x00007fff23da0434 __CFRunLoopDoSources0 + 180 29 CoreFoundation 0x00007fff23d9b02e __CFRunLoopRun + 974 30 CoreFoundation 0x00007fff23d9a944 CFRunLoopRunSpecific + 404 31 GraphicsServices 0x00007fff38ba6c1a GSEventRunModal + 139 32 UIKitCore 0x00007fff48c8b9ec UIApplicationMain + 1605 33 ProfiBeraterAppDev 0x000000010a71073b main + 75 34 libdyld.dylib 0x00007fff51a231fd start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil' terminating with uncaught exception of type NSException CoreSimulator 732.17 - Device: iPhone 11 Pro Max (2EC05751-B9DA-4A84-BA18-1B7ED0BC5290) - Runtime: iOS 13.5 (17F61) - DeviceType: iPhone 11 Pro Max

To Reproduce Steps to reproduce the behavior:

  1. Create an OIDAuthState object only via OIDTokenRequest and OIDTokenResponse -> "OIDAuthState(authorizationResponse: nil, tokenResponse: response, registrationResponse: nil)"
  2. Request a new token via "authState?.setNeedsTokenRefresh()"
  3. Perform an action and try to refresh the token "authState?.performAction() { (accessToken, idToken, error) in }"

Expected behavior The Exception should not be raised and the OIDTokenRequest should be created with the "_lastTokenResponse" object.

Desktop (please complete the following information):

  • OS: OSX 10.15.7

Smartphone (please complete the following information): iOS Simulator with iOS 13.5

netrager avatar Oct 15 '20 06:10 netrager

I'm facing this exact same issue. @netrager did you find a way to avoid this error?

jonatantilting avatar Sep 27 '22 14:09 jonatantilting

Can you provide more detail about your use case? What's the scenario in which you only have an OIDTokenResponse with which to instantiate OIDAuthState? Typically, there would be an associated OIDAuthorizationResponse at that point.

petea avatar Oct 19 '22 22:10 petea

@petea Im trying to authorise exchanging tokens from an external provider like Facebook, Google... The OIDTokenResponse contains all the correct info and tokens but whenever those tokens need to get refreshed the OIDAuthState does not seem to handle that. @netrager Did a great job with the detailed explanation above. Here's a chunk of my code if that helps:

` (void) TokenExchange:(char *) tokenChar: (char *) issuerChar {

NSString *token = [NSString stringWithFormat:@"%s", tokenChar];
NSString *issuer = [NSString stringWithFormat:@"%s", issuerChar];
NSDictionary<NSString *, NSString *> *additionalParams = @{
    @"subject_token": token,
    @"subject_issuer": issuer
};

OIDAuthorizationRequest *request =
[[OIDAuthorizationRequest alloc] initWithConfiguration:_configuration
                                              clientId:_clientId
                                                scopes:@[OIDScopeOpenID]
                                           redirectURL:_callbackUrl
                                          responseType:OIDResponseTypeCode
                                  additionalParameters:additionalParams];
OIDTokenRequest *tokenRequest = [[OIDTokenRequest alloc] initWithConfiguration:_configuration
                                                                     grantType:defaultGrantType
                                                             authorizationCode:nil
                                                                   redirectURL:_callbackUrl
                                                                      clientID:_clientId
                                                                  clientSecret:nil
                                                                         scope:@"openid"
                                                                  refreshToken:nil
                                                                  codeVerifier:nil
                                                          additionalParameters:additionalParams];
OIDAuthState * auth;
if([[self instance]authState] != nil){
    auth = [[self instance]authState];
} else {
    auth = [OIDAuthState alloc];
}

UIViewController *controller = [self instance].GetRootViewController;
[OIDAuthorizationService performTokenRequest:tokenRequest
               originalAuthorizationResponse:nil
                                    callback:^(OIDTokenResponse * _Nullable tokenResponse, NSError * _Nullable error) {
    
    if(error != nil){
        NSLog(@"Token Exchange error: %@", [error localizedDescription]);
        return;
    }

    [auth updateWithTokenResponse:tokenResponse error:error];
    [[self instance]setAuthState:auth];
    [[self instance]saveState];
}];

} `

jonatantilting avatar Oct 20 '22 07:10 jonatantilting

same issue.

yira97 avatar Aug 30 '23 23:08 yira97