From c7346624215d00a3826ba379eb2179e0c578b3e6 Mon Sep 17 00:00:00 2001 From: Veena Soman Date: Tue, 17 Dec 2024 16:15:14 -0800 Subject: [PATCH] Add new error mapping for http error code 403 and 404 --- IdentityCore/src/MSIDError.h | 2 + IdentityCore/src/MSIDError.m | 5 +- .../MSIDAADRequestErrorHandler.m | 8 ++- .../tests/MSIDAADRequestErrorHandlerTests.m | 4 ++ .../ios/MSIDDefaultSilentTokenRequestTests.m | 60 +++++++++++++++++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/IdentityCore/src/MSIDError.h b/IdentityCore/src/MSIDError.h index b77d8df3f..b72347214 100644 --- a/IdentityCore/src/MSIDError.h +++ b/IdentityCore/src/MSIDError.h @@ -171,6 +171,8 @@ typedef NS_ENUM(NSInteger, MSIDErrorCode) */ MSIDErrorServerUnhandledResponse = -51500, + // http status Code 403 or 404 + MSIDErrorUnExpectedHttpResponse = -51501, /*! ========================================================= diff --git a/IdentityCore/src/MSIDError.m b/IdentityCore/src/MSIDError.m index 5de01abe0..5925c2ab3 100644 --- a/IdentityCore/src/MSIDError.m +++ b/IdentityCore/src/MSIDError.m @@ -224,7 +224,8 @@ MSIDErrorCode MSIDErrorCodeForOAuthErrorWithSubErrorCode(NSString *oauthError, M @(MSIDErrorServerError), ], MSIDHttpErrorCodeDomain : @[ - @(MSIDErrorServerUnhandledResponse) + @(MSIDErrorServerUnhandledResponse), + @(MSIDErrorUnExpectedHttpResponse) ] // TODO: add new codes here @@ -301,6 +302,8 @@ void MSIDFillAndLogError(NSError **error, MSIDErrorCode errorCode, NSString *err // HTTP errors case MSIDErrorServerUnhandledResponse: return @"MSIDErrorServerUnhandledResponse"; + case MSIDErrorUnExpectedHttpResponse: + return @"MSIDErrorUnExpectedHttpResponse"; // Authority validation errors case MSIDErrorAuthorityValidation: return @"MSIDErrorAuthorityValidation"; diff --git a/IdentityCore/src/network/error_handler/MSIDAADRequestErrorHandler.m b/IdentityCore/src/network/error_handler/MSIDAADRequestErrorHandler.m index 4d255e1ce..a19458658 100644 --- a/IdentityCore/src/network/error_handler/MSIDAADRequestErrorHandler.m +++ b/IdentityCore/src/network/error_handler/MSIDAADRequestErrorHandler.m @@ -150,7 +150,13 @@ - (void)handleError:(NSError *)error } } - NSError *httpError = MSIDCreateError(MSIDHttpErrorCodeDomain, MSIDErrorServerUnhandledResponse, errorDescription, nil, nil, nil, context.correlationId, additionalInfo, YES); + NSError *httpUnderlyingError = nil; + if (httpResponse.statusCode == 403 || httpResponse.statusCode == 404) + { + httpUnderlyingError = MSIDCreateError(MSIDHttpErrorCodeDomain, MSIDErrorUnExpectedHttpResponse, errorDescription, nil, nil, nil, context.correlationId, nil, YES); + } + + NSError *httpError = MSIDCreateError(MSIDHttpErrorCodeDomain, MSIDErrorServerUnhandledResponse, errorDescription, nil, nil, httpUnderlyingError, context.correlationId, additionalInfo, YES); if (completionBlock) completionBlock(nil, httpError); } diff --git a/IdentityCore/tests/MSIDAADRequestErrorHandlerTests.m b/IdentityCore/tests/MSIDAADRequestErrorHandlerTests.m index 6847799eb..3b1bd6f9f 100644 --- a/IdentityCore/tests/MSIDAADRequestErrorHandlerTests.m +++ b/IdentityCore/tests/MSIDAADRequestErrorHandlerTests.m @@ -191,6 +191,8 @@ - (void)testHandleError_whenItIsNotServerError_shouldReturnStatusCodeAndHeaders XCTAssertEqualObjects(returnError.domain, MSIDHttpErrorCodeDomain); XCTAssertEqual(returnError.code, MSIDErrorServerUnhandledResponse); + NSError *underlyingError = returnError.userInfo[NSUnderlyingErrorKey]; + XCTAssertEqual(underlyingError.code, MSIDErrorUnExpectedHttpResponse); XCTAssertEqualObjects(returnError.userInfo[MSIDHTTPHeadersKey], @{@"headerKey":@"headerValue"}); XCTAssertNil(errorResponse); @@ -275,6 +277,8 @@ - (void)testHandleError_whenItIsServerError_shouldReturnResponseCodeInError XCTAssertEqualObjects(returnError.domain, MSIDHttpErrorCodeDomain); XCTAssertEqual(returnError.code, MSIDErrorServerUnhandledResponse); + NSError *underlyingError = returnError.userInfo[NSUnderlyingErrorKey]; + XCTAssertEqual(underlyingError.code, MSIDErrorUnExpectedHttpResponse); XCTAssertEqualObjects(returnError.userInfo[MSIDHTTPResponseCodeKey], @"404"); } diff --git a/IdentityCore/tests/integration/ios/MSIDDefaultSilentTokenRequestTests.m b/IdentityCore/tests/integration/ios/MSIDDefaultSilentTokenRequestTests.m index 1562ee18a..e1b5047be 100644 --- a/IdentityCore/tests/integration/ios/MSIDDefaultSilentTokenRequestTests.m +++ b/IdentityCore/tests/integration/ios/MSIDDefaultSilentTokenRequestTests.m @@ -1336,6 +1336,66 @@ - (void)testAcquireTokenSilent_when429ThrottledErrorReturned_shouldReturnAllHead [self waitForExpectationsWithTimeout:1.0 handler:nil]; } + +- (void)testAcquireTokenSilent_when403HttpCodeReturned_shouldReturnMSIDErrorUnexpectedHttpResponseInUnderlyingError +{ + MSIDRequestParameters *silentParameters = [self silentRequestParameters]; + MSIDDefaultTokenCacheAccessor *tokenCache = self.tokenCache; + + [self saveExpiredTokensInCache:tokenCache configuration:silentParameters.msidConfiguration]; + silentParameters.accountIdentifier = [[MSIDAccountIdentifier alloc] initWithDisplayableId:DEFAULT_TEST_ID_TOKEN_USERNAME homeAccountId:DEFAULT_TEST_HOME_ACCOUNT_ID]; + + NSString *authority = DEFAULT_TEST_AUTHORITY_GUID; + MSIDTestURLResponse *discoveryResponse = [MSIDTestURLResponse discoveryResponseForAuthority:authority]; + [MSIDTestURLSession addResponse:discoveryResponse]; + + MSIDTestURLResponse *oidcResponse = [MSIDTestURLResponse oidcResponseForAuthority:authority]; + [MSIDTestURLSession addResponse:oidcResponse]; + + NSMutableDictionary *reqHeaders = [[MSIDTestURLResponse msidDefaultRequestHeaders] mutableCopy]; + [reqHeaders setObject:@"application/x-www-form-urlencoded" forKey:@"Content-Type"]; + + MSIDTestURLResponse *errorTokenResponse = + [MSIDTestURLResponse requestURLString:DEFAULT_TEST_TOKEN_ENDPOINT_GUID + requestHeaders:reqHeaders + requestParamsBody:@{ @"client_id" : @"my_client_id", + @"scope" : @"user.read tasks.read openid profile offline_access", + @"grant_type" : @"refresh_token", + @"refresh_token" : DEFAULT_TEST_REFRESH_TOKEN, + MSID_OAUTH2_REDIRECT_URI : [[self silentRequestParameters] redirectUri], + @"client_info" : @"1"} + responseURLString:DEFAULT_TEST_TOKEN_ENDPOINT_GUID + responseCode:403 + httpHeaderFields:@{@"Retry-After": @"256", + @"Other-Header-Field": @"Other header field" + } + dictionaryAsJSON:nil]; + + [errorTokenResponse->_requestHeaders removeObjectForKey:@"Content-Length"]; + + [MSIDTestURLSession addResponse:errorTokenResponse]; + + MSIDDefaultSilentTokenRequest *silentRequest = [[MSIDDefaultSilentTokenRequest alloc] initWithRequestParameters:silentParameters + forceRefresh:NO + oauthFactory:[MSIDAADV2Oauth2Factory new] + tokenResponseValidator:[MSIDDefaultTokenResponseValidator new] + tokenCache:tokenCache + accountMetadataCache:self.accountMetadataCache]; + + XCTestExpectation *expectation = [self expectationWithDescription:@"silent request"]; + + [silentRequest executeRequestWithCompletion:^(MSIDTokenResult * _Nullable result, NSError * _Nullable error) { + + XCTAssertNotNil(error); + XCTAssertNil(result); + XCTAssertEqual(error.code, MSIDErrorServerUnhandledResponse); + XCTAssertEqualObjects(error.domain, MSIDHttpErrorCodeDomain); + XCTAssertEqualObjects(error.userInfo[MSIDHTTPResponseCodeKey], @"403"); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:1.0 handler:nil]; +} - (void)testAcquireTokenSilent_whenTokenEndpointInDifferentCloud_shouldReturnInteractionRequired { // Prepare RT in cache