Skip to content

Commit

Permalink
Merge pull request #1457 from AzureAD/veena/fixHttpErrorMapping
Browse files Browse the repository at this point in the history
Add new error mapping for http error code 403 and 404
  • Loading branch information
Veena11 authored Jan 14, 2025
2 parents a1c9345 + ef4d680 commit 2143028
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 2 deletions.
2 changes: 2 additions & 0 deletions IdentityCore/src/MSIDError.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ typedef NS_ENUM(NSInteger, MSIDErrorCode)
*/

MSIDErrorServerUnhandledResponse = -51500,
// http status Code 403 or 404
MSIDErrorUnexpectedHttpResponse = -51501,

/*!
=========================================================
Expand Down
5 changes: 4 additions & 1 deletion IdentityCore/src/MSIDError.m
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ MSIDErrorCode MSIDErrorCodeForOAuthErrorWithSubErrorCode(NSString *oauthError, M
@(MSIDErrorServerError),
],
MSIDHttpErrorCodeDomain : @[
@(MSIDErrorServerUnhandledResponse)
@(MSIDErrorServerUnhandledResponse),
@(MSIDErrorUnexpectedHttpResponse)
]

// TODO: add new codes here
Expand Down Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions IdentityCore/tests/MSIDAADRequestErrorHandlerTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,68 @@ - (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);
NSError *underlyingError = error.userInfo[NSUnderlyingErrorKey];
XCTAssertEqual(underlyingError.code, MSIDErrorUnexpectedHttpResponse);
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
Expand Down

0 comments on commit 2143028

Please sign in to comment.