Skip to content

Sagonzal/exceptions#69

Merged
sangonzal merged 8 commits intodevfrom
sagonzal/exposeHttp429
Jul 11, 2019
Merged

Sagonzal/exceptions#69
sangonzal merged 8 commits intodevfrom
sagonzal/exposeHttp429

Conversation

@sangonzal
Copy link
Copy Markdown
Contributor

@sangonzal sangonzal commented Jun 25, 2019

  • Split AuthenticationException into AuthenticationClientException and AuthenticationServiceException
  • Expose http headers in AuthenticationServiceException- AuthenticationException should return 429 headers information  #59
  • Expose suberror code in AuthenticationServiceException (invalid_grant and interaction_required classification) - Improve CA Error Handling #61
  • Remove ClaimsChallengeException.
    • developers should instead check if AuthenticationServiceException contains claims (aligned with .NET)

Open question:
Should we rename:

  • AuthenticationException -> MsalException
  • AuthenticationServiceException -> MsalServiceException
  • AuthenticationClientException -> MsalClientException

@sangonzal sangonzal requested review from SomkaPe and henrik-me June 25, 2019 20:13

/**
* claims challenge value
* Initializes a new instance of the exception class with a specified error message
Copy link
Copy Markdown
Contributor

@SomkaPe SomkaPe Jul 1, 2019

Choose a reason for hiding this comment

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

probably not "error message" but instance of Throwable #Closed

private String statusMessage;

/**
* An ID that can used to piece up a single authentication flow.
Copy link
Copy Markdown
Contributor

@SomkaPe SomkaPe Jul 1, 2019

Choose a reason for hiding this comment

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

"can be used" probably #Closed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 : Seems like a missing word as Petro indicates


In reply to: 299208121 [](ancestors = 299208121)

Map<String, List<String>> headers = conn.getHeaderFields();
for(Map.Entry<String, List<String>> header: headers.entrySet()){

if(header.getKey() == null || StringHelper.isBlank(header.getKey())){
Copy link
Copy Markdown
Contributor

@SomkaPe SomkaPe Jul 1, 2019

Choose a reason for hiding this comment

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

check for null is included into StringHelper.isBlank #Closed

@sangonzal
Copy link
Copy Markdown
Contributor Author

@SomkaPe @henrik-me any opinions on the naming of the exceptions?

Assert.fail("Expected AuthenticationServiceException was not thrown");
} catch (AuthenticationServiceException ex) {
Assert.assertEquals(claims.replace("\\", ""), ex.claims());
Assert.assertEquals(ex.subError(), "");
Copy link
Copy Markdown
Contributor

@henrik-me henrik-me Jul 4, 2019

Choose a reason for hiding this comment

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

Assert.assertEquals(ex.subError(), ""); [](start = 12, length = 39)

I dont' see any tests really validating the sub error. Also the subError is not what should be exposed, the exposed property is Classification and it will only be a subset of the suberrors. Please work with Bogdan on these details. #Closed

@henrik-me henrik-me requested a review from bgavrilMS July 4, 2019 04:46
Copy link
Copy Markdown
Contributor

@henrik-me henrik-me left a comment

Choose a reason for hiding this comment

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

🕐

* Exception type thrown when service returns an error response or other networking errors occur.
*/
@Accessors(fluent = true)
@Getter
Copy link
Copy Markdown
Contributor

@henrik-me henrik-me Jul 4, 2019

Choose a reason for hiding this comment

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

Getter [](start = 1, length = 6)

subError is supposed to stay private and a subset of errors should be exposed via the Classification property #Closed

*/
@Accessors(fluent = true)
@Getter
public class AuthenticationServiceException extends AuthenticationException{
Copy link
Copy Markdown
Contributor

@henrik-me henrik-me Jul 4, 2019

Choose a reason for hiding this comment

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

AuthenticationServiceException [](start = 13, length = 30)

Some of the errors should be categorized as client side / UiRequiredExceptions and not ServiceExceptions. #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

Yes, namely "invalid_grant" service exceptions are exposed as UiRequiredServiceExceptions. Currently MSAL.NET treats all "invalid_grant" exceptions as UiRequiredExceptions, but I have a PR to filter some of these out (e.g. suberror "client_mismatch", which is a FOCI related suberror, is not a UiRequiredException). #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

Consider having a factory that decides which type of exception needs to be thrown - ServiceException or UiRequiredException. #Closed

Copy link
Copy Markdown
Contributor Author

@sangonzal sangonzal Jul 8, 2019

Choose a reason for hiding this comment

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

@bgavrilMS I believe the service also returns "interaction_required". Are you treating these as UiRequiredExceptions as well? #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 9, 2019

Choose a reason for hiding this comment

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

@sangonzal - yes, sorry, let me clarify. There are 2 cases where MSAL gets an error from the server and throws UiRequiredException:

  • Whenever it interacts with Evo and Evo responds with error code invalid_grant (this is where I suggest to use a factory - i.e. an object is responsible for transforming Evo errors into Service or UiRequired)
  • In the authorization flow, when the auth code url contains the param error=login_required

The MSAL library also throws UiRequiredException based on client-side logic, as follows:

  • in AcquireTokenSilent if the account / login_hint is null, or if a login_hint is used but no matching Account / too many Accounts are in the cache for that hint.
  • If no cache is configured
  • Some web UIs also throw this (should not apply to you, the system browser ui doesn't throw this) #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 9, 2019

Choose a reason for hiding this comment

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

For the Authorization flow, that error will be sent when either:

  • Prompt.Never was passsed, but interaction is actually required
  • An error occurs during silent auth that prevented the authentication to complete in time. #Closed

public String toString(){
return errorCode;
}
public final static String AUTHORIZATION_PENDING = "authorization_pending";
Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

Consider providing comments on these strings, in a format similar to "What Happens?" and "Mitigation". #Closed

/**
* More specific error
*/
private String subError;
Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

As Henrik mentioned, we don't expose this because Evo does not guarantee that these sub errors will remain unchanged. #Closed

errorObject.getCode();
// Some invalid_grant or interaction_required subError codes returned by
// the service are not supposed to be exposed to customers
if(errorResponse.error() != null &&
Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

The TokenRequest class does too much, consider moving this logic to another object, for example the ServiceException factory can take on this responsability. #Closed

}
}

private ErrorResponse filterSubErrorCode(ErrorResponse errorResponse){
Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS Jul 4, 2019

Choose a reason for hiding this comment

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

The spec I've used to do this work mentioned having a "Classification" property that exposes some of the sub-errors. We don't expose sub_error in general.

Also, for discoverability, the Classification property will return an enum instead of a string constant. #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS left a comment

Choose a reason for hiding this comment

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

Main issues are around:

  • separate UiRequiredException, which is a subclass of ServiceException
  • do not expose sub_error
  • expose a classification getter on UiRequiredException (enum or string, I'd prefer enum) that encapsulates that filtering logic you already wrote.
  • allow list instead of block list (i.e. if sub_error is X, Y or Z, classification is A, B or C instead of if sub_error is NOT X...). I've discussed this at length with Henrik and we'd rather take responsability to curate new suberrors as they appear (i.e. add new mappings).

@sangonzal
Copy link
Copy Markdown
Contributor Author

sangonzal commented Jul 10, 2019

@bgavrilMS Thanks for all of the detailed feedback. I have addressed all of the main issues you have raised, and have aligned this implementation with the one in .NET. I have a couple of questions which I will follow up with offline. #Closed

Copy link
Copy Markdown
Member

@bgavrilMS bgavrilMS left a comment

Choose a reason for hiding this comment

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

LGTM, ping me to discuss further

Copy link
Copy Markdown
Contributor

@henrik-me henrik-me left a comment

Choose a reason for hiding this comment

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

:shipit:

@henrik-me
Copy link
Copy Markdown
Contributor

henrik-me commented Jul 11, 2019

one naming question/suggestion for the enum which should be thought of before closing

@henrik-me
Copy link
Copy Markdown
Contributor

Not sure which exceptions. IMO, I like calling it InteractionRequired and not UIInteractionRequired, though this may be misleading as some of them we should really show them the system browser... otherwise using names that are used in other libraries makes the most sense to me for the exception naming (seems like you are generally following that pattern)


In reply to: 507772688 [](ancestors = 507772688)

@sangonzal sangonzal merged commit 01498d5 into dev Jul 11, 2019
@sangonzal sangonzal deleted the sagonzal/exposeHttp429 branch July 12, 2019 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants