Conversation
|
|
||
| /** | ||
| * claims challenge value | ||
| * Initializes a new instance of the exception class with a specified error message |
There was a problem hiding this comment.
probably not "error message" but instance of Throwable #Closed
| private String statusMessage; | ||
|
|
||
| /** | ||
| * An ID that can used to piece up a single authentication flow. |
There was a problem hiding this comment.
"can be used" probably #Closed
There was a problem hiding this comment.
| Map<String, List<String>> headers = conn.getHeaderFields(); | ||
| for(Map.Entry<String, List<String>> header: headers.entrySet()){ | ||
|
|
||
| if(header.getKey() == null || StringHelper.isBlank(header.getKey())){ |
There was a problem hiding this comment.
check for null is included into StringHelper.isBlank #Closed
|
@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(), ""); |
There was a problem hiding this comment.
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
| * Exception type thrown when service returns an error response or other networking errors occur. | ||
| */ | ||
| @Accessors(fluent = true) | ||
| @Getter |
There was a problem hiding this comment.
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{ |
There was a problem hiding this comment.
AuthenticationServiceException [](start = 13, length = 30)
Some of the errors should be categorized as client side / UiRequiredExceptions and not ServiceExceptions. #Closed
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Consider having a factory that decides which type of exception needs to be thrown - ServiceException or UiRequiredException. #Closed
There was a problem hiding this comment.
@bgavrilMS I believe the service also returns "interaction_required". Are you treating these as UiRequiredExceptions as well? #Closed
There was a problem hiding this comment.
@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
AcquireTokenSilentif 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
There was a problem hiding this comment.
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"; |
There was a problem hiding this comment.
Consider providing comments on these strings, in a format similar to "What Happens?" and "Mitigation". #Closed
| /** | ||
| * More specific error | ||
| */ | ||
| private String subError; |
There was a problem hiding this comment.
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 && |
There was a problem hiding this comment.
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){ |
There was a problem hiding this comment.
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
bgavrilMS
left a comment
There was a problem hiding this comment.
Main issues are around:
- separate UiRequiredException, which is a subclass of ServiceException
- do not expose sub_error
- expose a
classificationgetter 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).
|
@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 |
bgavrilMS
left a comment
There was a problem hiding this comment.
LGTM, ping me to discuss further
src/main/java/com/microsoft/aad/msal4j/MsalClientException.java
Outdated
Show resolved
Hide resolved
src/main/java/com/microsoft/aad/msal4j/MsalServiceException.java
Outdated
Show resolved
Hide resolved
src/main/java/com/microsoft/aad/msal4j/ServiceExceptionClassification.java
Outdated
Show resolved
Hide resolved
|
one naming question/suggestion for the enum which should be thought of before closing |
|
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) |
Open question:
Should we rename: