Skip to content

Commit 8d8c094

Browse files
author
sgonzalezMSFT
committed
Expose headers and subErrors in exceptions
1 parent 074de34 commit 8d8c094

24 files changed

+342
-290
lines changed

src/main/java/com/microsoft/aad/msal4j/AadInstanceDiscovery.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ private static String getInstanceDiscoveryEndpoint(String host) {
8686
}
8787

8888
private static void validate(InstanceDiscoveryResponse instanceDiscoveryResponse) {
89-
if (StringHelper.isBlank(instanceDiscoveryResponse.getTenantDiscoveryEndpoint())) {
90-
throw new AuthenticationException(instanceDiscoveryResponse.getErrorDescription());
89+
if (StringHelper.isBlank(instanceDiscoveryResponse.tenantDiscoveryEndpoint())) {
90+
throw new AuthenticationServiceException(instanceDiscoveryResponse);
9191
}
9292
}
9393

@@ -117,8 +117,8 @@ private static void validate(InstanceDiscoveryResponse instanceDiscoveryResponse
117117
}
118118

119119
private static void cacheInstanceDiscoveryMetadata(String host, InstanceDiscoveryResponse instanceDiscoveryResponse) {
120-
if (instanceDiscoveryResponse.getMetadata() != null) {
121-
for (InstanceDiscoveryMetadataEntry entry : instanceDiscoveryResponse.getMetadata()) {
120+
if (instanceDiscoveryResponse.metadata() != null) {
121+
for (InstanceDiscoveryMetadataEntry entry : instanceDiscoveryResponse.metadata()) {
122122
for (String alias : entry.aliases) {
123123
cache.put(alias, entry);
124124
}

src/main/java/com/microsoft/aad/msal4j/AcquireTokenByDeviceCodeFlowSupplier.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,15 @@ private AuthenticationResult acquireTokenWithDeviceCode(DeviceCode deviceCode,
7777
}
7878
try {
7979
return acquireTokenByAuthorisationGrantSupplier.execute();
80-
} catch (AuthenticationException ex) {
81-
if (ex.getErrorCode().equals(AUTHORIZATION_PENDING)) {
80+
} catch (AuthenticationServiceException ex) {
81+
if (ex.errorCode().equals(AUTHORIZATION_PENDING)) {
8282
TimeUnit.SECONDS.sleep(deviceCode.interval());
8383
} else {
8484
throw ex;
8585
}
8686
}
8787
}
88-
throw new AuthenticationException("Expired Device code");
88+
throw new AuthenticationClientException("Expired Device code");
8989
}
9090

9191
private Long getCurrentSystemTimeInSeconds(){

src/main/java/com/microsoft/aad/msal4j/ApiEvent.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void setIsConfidentialClient(boolean isConfidentialClient){
9595
this.put(IS_CONFIDENTIAL_CLIENT_KEY, String.valueOf(isConfidentialClient).toLowerCase(Locale.ROOT));
9696
}
9797

98-
public void setApiErrorCode(AuthenticationErrorCode apiErrorCode){
99-
this.put(API_ERROR_CODE_KEY, apiErrorCode.toString());
98+
public void setApiErrorCode(String apiErrorCode){
99+
this.put(API_ERROR_CODE_KEY, apiErrorCode);
100100
}
101101
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.microsoft.aad.msal4j;
2+
3+
/**
4+
* Exception type thrown when and error occurs that is local to the library or the device.
5+
*/
6+
public class AuthenticationClientException extends AuthenticationException{
7+
8+
/**
9+
* Initializes a new instance of the exception class with a specified error message
10+
* @param throwable the inner exception that is the cause of the current exception
11+
*/
12+
public AuthenticationClientException(final Throwable throwable){
13+
super(throwable);
14+
}
15+
16+
/**
17+
* Initializes a new instance of the exception class with a specified error message
18+
* @param message the error message that explains the reason for the exception
19+
*/
20+
public AuthenticationClientException(final String message){
21+
super(message);
22+
}
23+
}

src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorCode.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,10 @@
2323

2424
package com.microsoft.aad.msal4j;
2525

26-
public enum AuthenticationErrorCode {
26+
public class AuthenticationErrorCode {
2727

28-
UNKNOWN ("unknown"),
29-
AUTHORIZATION_PENDING ("authorization_pending"),
30-
INTERACTION_REQUIRED ("interaction_required");
31-
32-
private String errorCode;
33-
34-
AuthenticationErrorCode(String errorCode){
35-
this.errorCode = errorCode;
36-
}
37-
38-
@Override
39-
public String toString(){
40-
return errorCode;
41-
}
28+
public final static String AUTHORIZATION_PENDING = "authorization_pending";
29+
public final static String INTERACTION_REQUIRED = "interaction_required";
30+
public final static String INVALID_GRANT = "invalid_grant";
31+
public final static String UNKNOWN = "unknown";
4232
}

src/main/java/com/microsoft/aad/msal4j/AuthenticationErrorMessage.java

Lines changed: 0 additions & 70 deletions
This file was deleted.

src/main/java/com/microsoft/aad/msal4j/AuthenticationException.java

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -23,53 +23,42 @@
2323

2424
package com.microsoft.aad.msal4j;
2525

26+
import lombok.AccessLevel;
27+
import lombok.Getter;
28+
import lombok.experimental.Accessors;
29+
2630
/**
27-
* MSAL generic exception class
31+
* Base exception type thrown when an error occurs during token acquisition.
2832
*/
33+
@Accessors(fluent = true)
34+
@Getter
2935
public class AuthenticationException extends RuntimeException {
3036

37+
@Getter(value = AccessLevel.PRIVATE)
3138
private static final long serialVersionUID = 1L;
3239

33-
private AuthenticationErrorCode errorCode;
34-
3540
/**
36-
* Constructor
37-
*
38-
* @param t Throwable object
41+
* Initializes a new instance of the exception class
42+
* @param throwable the inner exception that is the cause of the current exception
3943
*/
40-
public AuthenticationException(final Throwable t) {
41-
super(t);
42-
43-
this.errorCode = AuthenticationErrorCode.UNKNOWN;
44+
public AuthenticationException(final Throwable throwable) {
45+
super(throwable);
4446
}
4547

4648
/**
47-
* Constructor
48-
*
49-
* @param message string error message
49+
* Initializes a new instance of the exception class
50+
* @param message the error message that explains the reason for the exception
5051
*/
5152
public AuthenticationException(final String message) {
52-
this(AuthenticationErrorCode.UNKNOWN, message);
53-
}
54-
55-
public AuthenticationException(AuthenticationErrorCode errorCode, final String message) {
5653
super(message);
57-
this.errorCode = errorCode;
5854
}
5955

6056
/**
61-
* Constructor
62-
*
63-
* @param message string error message
64-
* @param t Throwable object
57+
* Initializes a new instance of the exception class
58+
* @param message the error message that explains the reason for the exception
59+
* @param t the inner exception that is the cause of the current exception
6560
*/
6661
public AuthenticationException(final String message, final Throwable t) {
6762
super(message, t);
68-
69-
this.errorCode = AuthenticationErrorCode.UNKNOWN;
70-
}
71-
72-
public AuthenticationErrorCode getErrorCode() {
73-
return errorCode;
7463
}
7564
}

src/main/java/com/microsoft/aad/msal4j/AuthenticationResultSupplier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public IAuthenticationResult get() {
8383
apiEvent.setTenantId(result.accountCacheEntity().realm());
8484
}
8585
} catch(Exception ex) {
86-
if (ex instanceof AuthenticationException) {
87-
apiEvent.setApiErrorCode(((AuthenticationException) ex).getErrorCode());
86+
if (ex instanceof AuthenticationServiceException) {
87+
apiEvent.setApiErrorCode(((AuthenticationServiceException) ex).errorCode());
8888
}
8989
clientApplication.log.error(
9090
LogHelper.createMessage(
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.microsoft.aad.msal4j;
2+
3+
import lombok.Getter;
4+
import lombok.experimental.Accessors;
5+
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
/**
10+
* Exception type thrown when service returns an error response or other networking errors occur.
11+
*/
12+
@Accessors(fluent = true)
13+
@Getter
14+
public class AuthenticationServiceException extends AuthenticationException{
15+
16+
/**
17+
* The protocol error code returned by the service
18+
*/
19+
private String errorCode;
20+
21+
/**
22+
* More specific error
23+
*/
24+
private String subError;
25+
26+
/**
27+
* Status code returned from http layer
28+
*/
29+
private Integer statusCode;
30+
31+
/**
32+
* Status message returned from the http layer
33+
*/
34+
private String statusMessage;
35+
36+
/**
37+
* An ID that can used to piece up a single authentication flow.
38+
*/
39+
private String correlationId;
40+
41+
/**
42+
* Claims included in the claims challenge
43+
*/
44+
private String claims;
45+
46+
/**
47+
* Contains the http headers from the server response that indicated an error.
48+
* When the server returns a 429 Too Many Requests error, a Retry-After should be set.
49+
* It is important to read and respect the time specified in the Retry-After header
50+
*/
51+
private Map<String, List<String>> headers;
52+
53+
/**
54+
* Initializes a new instance of the exception class with a specified error message
55+
* @param message the error message that explains the reason for the exception
56+
*/
57+
public AuthenticationServiceException(final String message){
58+
super(message);
59+
}
60+
61+
/**
62+
* Initializes a new instance of the exception class
63+
* @param errorResponse response object contain information about error returned by server
64+
* @param httpHeaders http headers from the server response
65+
*/
66+
public AuthenticationServiceException(
67+
final ErrorResponse errorResponse,
68+
final Map<String, List<String>> httpHeaders) {
69+
70+
super(errorResponse.errorDescription);
71+
72+
this.errorCode = errorResponse.error();
73+
this.statusCode = errorResponse.statusCode();
74+
this.statusMessage = errorResponse.statusMessage();
75+
this.subError = errorResponse.subError();
76+
this.correlationId = errorResponse.correlation_id();
77+
this.claims = errorResponse.claims();
78+
this.headers = httpHeaders;
79+
}
80+
81+
/**
82+
* Initializes a new instance of the exception class
83+
* @param discoveryResponse response object from instance discovery network call
84+
*/
85+
public AuthenticationServiceException(InstanceDiscoveryResponse discoveryResponse){
86+
87+
super(discoveryResponse.errorDescription());
88+
89+
this.errorCode = discoveryResponse.error();
90+
this.correlationId = discoveryResponse.correlationId();
91+
}
92+
}

src/main/java/com/microsoft/aad/msal4j/Authority.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {
6161
final String path = authorityUrl.getPath().substring(1);
6262
if (StringHelper.isBlank(path)) {
6363
throw new IllegalArgumentException(
64-
AuthenticationErrorMessage.AUTHORITY_URI_INVALID_PATH);
64+
"authority Uri should have at least one segment in the path (i.e. https://<host>/<path>/...)");
6565
}
6666

6767
final String firstPath = path.substring(0, path.indexOf("/"));
@@ -79,7 +79,7 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {
7979
void validateAuthorityUrl() {
8080
if (!this.canonicalAuthorityUrl.getProtocol().equalsIgnoreCase("https")) {
8181
throw new IllegalArgumentException(
82-
AuthenticationErrorMessage.AUTHORITY_URI_INSECURE);
82+
"authority should use the 'https' scheme");
8383
}
8484

8585
if (this.canonicalAuthorityUrl.toString().contains("#")) {

0 commit comments

Comments
 (0)