Ejemplo n.º 1
0
        private MsalTokenResponse CreateMsalTokenResponse(
            IWebTokenRequestResultWrapper wamResponse,
            IWamPlugin wamPlugin,
            bool isInteractive)
        {
            string internalErrorCode = null;
            string errorMessage;
            string errorCode;

            switch (wamResponse.ResponseStatus)
            {
            case WebTokenRequestStatus.Success:
                _logger.Info("WAM response status success");
                return(wamPlugin.ParseSuccesfullWamResponse(wamResponse.ResponseData[0]));

            // Account Switch occurs when a login hint is passed to WAM but the user chooses a different account for login.
            // MSAL treats this as a success scenario
            case WebTokenRequestStatus.AccountSwitch:
                _logger.Info("WAM response status account switch. Treating as success");
                return(wamPlugin.ParseSuccesfullWamResponse(wamResponse.ResponseData[0]));

            case WebTokenRequestStatus.UserInteractionRequired:
                errorCode =
                    wamPlugin.MapTokenRequestError(wamResponse.ResponseStatus, wamResponse.ResponseError?.ErrorCode ?? 0, isInteractive);
                internalErrorCode = (wamResponse.ResponseError?.ErrorCode ?? 0).ToString(CultureInfo.InvariantCulture);
                errorMessage      = WamErrorPrefix +
                                    $"Wam plugin {wamPlugin.GetType()}" +
                                    $" error code: {internalErrorCode}" +
                                    $" error: " + wamResponse.ResponseError?.ErrorMessage;
                break;

            case WebTokenRequestStatus.UserCancel:
                errorCode    = MsalError.AuthenticationCanceledError;
                errorMessage = MsalErrorMessage.AuthenticationCanceled;
                break;

            case WebTokenRequestStatus.ProviderError:
                errorCode =
                    wamPlugin.MapTokenRequestError(wamResponse.ResponseStatus, wamResponse.ResponseError?.ErrorCode ?? 0, isInteractive);
                errorMessage      = WamErrorPrefix + wamPlugin.GetType() + wamResponse.ResponseError?.ErrorMessage;
                internalErrorCode = (wamResponse.ResponseError?.ErrorCode ?? 0).ToString(CultureInfo.InvariantCulture);
                break;

            default:
                errorCode         = MsalError.UnknownBrokerError;
                internalErrorCode = wamResponse.ResponseError.ErrorCode.ToString(CultureInfo.InvariantCulture);
                errorMessage      = $"Unknown WebTokenRequestStatus {wamResponse.ResponseStatus} (internal error code {internalErrorCode})";
                break;
            }

            return(new MsalTokenResponse()
            {
                Error = errorCode,
                ErrorCodes = internalErrorCode != null ? new[] { internalErrorCode } : null,
                ErrorDescription = errorMessage
            });
        }
Ejemplo n.º 2
0
        public async Task GetAccounts_WamAccount_NoCacheAccountMatch_WebRequest_Async()
        {
            // Arrange
            using (MockHttpAndServiceBundle harness = CreateTestHarness())
            {
                const string User1Upn           = "*****@*****.**";
                var          wamAccountProvider = new WebAccountProvider("id", User1Upn, null);
                _webAccountProviderFactory.GetAccountProviderAsync("organizations").Returns(wamAccountProvider);
                var wamAccount = new WebAccount(wamAccountProvider, "*****@*****.**", WebAccountState.Connected);
                _wamProxy.FindAllWebAccountsAsync(wamAccountProvider, TestConstants.ClientId).Returns(new[] { wamAccount });
                _wamProxy.TryGetAccountProperty(wamAccount, "Authority", out string _).Returns(x =>
                {
                    x[2] = TestConstants.AuthorityCommonTenant;
                    return(true);
                });
                var rq = new Client.Internal.RequestContext(harness.ServiceBundle, Guid.NewGuid(), default);
                _cacheSessionManager.RequestContext.Returns(rq);
                _cacheSessionManager.GetAccountsAsync().Returns(new[] {
                    new Account(TestConstants.HomeAccountId, "some_other_user", null, null)
                });

                _instanceDiscoveryManager.GetMetadataEntryTryAvoidNetworkAsync(
                    Arg.Any <AuthorityInfo>(),
                    Arg.Any <IEnumerable <string> >(), rq)
                .Returns(CreateEntryForSingleAuthority(new Uri(TestConstants.AuthorityCommonTenant)));     // user set this authority in config

                // Setup for the silent token request we're going to do via WAM
                _webAccountProviderFactory.GetAccountProviderAsync(TestConstants.AuthorityCommonTenant).Returns(wamAccountProvider);
                IWebTokenRequestResultWrapper webTokenResponseWrapper = CreateSuccessResponse(wamAccount);

                var newlyAddedAccountToCache = new Account("Id_From_ESTS", "upn", null);
                _wamProxy.GetTokenSilentlyAsync(wamAccount, Arg.Any <WebTokenRequest>()).Returns(webTokenResponseWrapper);
                _cacheSessionManager.SaveTokenResponseAsync(Arg.Any <MsalTokenResponse>()).Returns(Task.FromResult(
                                                                                                       new Tuple <MsalAccessTokenCacheItem, MsalIdTokenCacheItem, Account>(null, null, newlyAddedAccountToCache)));

                // Act
                var accounts = await _aadPlugin.GetAccountsAsync(
                    TestConstants.ClientId,
                    AuthorityInfo.FromAuthorityUri(TestConstants.AuthorityCommonTenant, true),
                    _cacheSessionManager,
                    _instanceDiscoveryManager).ConfigureAwait(false);

                // Assert
                Assert.AreEqual(1, accounts.Count());
                Assert.AreEqual("Id_From_ESTS", accounts.Single().HomeAccountId.Identifier);
            }
        }
        private (Client.Internal.Requests.AuthenticationRequestParameters requestParams, IWebTokenRequestResultWrapper webTokenResponseWrapper) SetupSilentCall(MockHttpAndServiceBundle harness)
        {
            var wamAccountProvider = new WebAccountProvider("id", "*****@*****.**", null);
            var requestParams      = harness.CreateAuthenticationRequestParameters(
                TestConstants.AuthorityHomeTenant);

            requestParams.Account = new Account(
                $"{TestConstants.Uid}.{TestConstants.Utid}",
                TestConstants.DisplayableId,
                null,
                new Dictionary <string, string>()
            {
                { TestConstants.ClientId, "wam_id_1" }
            });                                                                               // account has wam_id!

            var webAccount      = new WebAccount(wamAccountProvider, "*****@*****.**", WebAccountState.Connected);
            var webTokenRequest = new WebTokenRequest(wamAccountProvider);
            IWebTokenRequestResultWrapper webTokenResponseWrapper = Substitute.For <IWebTokenRequestResultWrapper>();


            _webAccountProviderFactory.GetAccountProviderAsync(null).ReturnsForAnyArgs(Task.FromResult(wamAccountProvider));
            _wamProxy.FindAccountAsync(Arg.Any <WebAccountProvider>(), "wam_id_1").Returns(Task.FromResult(webAccount));
            _aadPlugin.CreateWebTokenRequestAsync(
                wamAccountProvider,
                requestParams,
                isForceLoginPrompt: false,
                isAccountInWam: true,
                isInteractive: false)
            .Returns(Task.FromResult(webTokenRequest));



            _wamProxy.GetTokenSilentlyAsync(webAccount, webTokenRequest).
            Returns(Task.FromResult(webTokenResponseWrapper));

            return(requestParams, webTokenResponseWrapper);
        }
Ejemplo n.º 4
0
        private string ExtractTransferToken(
            string clientId,
            IWebTokenRequestResultWrapper transferResponse,
            bool isInteractive)
        {
            if (!transferResponse.ResponseStatus.IsSuccessStatus())
            {
                try
                {
                    _ = WamAdapters.CreateMsalResponseFromWamResponse(
                        transferResponse,
                        _msaPlugin,
                        clientId,
                        _logger,
                        isInteractive: isInteractive);
                }
                catch (MsalServiceException exception)
                {
                    _logger.Warning(
                        "WAM MSA-PT: could not get a transfer token, ussually this is because the " +
                        "1st party app is configured for MSA-PT but not configured to login MSA users (signinaudience =2). " +
                        "Error was: " + exception.ErrorCode + " " + exception.Message);
                }

                return(null);
            }

            _ = _msaPlugin.ParseSuccessfullWamResponse(transferResponse.ResponseData[0], out var properties);
            properties.TryGetValue("code", out string code);

            // Important: cannot use this WebAccount with the AAD provider
            WebAccount msaPtWebAccount = transferResponse.ResponseData[0].WebAccount;

            _logger.InfoPii($"Obtained a transfer token for {msaPtWebAccount.UserName} ?  {code != null}", $"Obtained a transfer token? {code != null}");

            return(code);
        }
Ejemplo n.º 5
0
        internal static MsalTokenResponse CreateMsalResponseFromWamResponse(
            IWebTokenRequestResultWrapper wamResponse,
            IWamPlugin wamPlugin,
            string clientId,
            ICoreLogger logger,
            bool isInteractive)
        {
            string internalErrorCode = null;
            string errorMessage;
            string errorCode;

            switch (wamResponse.ResponseStatus)
            {
            case WebTokenRequestStatus.Success:
                logger.Info("WAM response status success");
                return(wamPlugin.ParseSuccessfullWamResponse(wamResponse.ResponseData[0], out _));

            // Account Switch occurs when a login hint is passed to WAM but the user chooses a different account for login.
            // MSAL treats this as a success scenario
            case WebTokenRequestStatus.AccountSwitch:
                logger.Info("WAM response status account switch. Treating as success");
                return(wamPlugin.ParseSuccessfullWamResponse(wamResponse.ResponseData[0], out _));

            case WebTokenRequestStatus.UserInteractionRequired:
                errorCode =
                    wamPlugin.MapTokenRequestError(wamResponse.ResponseStatus, wamResponse.ResponseError?.ErrorCode ?? 0, isInteractive);
                internalErrorCode = (wamResponse.ResponseError?.ErrorCode ?? 0).ToString(CultureInfo.InvariantCulture);
                errorMessage      = WamErrorPrefix +
                                    $"Wam plugin {wamPlugin.GetType()}" +
                                    $" Error code: {internalErrorCode}" +
                                    $" Error Message: " + wamResponse.ResponseError?.ErrorMessage;
                break;

            case WebTokenRequestStatus.UserCancel:
                errorCode    = MsalError.AuthenticationCanceledError;
                errorMessage = MsalErrorMessage.AuthenticationCanceled;
                break;

            case WebTokenRequestStatus.ProviderError:
                errorCode =
                    wamPlugin.MapTokenRequestError(wamResponse.ResponseStatus, wamResponse.ResponseError?.ErrorCode ?? 0, isInteractive);
                errorMessage =
                    $"{WamErrorPrefix} {wamPlugin.GetType()} \n" +
                    $" Error Code: {errorCode} \n" +
                    $" Error Message: {wamResponse.ResponseError?.ErrorMessage} \n" +
                    $" Possible causes: \n " +
                    $"- Invalid redirect uri - ensure you have configured the following url in the AAD portal App Registration: {GetExpectedRedirectUri(clientId)} \n" +
                    $"- No Internet connection \n" +
                    $"Please see https://aka.ms/msal-net-wam for details about Windows Broker integration";

                internalErrorCode = (wamResponse.ResponseError?.ErrorCode ?? 0).ToString(CultureInfo.InvariantCulture);
                break;

            default:
                errorCode         = MsalError.UnknownBrokerError;
                internalErrorCode = wamResponse.ResponseError.ErrorCode.ToString(CultureInfo.InvariantCulture);
                errorMessage      = $"Unknown WebTokenRequestStatus {wamResponse.ResponseStatus} (internal error code {internalErrorCode})";
                break;
            }

            return(new MsalTokenResponse()
            {
                Error = errorCode,
                ErrorCodes = internalErrorCode != null ? new[] { internalErrorCode } : null,
                ErrorDescription = errorMessage
            });
        }