use of com.microsoft.aad.adal.ChallengeResponseBuilder.ChallengeResponse in project azure-activedirectory-library-for-android by AzureAD.
the class Oauth2 method postMessage.
private AuthenticationResult postMessage(String requestMessage, Map<String, String> headers) throws IOException, AuthenticationException {
final String methodName = ":postMessage";
AuthenticationResult result = null;
final HttpEvent httpEvent = startHttpEvent();
final URL authority = StringExtensions.getUrl(getTokenEndpoint());
if (authority == null) {
stopHttpEvent(httpEvent);
throw new AuthenticationException(ADALError.DEVELOPER_AUTHORITY_IS_NOT_VALID_URL);
}
httpEvent.setHttpPath(authority);
try {
mWebRequestHandler.setRequestCorrelationId(mRequest.getCorrelationId());
mWebRequestHandler.setClientVersion(AuthenticationContext.getVersionName());
ClientMetrics.INSTANCE.beginClientMetricsRecord(authority, mRequest.getCorrelationId(), headers);
HttpWebResponse response = mWebRequestHandler.sendPost(authority, headers, requestMessage.getBytes(AuthenticationConstants.ENCODING_UTF8), "application/x-www-form-urlencoded");
httpEvent.setResponseCode(response.getStatusCode());
httpEvent.setCorrelationId(mRequest.getCorrelationId().toString());
stopHttpEvent(httpEvent);
if (response.getStatusCode() == HttpURLConnection.HTTP_UNAUTHORIZED) {
if (response.getResponseHeaders() != null && response.getResponseHeaders().containsKey(AuthenticationConstants.Broker.CHALLENGE_REQUEST_HEADER)) {
// Device certificate challenge will send challenge request
// in 401 header.
String challengeHeader = response.getResponseHeaders().get(AuthenticationConstants.Broker.CHALLENGE_REQUEST_HEADER).get(0);
Logger.i(TAG + methodName, "Device certificate challenge request. ", "Challenge header: " + challengeHeader);
if (!StringExtensions.isNullOrBlank(challengeHeader)) {
// Handle each specific challenge header
if (StringExtensions.hasPrefixInHeader(challengeHeader, AuthenticationConstants.Broker.CHALLENGE_RESPONSE_TYPE)) {
final HttpEvent challengeHttpEvent = startHttpEvent();
challengeHttpEvent.setHttpPath(authority);
Logger.v(TAG + methodName, "Received pkeyAuth device challenge.");
ChallengeResponseBuilder certHandler = new ChallengeResponseBuilder(mJWSBuilder);
Logger.v(TAG + methodName, "Processing device challenge.");
final ChallengeResponse challengeResponse = certHandler.getChallengeResponseFromHeader(challengeHeader, authority.toString());
headers.put(AuthenticationConstants.Broker.CHALLENGE_RESPONSE_HEADER, challengeResponse.getAuthorizationHeaderValue());
Logger.v(TAG + methodName, "Sending request with challenge response.");
response = mWebRequestHandler.sendPost(authority, headers, requestMessage.getBytes(AuthenticationConstants.ENCODING_UTF8), "application/x-www-form-urlencoded");
challengeHttpEvent.setResponseCode(response.getStatusCode());
challengeHttpEvent.setCorrelationId(mRequest.getCorrelationId().toString());
stopHttpEvent(challengeHttpEvent);
}
} else {
throw new AuthenticationException(ADALError.DEVICE_CERTIFICATE_REQUEST_INVALID, "Challenge header is empty", response);
}
} else {
// AAD server returns 401 response for wrong request
// messages
Logger.v(TAG + methodName, "401 http status code is returned without authorization header.");
}
}
boolean isBodyEmpty = TextUtils.isEmpty(response.getBody());
if (!isBodyEmpty) {
// Protocol related errors will read the error stream and report
// the error and error description
Logger.v(TAG + methodName, "Token request does not have exception.");
try {
result = processTokenResponse(response, httpEvent);
} catch (final ServerRespondingWithRetryableException e) {
result = retry(requestMessage, headers);
if (result != null) {
return result;
}
if (mRequest.getIsExtendedLifetimeEnabled()) {
Logger.v(TAG + methodName, "WebResponse is not a success due to: " + response.getStatusCode());
throw e;
} else {
Logger.v(TAG + methodName, "WebResponse is not a success due to: " + response.getStatusCode());
throw new AuthenticationException(ADALError.SERVER_ERROR, "WebResponse is not a success due to: " + response.getStatusCode(), response);
}
}
ClientMetrics.INSTANCE.setLastError(null);
}
if (result == null) {
// non-protocol related error
String errMessage = isBodyEmpty ? "Status code:" + response.getStatusCode() : response.getBody();
Logger.e(TAG + methodName, ADALError.SERVER_ERROR.getDescription(), errMessage, ADALError.SERVER_ERROR);
throw new AuthenticationException(ADALError.SERVER_ERROR, errMessage, response);
} else {
ClientMetrics.INSTANCE.setLastErrorCodes(result.getErrorCodes());
}
} catch (final UnsupportedEncodingException e) {
ClientMetrics.INSTANCE.setLastError(null);
Logger.e(TAG + methodName, ADALError.ENCODING_IS_NOT_SUPPORTED.getDescription(), e.getMessage(), ADALError.ENCODING_IS_NOT_SUPPORTED, e);
throw e;
} catch (final SocketTimeoutException e) {
result = retry(requestMessage, headers);
if (result != null) {
return result;
}
ClientMetrics.INSTANCE.setLastError(null);
if (mRequest.getIsExtendedLifetimeEnabled()) {
Logger.e(TAG + methodName, ADALError.SERVER_ERROR.getDescription(), e.getMessage(), ADALError.SERVER_ERROR, e);
throw new ServerRespondingWithRetryableException(e.getMessage(), e);
} else {
Logger.e(TAG + methodName, ADALError.SERVER_ERROR.getDescription(), e.getMessage(), ADALError.SERVER_ERROR, e);
throw e;
}
} catch (final IOException e) {
ClientMetrics.INSTANCE.setLastError(null);
Logger.e(TAG + methodName, ADALError.SERVER_ERROR.getDescription(), e.getMessage(), ADALError.SERVER_ERROR, e);
throw e;
} finally {
ClientMetrics.INSTANCE.endClientMetricsRecord(ClientMetricsEndpointType.TOKEN, mRequest.getCorrelationId());
}
return result;
}
use of com.microsoft.aad.adal.ChallengeResponseBuilder.ChallengeResponse in project azure-activedirectory-library-for-android by AzureAD.
the class WebviewHelper method getPreKeyAuthInfo.
/**
* @param challengeUrl URL from which challenge response is received
* @return PreKeyAuth class filled in
* @throws UnsupportedEncodingException on malformed exception
* @throws AuthenticationException on parameter validation failure
*/
public PreKeyAuthInfo getPreKeyAuthInfo(String challengeUrl) throws UnsupportedEncodingException, AuthenticationException {
JWSBuilder jwsBuilder = new JWSBuilder();
ChallengeResponseBuilder certHandler = new ChallengeResponseBuilder(jwsBuilder);
final ChallengeResponse challengeResponse = certHandler.getChallengeResponseFromUri(challengeUrl);
final HashMap<String, String> headers = new HashMap<String, String>();
headers.put(AuthenticationConstants.Broker.CHALLENGE_RESPONSE_HEADER, challengeResponse.getAuthorizationHeaderValue());
String loadUrl = challengeResponse.getSubmitUrl();
HashMap<String, String> parameters = StringExtensions.getUrlParameters(challengeResponse.getSubmitUrl());
Logger.i(TAG, "Get submit url. ", "SubmitUrl:" + challengeResponse.getSubmitUrl());
if (!parameters.containsKey(AuthenticationConstants.OAuth2.CLIENT_ID)) {
loadUrl = loadUrl + "?" + mOauth.getAuthorizationEndpointQueryParameters();
}
return new PreKeyAuthInfo(headers, loadUrl);
}
use of com.microsoft.aad.adal.ChallengeResponseBuilder.ChallengeResponse in project azure-activedirectory-library-for-android by AzureAD.
the class BasicWebViewClient method shouldOverrideUrlLoading.
@Override
public // loaded in the current WebView.
boolean shouldOverrideUrlLoading(final WebView view, final String url) {
final String methodName = ":shouldOverrideUrlLoading";
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Navigation is detected.");
if (url.startsWith(PKEYAUTH_REDIRECT)) {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Webview detected request for pkeyauth challenge.");
view.stopLoading();
setPKeyAuthStatus(true);
new Thread(new Runnable() {
@Override
public void run() {
try {
final ChallengeResponseBuilder certHandler = new ChallengeResponseBuilder(new JWSBuilder());
final ChallengeResponse challengeResponse = certHandler.getChallengeResponseFromUri(url);
final Map<String, String> headers = new HashMap<>();
headers.put(CHALLENGE_RESPONSE_HEADER, challengeResponse.getAuthorizationHeaderValue());
postRunnable(new Runnable() {
@Override
public void run() {
String loadUrl = challengeResponse.getSubmitUrl();
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Respond to pkeyAuth challenge.");
com.microsoft.identity.common.internal.logging.Logger.verbosePII(TAG + methodName, "Challenge submit url:" + challengeResponse.getSubmitUrl());
view.loadUrl(loadUrl, headers);
}
});
} catch (final AuthenticationServerProtocolException e) {
com.microsoft.identity.common.internal.logging.Logger.errorPII(TAG + methodName, "Argument exception", e);
// It should return error code and finish the
// activity, so that onActivityResult implementation
// returns errors to callback.
final Intent resultIntent = new Intent();
resultIntent.putExtra(RESPONSE_AUTHENTICATION_EXCEPTION, e);
if (mRequest != null) {
resultIntent.putExtra(RESPONSE_REQUEST_INFO, mRequest);
}
sendResponse(BROWSER_CODE_AUTHENTICATION_EXCEPTION, resultIntent);
} catch (final AuthenticationException e) {
com.microsoft.identity.common.internal.logging.Logger.error(TAG + methodName, "Failed to create device certificate response", null);
com.microsoft.identity.common.internal.logging.Logger.errorPII(TAG + methodName, "Error", e);
// It should return error code and finish the
// activity, so that onActivityResult implementation
// returns errors to callback.
final Intent resultIntent = new Intent();
resultIntent.putExtra(RESPONSE_AUTHENTICATION_EXCEPTION, e);
if (mRequest != null) {
resultIntent.putExtra(RESPONSE_REQUEST_INFO, mRequest);
}
sendResponse(BROWSER_CODE_AUTHENTICATION_EXCEPTION, resultIntent);
}
}
}).start();
return true;
} else if (url.toLowerCase(Locale.US).startsWith(mRedirect.toLowerCase(Locale.US))) {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Navigation starts with the redirect uri.");
Intent errorIntent = parseError(url);
if (errorIntent != null) {
// Catch WEB-UI cancel request
com.microsoft.identity.common.internal.logging.Logger.info(TAG + methodName, "Sending intent to cancel authentication activity");
view.stopLoading();
cancelWebViewRequest(errorIntent);
return true;
}
processRedirectUrl(view, url);
return true;
} else if (url.startsWith(BROWSER_EXT_PREFIX)) {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "It is an external website request");
view.stopLoading();
if (url.contains(AuthenticationConstants.Broker.BROWSER_DEVICE_CA_URL_QUERY_STRING_PARAMETER)) {
Logger.warn(TAG + methodName, "Failed to launch Company Portal, falling back to browser.");
openLinkInBrowser(url);
sendResponse(AuthenticationConstants.UIResponse.BROWSER_CODE_MDM, new Intent());
} else {
openLinkInBrowser(url);
cancelWebViewRequest(null);
}
return true;
} else if (url.startsWith(BROWSER_EXT_INSTALL_PREFIX)) {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "It is an install request");
final HashMap<String, String> parameters = StringExtensions.getUrlParameters(url);
prepareForBrokerResumeRequest();
// Having thread sleep for 1 second for calling activity to receive the result from
// prepareForBrokerResumeRequest, thus the receiver for listening broker result return
// can be registered. openLinkInBrowser will launch activity for going to
// playstore and broker app download page which brought the calling activity down
// in the activity stack.
final int threadSleepForCallingActivity = 1000;
try {
Thread.sleep(threadSleepForCallingActivity);
} catch (InterruptedException e) {
com.microsoft.identity.common.internal.logging.Logger.warn(TAG + methodName, "Error occurred when having thread sleeping for 1 second.");
}
openLinkInBrowser(parameters.get(INSTALL_URL_KEY));
view.stopLoading();
return true;
}
return processInvalidUrl(view, url);
}
Aggregations