Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
vNext
----------
- [MINOR] Expose a JavaScript API in brokered Webviews to facilitate Improved Same Device NumberMatch (#2617)
- [MINOR] Enable the new Broker discovery on MSAL by default (#2618)
- [PATCH] Improve logs and error reporting SIWG flow (#2616)
- [PATCH] Only show QR +PIN rationale when the request origin is from Microsoft (#2613)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.internal.numberMatch

import android.webkit.JavascriptInterface
import com.microsoft.identity.common.logging.Logger
import com.microsoft.identity.common.nativeauth.internal.commands.GetAuthMethodsCommand

/**
* Java Script API to be exposed as part of brokered WebView requests.
* Will be used by AuthUX as part of number match feature.
* When authenticator is installed, and phone uses MFA or PSI in an interactive flow, a number
* matching challenge is issued, where used is given a number and asked to open authenticator and check
* for the same number in authenticator UI. This feature cuts out one UI step, where this API is used to
* supply the number match value and store it in ephemeral storage (kept as long as current broker
* process is alive), where Authenticator can call a broker API to fetch the number match, and immediately
* prompt user for consent, rather than first asking them to check the number match.
Comment thread
fadidurah marked this conversation as resolved.
*/
class NumberMatchJavaScriptInterface {

// Store number matches in a static hash map
// No need to persist this storage beyond the current broker process, but we need to keep them
Comment thread
fadidurah marked this conversation as resolved.
// long enough for AuthApp to call the broker api to fetch the number match
companion object {
val TAG = NumberMatchJavaScriptInterface::class.java.simpleName
val numberMatchMap: HashMap<String?, String?> = HashMap()
Comment thread
fadidurah marked this conversation as resolved.
Outdated
}

/**
* Method to add a key:value pair of sessionID:numberMatch to static hashmap. This hashmap will be accessed
* by broker api to get the number match for a particular sessionID.
*/
@JavascriptInterface
fun postCodeMatch(sessionID : String?, numberMatch : String?) {
Comment thread
fadidurah marked this conversation as resolved.
Outdated
// If both parameters are non-null, add a new entry to the hashmap
if (sessionID != null && numberMatch != null) {
val methodTag = "$TAG:postCodeMatch"
Logger.info(
methodTag,
"Adding entry in NumberMatch hashmap for session ID: $sessionID"
)
numberMatchMap[sessionID] = numberMatch
}

// If either parameter is null, do nothing
}

/**
* Clear existing number match key:value pairs
*/
fun clearNumberMatchMap() {
numberMatchMap.clear()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
import com.microsoft.identity.common.R;
import com.microsoft.identity.common.internal.fido.LegacyFidoActivityResultContract;
import com.microsoft.identity.common.internal.fido.LegacyFido2ApiObject;
import com.microsoft.identity.common.internal.numberMatch.NumberMatchJavaScriptInterface;
import com.microsoft.identity.common.internal.ui.webview.ISendResultCallback;
import com.microsoft.identity.common.internal.ui.webview.ProcessUtil;
import com.microsoft.identity.common.internal.ui.webview.switchbrowser.SwitchBrowserProtocolCoordinator;
import com.microsoft.identity.common.java.WarningType;
import com.microsoft.identity.common.adal.internal.AuthenticationConstants;
Expand Down Expand Up @@ -126,6 +128,8 @@ public class WebViewAuthorizationFragment extends AuthorizationFragment {
// This is used by the switch browser protocol to handle the resume of the flow.
private SwitchBrowserProtocolCoordinator mSwitchBrowserProtocolCoordinator = null;

private boolean isBrokerRequest = false;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand Down Expand Up @@ -214,6 +218,9 @@ void extractState(@NonNull final Bundle state) {
mAuthIntent = state.getParcelable(AUTH_INTENT);
mPkeyAuthStatus = state.getBoolean(PKEYAUTH_STATUS, false);
mAuthorizationRequestUrl = state.getString(REQUEST_URL);
if (getContext() != null) {
isBrokerRequest = ProcessUtil.isRunningOnAuthService(getContext());
}
mRedirectUri = state.getString(REDIRECT_URI);
mRequestHeaders = getRequestHeaders(state);
mPostPageLoadedJavascript = state.getString(POST_PAGE_LOADED_URL);
Expand Down Expand Up @@ -294,6 +301,9 @@ private void setUpWebView(@NonNull final View view,
mWebView.getSettings().setUserAgentString(
userAgent + AuthenticationConstants.Broker.CLIENT_TLS_NOT_SUPPORTED);
mWebView.getSettings().setJavaScriptEnabled(true);
if (isBrokerRequest) {
mWebView.addJavascriptInterface(new NumberMatchJavaScriptInterface(), "Android");
}
mWebView.requestFocus(View.FOCUS_DOWN);

// Set focus to the view for touch event
Expand Down Expand Up @@ -480,7 +490,7 @@ private HashMap<String, String> getRequestHeaders(final Bundle state) {
}

// Attach client extras header for ESTS telemetry. Only done for broker requests
if (isBrokerRequest(this.mAuthorizationRequestUrl)) {
if (isBrokerRequest) {
final ClientExtraSku clientExtraSku = ClientExtraSku.builder()
.srcSku(state.getString(PRODUCT))
.srcSkuVer(state.getString(VERSION))
Expand All @@ -502,7 +512,7 @@ public ActivityResultLauncher<LegacyFido2ApiObject> getFidoLauncher() {
* Helper method to check if the authorization request is being made through broker.
* Done by checking for broker version key in the url
*/
private boolean isBrokerRequest(final String authorizationUrl) {
private boolean checkBrokerRequest(final String authorizationUrl) {
return authorizationUrl.contains(Device.PlatformIdParameters.BROKER_VERSION);
}

Expand Down
Loading