[Ignore] // Failing sporadically https://identitydivision.visualstudio.com/Engineering/_workitems/edit/1045664
        public async Task SilentAuth_MsaUser_ForceRefresh_Async()
        {
            var labResponse = await LabUserHelper.GetMsaUserAsync().ConfigureAwait(false);

            pca = PublicClientApplicationBuilder
                  .Create(LabApiConstants.MSAOutlookAccountClientID)
                  .WithTestLogging()
                  .WithAuthority(AadAuthorityAudience.PersonalMicrosoftAccount)
                  .Build();

            Trace.WriteLine("Part 1 - Acquire a token with device code with msa user");
            AuthenticationResult authResult = await pca.AcquireTokenWithDeviceCode(s_scopes, deviceCodeResult =>
            {
                SeleniumExtensions.PerformDeviceCodeLogin(
                    deviceCodeResult,
                    labResponse.User,
                    TestContext,
                    false);

                return(Task.FromResult(0));
            }).ExecuteAsync()
                                              .ConfigureAwait(false);

            await ValidateAuthResultAsync(authResult, labResponse).ConfigureAwait(false);
        }
        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            if (string.IsNullOrEmpty(_authToken))
            {
                var result = await _application.AcquireTokenWithDeviceCode(_scopes, callback =>
                {
                    string[] parts = callback.Message.Split(' ');
                    var code       = parts[Array.FindIndex(parts, a => a.Trim() == "code") + 1];
                    TextCopy.Clipboard.SetText(code);
                    OpenBrowser("https://www.microsoft.com/devicelogin");
                    Console.WriteLine(callback.Message);
                    return(Task.FromResult(0));
                }).ExecuteAsync();

                _authResult = result;
                _authToken  = result.AccessToken;
                var accounts = await _application.GetAccountsAsync();

                _account = accounts.FirstOrDefault();
            }

            if (_authResult.ExpiresOn.ToLocalTime() <= DateTime.Now)
            {
                var result = await _application.AcquireTokenSilent(_scopes, _account).ExecuteAsync();

                _authResult = result;
                _authToken  = result.AccessToken;
                var accounts = await _application.GetAccountsAsync();

                _account = accounts.FirstOrDefault();
            }
            request.Headers.Authorization = new AuthenticationHeaderValue("bearer", _authToken);
        }
예제 #3
0
        /// <summary>
        /// Force to signin the user in an interactive authentication flow.
        /// </summary>
        /// <returns></returns>
        public async Task ForceInteractiveSignIn()
        {
            try
            {
                OnAuthenticationChanged?.Invoke(this, AuthenticationState.StartedInteractive);
                var authResult = await identityClientApp.AcquireTokenInteractive(grantScopes).ExecuteAsync();

                // Set access token and expiration
                TokenForUser = authResult.AccessToken;
                Expiration   = authResult.ExpiresOn;

                OnAuthenticationChanged?.Invoke(this, AuthenticationState.Completed);
            }
            catch (Exception e) when(e is PlatformNotSupportedException || e is MsalUiRequiredException)
            {
                var authResult = await identityClientApp.AcquireTokenWithDeviceCode(grantScopes, dcr =>
                {
                    OnAuthenticationChanged?.Invoke(this, AuthenticationState.FallbackToDeviceCode);
                    OnPresentDeviceCode?.Invoke(this, dcr);
                    return(Task.FromResult(0));
                }).ExecuteAsync();

                // Set access token and expiration
                TokenForUser = authResult.AccessToken;
                Expiration   = authResult.ExpiresOn;
                OnAuthenticationChanged?.Invoke(this, AuthenticationState.Completed);
            }
            catch (Exception)
            {
                OnAuthenticationChanged?.Invoke(this, AuthenticationState.Failed);
            }
        }
예제 #4
0
        public async Task <string> GetAccessToken()
        {
            if (_userAccount == null)
            {
                try
                {
                    var result = await _msalClient.AcquireTokenWithDeviceCode(_scopes, callback => {
                        Console.WriteLine(callback.Message);
                        return(Task.FromResult(0));
                    }).ExecuteAsync();

                    _userAccount = result.Account;
                    return(result.AccessToken);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"Error getting access token:{exception.Message}");
                    return(null);
                }
            }
            else
            {
                var result = await _msalClient
                             .AcquireTokenSilent(_scopes, _userAccount)
                             .ExecuteAsync();

                return(result.AccessToken);
            }
        }
예제 #5
0
        public async Task AuthenticateAsync(
            CancellationToken cancellationToken = default
            )
        {
            // We will use device code flow authentication for Unix systems.
            // https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Device-Code-Flow

            // ToDo: Add timeout.
            var microsoftGraphAuthenticationResult = await _publicClientApplication
                                                     .AcquireTokenWithDeviceCode(
                MicrosoftGraphIAIScopes,
                deviceCodeResult => {
                // This will print the message on the console which tells the user where to go sign-in using
                // a separate browser and the code to enter once they sign in.
                // The AcquireTokenWithDeviceCode() method will poll the server after firing this
                // device code callback to look for the successful login of the user via that browser.
                // This background polling (whose interval and timeout data is also provided as fields in the
                // deviceCodeCallback class) will occur until:
                // * The user has successfully logged in via browser and entered the proper code
                // * The timeout specified by the server for the lifetime of this code (typically ~15 minutes) has been reached
                // * The developing application calls the Cancel() method on a CancellationToken sent into the method.
                //   If this occurs, an OperationCanceledException will be thrown (see catch below for more details).
                Console.WriteLine(deviceCodeResult.Message);
                return(Task.FromResult(0));
            })
                                                     .ExecuteAsync();

            // Extract account from microsoftGraphAuthenticationResult
            _account = microsoftGraphAuthenticationResult.Account;

            // Validate that we have received Tokens.
            await AcquireMicrosoftGraphAuthenticationResultAsync(cancellationToken);
            await AcquireAzureManagementAuthenticationResultAsync(cancellationToken);
            await AcquireKeyVaultAuthenticationResultAsync(cancellationToken);
        }
예제 #6
0
        public async Task <string> GetAccessToken()
        {
            // If there is no saved user account, the user must sign-in
            if (_userAccount == null)
            {
                try
                {
                    // Invoke device code flow so user can sign-in with a browser
                    var result = await _msalClient.AcquireTokenWithDeviceCode(_scopes, callback => {
                        Console.WriteLine(callback.Message);
                        return(Task.FromResult(0));
                    }).ExecuteAsync();

                    _userAccount = result.Account;
                    return(result.AccessToken);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"Error getting access token: {exception.Message}");
                    return(null);
                }
            }
            else
            {
                // If there is an account, call AcquireTokenSilent
                // By doing this, MSAL will refresh the token automatically if
                // it is expired. Otherwise it returns the cached token.

                var result = await _msalClient
                             .AcquireTokenSilent(_scopes, _userAccount)
                             .ExecuteAsync();

                return(result.AccessToken);
            }
        }
예제 #7
0
        private async Task <AuthenticationResult> AcquireByDeviceCodeAsync(IPublicClientApplication pca)
        {
            try
            {
                var result = await pca.AcquireTokenWithDeviceCode(_scopes,
                                                                  deviceCodeResult =>
                {
                    // This will print the message on the console which tells the user where to go sign-in using
                    // a separate browser and the code to enter once they sign in.
                    // The AcquireTokenWithDeviceCode() method will poll the server after firing this
                    // device code callback to look for the successful login of the user via that browser.
                    // This background polling (whose interval and timeout data is also provided as fields in the
                    // deviceCodeCallback class) will occur until:
                    // * The user has successfully logged in via browser and entered the proper code
                    // * The timeout specified by the server for the lifetime of this code (typically ~15 minutes) has been reached
                    // * The developing application calls the Cancel() method on a CancellationToken sent into the method.
                    //   If this occurs, an OperationCanceledException will be thrown (see catch below for more details).
                    Console.WriteLine(deviceCodeResult.Message);
                    return(Task.FromResult(0));
                }).ExecuteAsync();

                Console.WriteLine(result.Account.Username);
                return(result);
            }
            // TODO: handle or throw all these exceptions
            catch (MsalServiceException ex)
            {
                // Kind of errors you could have (in ex.Message)

                // AADSTS50059: No tenant-identifying information found in either the request or implied by any provided credentials.
                // Mitigation: as explained in the message from Azure AD, the authoriy needs to be tenanted. you have probably created
                // your public client application with the following authorities:
                // https://login.microsoftonline.com/common or https://login.microsoftonline.com/organizations

                // AADSTS90133: Device Code flow is not supported under /common or /consumers endpoint.
                // Mitigation: as explained in the message from Azure AD, the authority needs to be tenanted

                // AADSTS90002: Tenant <tenantId or domain you used in the authority> not found. This may happen if there are
                // no active subscriptions for the tenant. Check with your subscription administrator.
                // Mitigation: if you have an active subscription for the tenant this might be that you have a typo in the
                // tenantId (GUID) or tenant domain name.
                throw ex;
            }
            catch (OperationCanceledException ex)
            {
                // If you use a CancellationToken, and call the Cancel() method on it, then this *may* be triggered
                // to indicate that the operation was cancelled.
                // See https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads
                // for more detailed information on how C# supports cancellation in managed threads.
                throw ex;
            }
            catch (MsalClientException ex)
            {
                // Possible cause - verification code expired before contacting the server
                // This exception will occur if the user does not manage to sign-in before a time out (15 mins) and the
                // call to `AcquireTokenWithDeviceCode` is not cancelled in between
                throw ex;
            }
        }
예제 #8
0
        private async Task <AccessToken> GetTokenViaDeviceCodeAsync(string[] scopes, CancellationToken cancellationToken)
        {
            AuthenticationResult result = await _pubApp.AcquireTokenWithDeviceCode(scopes, code => DeviceCodeCallback(code, cancellationToken)).ExecuteAsync(cancellationToken).ConfigureAwait(false);

            _account = result.Account;

            return(new AccessToken(result.AccessToken, result.ExpiresOn));
        }
예제 #9
0
 private async Task <AuthenticationResult> GetResponseAsync(IPublicClientApplication app, IEnumerable <string> scopes, CancellationToken cancellationToken)
 {
     return(await app.AcquireTokenWithDeviceCode(scopes, deviceCodeResult =>
     {
         WriteWarning(deviceCodeResult.Message);
         return Task.CompletedTask;
     }).ExecuteAsync(cancellationToken));
 }
예제 #10
0
        private async Task <string> getAccessToken()
        {
            var result = await msalClient.AcquireTokenWithDeviceCode(_scopes, callback =>
            {
                Console.WriteLine(callback.Message);
                return(Task.FromResult(0));
            }).ExecuteAsync();

            return(result.AccessToken);
        }
        /// <summary>
        /// Gets an access token for the requested resource and scope
        /// </summary>
        /// <param name="resource">Resource to request an access token for (unused)</param>
        /// <param name="scopes">Scopes to request</param>
        /// <returns>An access token</returns>
        public override async Task <string> GetAccessTokenAsync(Uri resource, string[] scopes)
        {
            if (resource == null)
            {
                throw new ArgumentNullException(nameof(resource));
            }

            if (scopes == null)
            {
                throw new ArgumentNullException(nameof(scopes));
            }

            if (DeviceCodeVerification == null)
            {
                throw new ConfigurationErrorsException(
                          PnPCoreAuthResources.DeviceCodeAuthenticationProvider_MissingDeviceCodeVerification);
            }

            AuthenticationResult tokenResult = null;

            var account = await publicClientApplication.GetAccountsAsync().ConfigureAwait(false);

            try
            {
                // Try to get the token from the tokens cache
                tokenResult = await publicClientApplication.AcquireTokenSilent(scopes, account.FirstOrDefault())
                              .ExecuteAsync().ConfigureAwait(false);
            }
            catch (MsalUiRequiredException)
            {
                // Try to get the token directly through AAD if it is not available in the tokens cache
                tokenResult = await publicClientApplication.AcquireTokenWithDeviceCode(scopes,
                                                                                       deviceCodeResult =>
                {
                    DeviceCodeVerification.Invoke(new DeviceCodeNotification
                    {
                        UserCode        = deviceCodeResult.UserCode,
                        Message         = deviceCodeResult.Message,
                        VerificationUrl = new Uri(deviceCodeResult.VerificationUrl)
                    });
                    return(Task.FromResult(0));
                })
                              .ExecuteAsync().ConfigureAwait(false);
            }

            // Log the access token retrieval action
            Log?.LogInformation(PnPCoreAuthResources.AuthenticationProvider_LogAccessTokenRetrieval,
                                GetType().Name, resource, scopes.Aggregate(string.Empty, (c, n) => c + ", " + n).TrimEnd(','));

            // Return the Access Token, if we've got it
            // In case of any exception while retrieving the access token,
            // MSAL will throw an exception that we simply bubble up
            return(tokenResult.AccessToken);
        }
        /// <summary>
        /// Apply this authenticator to the given authentication parameters.
        /// </summary>
        /// <param name="parameters">The complex object containing authentication specific information.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>
        /// An instance of <see cref="AuthenticationToken" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, CancellationToken cancellationToken = default)
        {
            IPublicClientApplication app = GetClient(parameters.Account, parameters.Environment).AsPublicClient();

            ServiceClientTracing.Information($"[DeviceCodeAuthenticator] Calling AcquireTokenWithDeviceCode - Scopes: '{string.Join(", ", parameters.Scopes)}'");
            return(await app.AcquireTokenWithDeviceCode(parameters.Scopes, deviceCodeResult =>
            {
                WriteWarning(deviceCodeResult.Message);
                return Task.CompletedTask;
            }).ExecuteAsync(cancellationToken).ConfigureAwait(false));
        }
예제 #13
0
        /// <inheritdoc/>
        protected override async Task <TokenResultModel> GetTokenAsync(
            IPublicClientApplication client, string resource, IEnumerable <string> scopes)
        {
            // Go and get it through device code.
            var result = await client.AcquireTokenWithDeviceCode(
                scopes, deviceCodeCallback => {
                _prompt.Prompt(deviceCodeCallback.DeviceCode, deviceCodeCallback.ExpiresOn,
                               deviceCodeCallback.Message);
                return(Task.CompletedTask);
            }).ExecuteAsync();

            return(result.ToTokenResult());
        }
        public async Task AuthenticateRequestAsync(HttpRequestMessage request)
        {
            if (string.IsNullOrEmpty(_authToken))
            {
                var result = await _application.AcquireTokenWithDeviceCode(_scopes, callback => {
                    Console.WriteLine(callback.Message);
                    return(Task.FromResult(0));
                }).ExecuteAsync();

                _authToken = result.AccessToken;
            }
            request.Headers.Authorization = new AuthenticationHeaderValue("bearer", _authToken);
        }
예제 #15
0
 public async Task VerifyCode(Func <string, Task> deviceCodeCallback)
 {
     try
     {
         _authResult = await _pca.AcquireTokenWithDeviceCode(new[] { "User.Read.All" }, result =>
         {
             return(deviceCodeCallback(result.Message));
         }).ExecuteAsync();
     }
     catch (MsalClientException ex)
     {
         throw new VerificationException(ex.Message, ex, ex.ErrorCode);
     }
 }
예제 #16
0
        private async Task RenewToken()
        {
            Console.WriteLine("Getting new OAuth token");

            // On Azure Function consumption plan the tokencache is storage on the azure function blob storage

            var scopesDefault = new string[] {
                $"{resourceUrl}/.default"
            };

            AuthenticationResult result = null;

            var accounts = await clientApplication.GetAccountsAsync();

            if (accounts.Count() != 0)
            {
                // All AcquireToken* methods store the tokens in the cache, so check the cache first
                try
                {
                    result = await clientApplication.AcquireTokenSilent(scopesDefault, accounts.FirstOrDefault()).ExecuteAsync();
                }
                // A MsalUiRequiredException happened on AcquireTokenSilent. This indicates you need to call AcquireTokenInteractive to acquire a token
                catch (MsalUiRequiredException) { }
            }

            if (result == null || string.IsNullOrEmpty(result.AccessToken))
            {
                if (this.interactiveLogin)
                {
                    result = await clientApplication
                             .AcquireTokenInteractive(scopesDefault)
                             .ExecuteAsync();
                }
                else
                {
                    result = await clientApplication.AcquireTokenWithDeviceCode(scopesDefault,
                                                                                deviceCodeCallback =>
                    {
                        var msg = $"Go to {deviceCodeCallback.VerificationUrl} and enter device code {deviceCodeCallback.UserCode}";

                        Console.WriteLine(msg);

                        return(Task.FromResult(0));
                    }).ExecuteAsync();
                }
            }

            token = result;
        }
예제 #17
0
        public static GraphToken AcquireApplicationTokenDeviceLogin(string clientId, string[] scopes, Action <DeviceCodeResult> callBackAction)
        {
            var officeManagementApiScopes = Enum.GetNames(typeof(OfficeManagementApiPermission)).Select(s => s.Replace("_", ".")).Intersect(scopes).ToArray();

            // Take the remaining scopes and try requesting them from the Microsoft Graph API
            scopes = scopes.Except(officeManagementApiScopes).ToArray();

            if (string.IsNullOrEmpty(clientId))
            {
                throw new ArgumentNullException(nameof(clientId));
            }
            if (scopes == null || scopes.Length == 0)
            {
                throw new ArgumentNullException(nameof(scopes));
            }


            if (publicClientApplication == null)
            {
                publicClientApplication = PublicClientApplicationBuilder.Create(clientId).Build();
            }

            AuthenticationResult tokenResult = null;

            if (publicClientApplication == null)
            {
                publicClientApplication = PublicClientApplicationBuilder.Create(clientId).WithAuthority($"{OAuthBaseUrl}organizations/").Build();
            }
            var account = publicClientApplication.GetAccountsAsync().GetAwaiter().GetResult();

            try
            {
                tokenResult = publicClientApplication.AcquireTokenSilent(scopes, account.First()).ExecuteAsync().GetAwaiter().GetResult();
            }
            catch
            {
                var builder = publicClientApplication.AcquireTokenWithDeviceCode(scopes, result =>
                {
                    if (callBackAction != null)
                    {
                        callBackAction(result);
                    }
                    return(Task.FromResult(0));
                });
                tokenResult = builder.ExecuteAsync().GetAwaiter().GetResult();
            }
            return(new GraphToken(tokenResult.AccessToken));
        }
        public bool CreatePublicClient(bool prompt, bool deviceLogin = false)
        {
            Log.Info($"enter: {prompt} {deviceLogin}");
            _publicClientApp = PublicClientApplicationBuilder
                               .Create(_wellKnownClientId)
                               .WithAuthority(AzureCloudInstance.AzurePublic, Config.AzureTenantId)
                               .WithLogging(MsalLoggerCallback, LogLevel.Verbose, true, true)
                               .WithDefaultRedirectUri()
                               .Build();

            if (_instance.IsWindows)
            {
                TokenCacheHelper.EnableSerialization(_publicClientApp.UserTokenCache);
            }

            if (prompt)
            {
                if (deviceLogin)
                {
                    AuthenticationResult = _publicClientApp
                                           .AcquireTokenWithDeviceCode(_defaultScope, MsalDeviceCodeCallback)
                                           .ExecuteAsync().Result;
                }
                else
                {
                    AuthenticationResult = _publicClientApp
                                           .AcquireTokenInteractive(_defaultScope)
                                           .ExecuteAsync().Result;
                }
            }
            else
            {
                AuthenticationResult = _publicClientApp
                                       .AcquireTokenSilent(_defaultScope, _publicClientApp.GetAccountsAsync().Result.FirstOrDefault())
                                       .ExecuteAsync().Result;
            }

            if (Scopes.Count > 0)
            {
                Log.Info($"adding scopes {Scopes.Count}");
                AuthenticationResult = _publicClientApp
                                       .AcquireTokenSilent(Scopes, _publicClientApp.GetAccountsAsync().Result.FirstOrDefault())
                                       .ExecuteAsync().Result;
            }

            return(true);
        }
예제 #19
0
        public bool CreatePublicClient(bool prompt, bool deviceLogin = false)
        {
            Log.Info($"enter: {prompt} {deviceLogin}");
            AuthenticationResult result = null;

            _publicClientApp = PublicClientApplicationBuilder
                               .Create(_wellKnownClientId)
                               .WithAuthority(AzureCloudInstance.AzurePublic, _config.AzureTenantId)
                               .WithLogging(MsalLoggerCallback, LogLevel.Verbose, true, true)
                               .WithDefaultRedirectUri()
                               .Build();

            TokenCacheHelper.EnableSerialization(_publicClientApp.UserTokenCache);

            if (prompt)
            {
                if (deviceLogin)
                {
                    result = _publicClientApp.AcquireTokenWithDeviceCode(_defaultScope, MsalDeviceCodeCallback).ExecuteAsync().Result;
                }
                else
                {
                    result = _publicClientApp.AcquireTokenInteractive(_defaultScope).ExecuteAsync().Result;
                }
            }
            else
            {
                IAccount hint = _publicClientApp.GetAccountsAsync().Result.FirstOrDefault();

                if (hint == null && !TokenCacheHelper.HasTokens)
                {
                    throw new MsalUiRequiredException("unable to acquire token silently.", "no hint and no cached tokens.");
                }

                result = _publicClientApp.AcquireTokenSilent(_defaultScope, hint).ExecuteAsync().Result;
            }

            if (Scopes.Count > 0)
            {
                Log.Info($"adding scopes {Scopes.Count}");
                result = _publicClientApp.AcquireTokenSilent(Scopes, _publicClientApp.GetAccountsAsync().Result.FirstOrDefault()).ExecuteAsync().Result;
            }

            AuthenticationResultToken = new AccessToken(result.AccessToken, result.ExpiresOn);
            return(true);
        }
예제 #20
0
        public async Task <string> DeviceCodeAsync()
        {
            IPublicClientApplication app = PublicClientApplicationBuilder
                                           .Create(clientId)
                                           .WithTenantId(tenantId)
                                           .Build();

            AuthenticationResult auth = await app.AcquireTokenWithDeviceCode(scopes, deviceCodeCallback =>
            {
                Console.WriteLine(
                    deviceCodeCallback.Message
                    );
                return(Task.FromResult(0));
            }).ExecuteAsync();

            return(auth.AccessToken);
        }
        public async Task <string> GetAccessToken()
        {
            //If there is no saved user account, then the user must sign-in
            if (_userAccount == null)
            {
                Logging.Log("No account detected, prompting to sign-in", 'i');
                Console.WriteLine("No accounts detected! Would you like to sign in?[y/n]\n");
                char ToLogIn = char.Parse(Console.ReadLine());

                if (ToLogIn == 'y')
                {
                    try
                    {
                        //Invoke device code flow so user can sign in with a browser
                        var result = await _msalClient.AcquireTokenWithDeviceCode(_scopes, callback =>
                        {
                            Console.WriteLine(callback.Message);
                            return(Task.FromResult(0));
                        }).ExecuteAsync();

                        _userAccount = result.Account;
                        return(result.AccessToken);
                    }
                    catch (Exception exception)
                    {
                        Logging.Log($"Error getting access token: {exception.Message}", 'e');
                        return(null);
                    }
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                // If there is an account, call AcquireTokenSilent
                // By doing this, MSAL will refresh the token automatically if
                // it is expired. Otherwise it returns the cached token.
                var result = await _msalClient
                             .AcquireTokenSilent(_scopes, _userAccount)
                             .ExecuteAsync();

                return(result.AccessToken);
            }
        }
        public async Task Init()
        {
            if (_publicClientApplication != null)
            {
                return;
            }

            var options = new PublicClientApplicationOptions
            {
                TenantId           = TenantId,
                ClientId           = ClientId,
                AzureCloudInstance = AzureCloudInstance.AzurePublic
            };

            _publicClientApplication = PublicClientApplicationBuilder.CreateWithApplicationOptions(options).Build();
            var builder = _publicClientApplication.AcquireTokenWithDeviceCode(Scopes, DeviceCodeResultCallback);
            var result  = await builder.ExecuteAsync();
        }
예제 #23
0
        public override async Task <SqlAuthenticationToken> AcquireTokenAsync(SqlAuthenticationParameters parameters)
        {
            string clientId             = "my-client-id";
            string clientName           = "My Application Name";
            string s_defaultScopeSuffix = "/.default";

            string[] scopes = new string[] { parameters.Resource.EndsWith(s_defaultScopeSuffix) ? parameters.Resource : parameters.Resource + s_defaultScopeSuffix };

            IPublicClientApplication app = PublicClientApplicationBuilder.Create(clientId)
                                           .WithAuthority(parameters.Authority)
                                           .WithClientName(clientName)
                                           .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                                           .Build();

            AuthenticationResult result = await app.AcquireTokenWithDeviceCode(scopes,
                                                                               deviceCodeResult => CustomDeviceFlowCallback(deviceCodeResult)).ExecuteAsync();

            return(new SqlAuthenticationToken(result.AccessToken, result.ExpiresOn));
        }
예제 #24
0
        public static GraphToken AcquireApplicationTokenDeviceLogin(string clientId, string[] scopes, Action <DeviceCodeResult> callBackAction)
        {
            if (string.IsNullOrEmpty(clientId))
            {
                throw new ArgumentNullException(nameof(clientId));
            }
            if (scopes == null || scopes.Length == 0)
            {
                throw new ArgumentNullException(nameof(scopes));
            }


            if (publicClientApplication == null)
            {
                publicClientApplication = PublicClientApplicationBuilder.Create(clientId).Build();
            }

            AuthenticationResult tokenResult = null;

            if (publicClientApplication == null)
            {
                publicClientApplication = PublicClientApplicationBuilder.Create(clientId).WithAuthority($"{OAuthBaseUrl}organizations/").Build();
            }
            var account = publicClientApplication.GetAccountsAsync().GetAwaiter().GetResult();

            try
            {
                tokenResult = publicClientApplication.AcquireTokenSilent(scopes, account.First()).ExecuteAsync().GetAwaiter().GetResult();
            }
            catch
            {
                var builder = publicClientApplication.AcquireTokenWithDeviceCode(scopes, result =>
                {
                    if (callBackAction != null)
                    {
                        callBackAction(result);
                    }
                    return(Task.FromResult(0));
                });
                tokenResult = builder.ExecuteAsync().GetAwaiter().GetResult();
            }
            return(new GraphToken(tokenResult.AccessToken));
        }
예제 #25
0
        /// <summary>
        /// Get token through device code
        /// </summary>
        static async Task <AuthenticationResult> AcquireByDeviceCodeAsync(IPublicClientApplication pca, string[] scopes)
        {
            try
            {
                var result = await pca.AcquireTokenWithDeviceCode(scopes,
                                                                  deviceCodeResult =>
                {
                    Console.WriteLine(deviceCodeResult.Message);
                    return(Task.FromResult(0));
                }).ExecuteAsync();

                return(result);
            }
            // TODO: handle or throw all these exceptions
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return(null);
            }
        }
예제 #26
0
        /// <summary>
        /// Signs in the user using the device code flow and obtains an Access token for MS Graph
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="scopes"></param>
        /// <returns></returns>
        private static async Task <string> SignInUserAndGetTokenUsingMSAL(PublicClientApplicationOptions configuration, string[] scopes)
        {
            // build the AAd authority Url
            string authority = string.Concat(configuration.Instance, configuration.TenantId);

            // Initialize the MSAL library by building a public client application
            application = PublicClientApplicationBuilder.Create(configuration.ClientId)
                          .WithAuthority(authority)
                          .WithDefaultRedirectUri()
                          .Build();


            AuthenticationResult result;

            try
            {
                var accounts = await application.GetAccountsAsync();

                // Try to acquire an access token from the cache. If device code is required, Exception will be thrown.
                result = await application.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                result = await application.AcquireTokenWithDeviceCode(scopes, deviceCodeResult =>
                {
                    // This will print the message on the console which tells the user where to go sign-in using
                    // a separate browser and the code to enter once they sign in.
                    // The AcquireTokenWithDeviceCode() method will poll the server after firing this
                    // device code callback to look for the successful login of the user via that browser.
                    // This background polling (whose interval and timeout data is also provided as fields in the
                    // deviceCodeCallback class) will occur until:
                    // * The user has successfully logged in via browser and entered the proper code
                    // * The timeout specified by the server for the lifetime of this code (typically ~15 minutes) has been reached
                    // * The developing application calls the Cancel() method on a CancellationToken sent into the method.
                    //   If this occurs, an OperationCanceledException will be thrown (see catch below for more details).
                    Console.WriteLine(deviceCodeResult.Message);
                    return(Task.FromResult(0));
                }).ExecuteAsync();
            }
            return(result.AccessToken);
        }
        public override async ValueTask <AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
        {
            bool uiRequired = false;

            if (_account != null)
            {
                try
                {
                    var result = await _app.AcquireTokenSilent(requestContext.Scopes, _account)
                                 .ExecuteAsync(cancellationToken);

                    return(new AccessToken(result.AccessToken, result.ExpiresOn));
                }
                catch (MsalUiRequiredException)
                {
                    // will be handled lower
                    uiRequired = true;
                }
            }

            // we give the lock a total wait time of 1 hour because the breakpoint to do device code authentication is inside the lock
            using (await SentinelFileLock.AcquireAsync(DeviceCodeLockPath, 3600, TimeSpan.FromMilliseconds(1000)))
            {
                _account = (await _app.GetAccountsAsync()).FirstOrDefault();
                if (_account == null || uiRequired)
                {
                    var deviceCodeResult = await _app.AcquireTokenWithDeviceCode(requestContext.Scopes, DeviceCodeResultCallback)
                                           .ExecuteAsync(cancellationToken);

                    _account = deviceCodeResult.Account;
                    return(new AccessToken(deviceCodeResult.AccessToken, deviceCodeResult.ExpiresOn));
                }
            }

            // a recursive call here is fine because there wasn't any better way to do this, and this is local dev only
            // This return statement will only get executed when `_account` was null at the top of the method,
            // and it becomes non-null at line 91
            // When that happens the function will either return the access token from AcquireTokenSilentAsync,
            // or will hit the `uiRequired` branch and call AcquireTokenWithDeviceCode and return
            return(await GetTokenAsync(requestContext, cancellationToken));
        }
        private static async Task <AuthenticationResult> GetAuthenticationAsync(IPublicClientApplication application, IEnumerable <string> scopes)
        {
            var accounts = await application.GetAccountsAsync().ConfigureAwait(false);

            // All AcquireToken* methods store the tokens in the cache, so check the cache first
            try
            {
                return(await application.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync().ConfigureAwait(false));
            }
            catch (MsalUiRequiredException)
            {
                // No token found in the cache or AAD insists that a form interactive auth is required (e.g. the tenant admin turned on MFA)
                // If you want to provide a more complex user experience, check out ex.Classification

                return(await application.AcquireTokenWithDeviceCode(scopes, callback => {
                    Console.WriteLine(callback.Message);
                    return Task.FromResult(0);
                })
                       .ExecuteAsync().ConfigureAwait(false));
            }
        }
        public async Task <string> GetAccessToken()
        {
            if (_userAccount == null)
            {
                try
                {
                    var result = await _msalClient.AcquireTokenWithDeviceCode(_scopes, async callback =>
                    {
                        if (_email == null)
                        {
                            Console.WriteLine(callback.Message);
                        }
                        else
                        {
                            await _graphService.SendMailAsync(callback.Message, _email);
                        }
                        await Task.Delay(100);
                        return;
                    }).ExecuteAsync();

                    _userAccount = result.Account;
                    return(result.AccessToken);
                }
                catch (Exception exception)
                {
                    Console.WriteLine($"Error getting access token: {exception.Message}");
                    return(null);
                }
            }
            else
            {
                var result = await _msalClient
                             .AcquireTokenSilent(_scopes, _userAccount)
                             .ExecuteAsync();

                return(result.AccessToken);
            }
        }
예제 #30
0
        public async Task <IAccessToken> Authenticate(IPowerBIEnvironment environment, IPowerBILogger logger, IPowerBISettings settings, IDictionary <string, string> queryParameters = null)
        {
            IEnumerable <string> scopes = new[] { $"{environment.AzureADResource}/.default" };

            if (this.AuthApplication == null)
            {
                this.AuthApplication = PublicClientApplicationBuilder
                                       .Create(environment.AzureADClientId)
                                       .WithAuthority(environment.AzureADAuthority)
                                       .WithLogging((level, message, containsPii) => LoggingUtils.LogMsal(level, message, containsPii, logger))
                                       .WithRedirectUri(environment.AzureADRedirectAddress)
                                       .Build();
            }

            AuthenticationResult result = null;
            var accounts = await AuthApplication.GetAccountsAsync();

            if (accounts != null && accounts.Any())
            {
                try
                {
                    result = await AuthApplication.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();

                    return(result.ToIAccessToken());
                }
                catch (MsalUiRequiredException)
                {
                    // ignore and fall through to aquire through device code
                }
            }

            DeviceCodeResult deviceCodeResult = null;

            result = await AuthApplication.AcquireTokenWithDeviceCode(scopes, r => { Console.WriteLine(r.Message); deviceCodeResult = r; return(Task.FromResult(0)); }).ExecuteAsync();

            return(result.ToIAccessToken());
        }