Skip to content

Commit 01498d5

Browse files
authored
Merge pull request #69 from AzureAD/sagonzal/exposeHttp429
Sagonzal/exceptions
2 parents 57040db + e6d5ea5 commit 01498d5

33 files changed

+553
-335
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
@@ -66,8 +66,8 @@ private static String getInstanceDiscoveryEndpoint(String host) {
6666
}
6767

6868
private static void validate(InstanceDiscoveryResponse instanceDiscoveryResponse) {
69-
if (StringHelper.isBlank(instanceDiscoveryResponse.getTenantDiscoveryEndpoint())) {
70-
throw new AuthenticationException(instanceDiscoveryResponse.getErrorDescription());
69+
if (StringHelper.isBlank(instanceDiscoveryResponse.tenantDiscoveryEndpoint())) {
70+
throw new MsalServiceException(instanceDiscoveryResponse);
7171
}
7272
}
7373

@@ -97,8 +97,8 @@ private static void validate(InstanceDiscoveryResponse instanceDiscoveryResponse
9797
}
9898

9999
private static void cacheInstanceDiscoveryMetadata(String host, InstanceDiscoveryResponse instanceDiscoveryResponse) {
100-
if (instanceDiscoveryResponse.getMetadata() != null) {
101-
for (InstanceDiscoveryMetadataEntry entry : instanceDiscoveryResponse.getMetadata()) {
100+
if (instanceDiscoveryResponse.metadata() != null) {
101+
for (InstanceDiscoveryMetadataEntry entry : instanceDiscoveryResponse.metadata()) {
102102
for (String alias : entry.aliases) {
103103
cache.put(alias, entry);
104104
}

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,14 @@ private AuthorizationGrant getAuthorizationGrantIntegrated(String userName) thro
133133
updatedGrant = getSAMLAuthorizationGrant(wsTrustResponse);
134134
}
135135
else if (userRealmResponse.isAccountManaged()) {
136-
throw new AuthenticationException("Password is required for managed user");
136+
throw new MsalClientException(
137+
"Password is required for managed user",
138+
AuthenticationErrorCode.PASSWORD_REQUIRED_FOR_MANAGED_USER);
137139
}
138140
else{
139-
throw new AuthenticationException("Unknown User Type");
141+
throw new MsalClientException(
142+
"User Realm request failed",
143+
AuthenticationErrorCode.USER_REALM_DISCOVERY_FAILED);
140144
}
141145

142146
return updatedGrant;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,15 @@ private AuthenticationResult acquireTokenWithDeviceCode(DeviceCode deviceCode,
5757
}
5858
try {
5959
return acquireTokenByAuthorisationGrantSupplier.execute();
60-
} catch (AuthenticationException ex) {
60+
} catch (MsalServiceException ex) {
6161
if (ex.errorCode().equals(AUTHORIZATION_PENDING)) {
6262
TimeUnit.SECONDS.sleep(deviceCode.interval());
6363
} else {
6464
throw ex;
6565
}
6666
}
6767
}
68-
throw new AuthenticationException("Expired Device code");
68+
throw new MsalClientException("Expired Device code", AuthenticationErrorCode.CODE_EXPIRED);
6969
}
7070

7171
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
@@ -75,7 +75,7 @@ public void setIsConfidentialClient(boolean isConfidentialClient){
7575
this.put(IS_CONFIDENTIAL_CLIENT_KEY, String.valueOf(isConfidentialClient).toLowerCase(Locale.ROOT));
7676
}
7777

78-
public void setApiErrorCode(AuthenticationErrorCode apiErrorCode){
79-
this.put(API_ERROR_CODE_KEY, apiErrorCode.toString());
78+
public void setApiErrorCode(String apiErrorCode){
79+
this.put(API_ERROR_CODE_KEY, apiErrorCode);
8080
}
8181
}

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

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,44 @@
33

44
package com.microsoft.aad.msal4j;
55

6-
public enum AuthenticationErrorCode {
6+
public class AuthenticationErrorCode {
77

8-
UNKNOWN ("unknown"),
9-
AUTHORIZATION_PENDING ("authorization_pending"),
10-
INTERACTION_REQUIRED ("interaction_required");
8+
/**
9+
* In the context of device code user has not yet authenticated via browser
10+
*/
11+
public final static String AUTHORIZATION_PENDING = "authorization_pending";
1112

12-
private String errorCode;
13+
/**
14+
* In the context of device code, this error happens when the device code has expired before
15+
* the user signed-in on another device (this is usually after 15 min)
16+
*/
17+
public final static String CODE_EXPIRED = "code_expired";
1318

14-
AuthenticationErrorCode(String errorCode){
15-
this.errorCode = errorCode;
16-
}
19+
/**
20+
* Standard Oauth2 protocol error code. It indicates that the application needs to expose
21+
* the UI to the user so that user does an interactive action in order to get a new token
22+
*/
23+
public final static String INVALID_GRANT = "invalid_grant";
1724

18-
@Override
19-
public String toString(){
20-
return errorCode;
21-
}
25+
/**
26+
* WS-Trust Endpoint not found in Metadata document
27+
*/
28+
public final static String WSTRUST_ENDPOINT_NOT_FOUND_IN_METADATA_DOCUMENT = "wstrust_endpoint_not_found";
29+
30+
/**
31+
* Password is required for managed user. Will typically happen when trying to do integrated windows authentication
32+
* for managed users
33+
*/
34+
public final static String PASSWORD_REQUIRED_FOR_MANAGED_USER = "password_required_for_managed_user";
35+
36+
/**
37+
* User realm discovery failed
38+
*/
39+
public final static String USER_REALM_DISCOVERY_FAILED = "user_realm_discovery_failed";
40+
41+
/**
42+
* Unknown error occurred
43+
*/
44+
public final static String UNKNOWN = "unknown";
2245
}
46+

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

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

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

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

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.net.URL;
1212
import java.security.MessageDigest;
1313
import java.security.NoSuchAlgorithmException;
14-
import java.util.Set;
1514
import java.util.concurrent.CompletionException;
1615
import java.util.function.Supplier;
1716

@@ -66,9 +65,11 @@ public IAuthenticationResult get() {
6665
}
6766
}
6867
} catch(Exception ex) {
69-
if (ex instanceof AuthenticationException) {
70-
apiEvent.setApiErrorCode(((AuthenticationException) ex).errorCode());
68+
69+
if (ex instanceof MsalServiceException) {
70+
apiEvent.setApiErrorCode(((MsalServiceException) ex).errorCode());
7171
}
72+
7273
clientApplication.log.error(
7374
LogHelper.createMessage(
7475
"Execution of " + this.getClass() + " failed.",

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

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

7676
final String firstPath = path.substring(0, path.indexOf("/"));
@@ -88,7 +88,7 @@ static AuthorityType detectAuthorityType(URL authorityUrl) {
8888
void validateAuthorityUrl() {
8989
if (!this.canonicalAuthorityUrl.getProtocol().equalsIgnoreCase("https")) {
9090
throw new IllegalArgumentException(
91-
AuthenticationErrorMessage.AUTHORITY_URI_INSECURE);
91+
"authority should use the 'https' scheme");
9292
}
9393

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

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

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

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ private static Authority createDefaultAADAuthority() {
387387
try {
388388
authority = new AADAuthority(new URL(DEFAULT_AUTHORITY));
389389
} catch(Exception e){
390-
throw new AuthenticationException(e);
390+
throw new MsalClientException(e);
391391
}
392392
return authority;
393393
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private ClientAuthentication createClientAuthFromClientAssertion(
8787
map.put("client_assertion", Collections.singletonList(clientAssertion.assertion()));
8888
return PrivateKeyJWT.parse(map);
8989
} catch (final ParseException e) {
90-
throw new AuthenticationException(e);
90+
throw new MsalClientException(e);
9191
}
9292
}
9393

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.aad.msal4j;
5+
6+
import com.google.gson.annotations.SerializedName;
7+
import lombok.Getter;
8+
import lombok.Setter;
9+
import lombok.experimental.Accessors;
10+
11+
@Accessors(fluent = true)
12+
@Getter
13+
@Setter
14+
class ErrorResponse {
15+
16+
private Integer statusCode;
17+
private String statusMessage;
18+
19+
@SerializedName("error")
20+
protected String error;
21+
22+
@SerializedName("error_description")
23+
protected String errorDescription;
24+
25+
@SerializedName("error_codes")
26+
protected long[] errorCodes;
27+
28+
@SerializedName("suberror")
29+
protected String subError;
30+
31+
@SerializedName("trace_id")
32+
protected String traceId;
33+
34+
@SerializedName("timestamp")
35+
protected String timestamp;
36+
37+
@SerializedName("correlation_id")
38+
protected String correlation_id;
39+
40+
@SerializedName("claims")
41+
private String claims;
42+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ static void verifyReturnedCorrelationId(Logger log,
148148
}
149149

150150
static String readResponseFromConnection(final HttpsURLConnection conn, HttpEvent httpEvent)
151-
throws AuthenticationException, IOException {
151+
throws MsalServiceException, IOException {
152152
InputStream is = null;
153153
try {
154154
int responseCode = conn.getResponseCode();
@@ -160,8 +160,8 @@ static String readResponseFromConnection(final HttpsURLConnection conn, HttpEven
160160
if (is != null) {
161161
msg = msg + ", Error details : " + inputStreamToString(is);
162162
}
163-
httpEvent.setOauthErrorCode(AuthenticationErrorCode.UNKNOWN.toString());
164-
throw new AuthenticationException(msg);
163+
httpEvent.setOauthErrorCode(AuthenticationErrorCode.UNKNOWN);
164+
throw new MsalServiceException(msg, AuthenticationErrorCode.UNKNOWN);
165165
}
166166

167167
is = conn.getInputStream();

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@ public interface IPublicClientApplication extends IClientApplicationBase {
3535
* End-user should be instructed to use another device to connect to the authorization server to approve the access request.
3636
* Since the client cannot receive incoming requests, it polls the authorization server repeatedly
3737
* until the end-user completes the approval process.
38-
*
3938
* @param parameters instance of {@link DeviceCodeFlowParameters}
4039
* @return {@link CompletableFuture} containing an {@link IAuthenticationResult}
41-
* @throws AuthenticationException thrown if authorization is pending or another error occurred.
40+
* @throws MsalException thrown if authorization is pending or another error occurred.
4241
* If the errorCode of the exception is AuthenticationErrorCode.AUTHORIZATION_PENDING,
4342
* the call needs to be retried until the AccessToken is returned.
4443
* DeviceCode.interval - The minimum amount of time in seconds that the client

0 commit comments

Comments
 (0)