예제 #1
0
        /// <summary>
        /// Registers the token cache with client application.
        /// </summary>
        /// <param name="client">The client application to be used when registering the token cache.</param>
        public virtual void RegisterCache(IClientApplicationBase client)
        {
            ClientId = client.AppConfig.ClientId;

            client.UserTokenCache.SetAfterAccess(AfterAccessNotification);
            client.UserTokenCache.SetBeforeAccess(BeforeAccessNotification);
        }
예제 #2
0
        /// <summary>
        /// Get account info for the user
        /// </summary>
        /// <param name="application"></param>
        /// <param name="user"></param>
        /// <returns></returns>
        public static async Task <IAccount> GetUserAccountAsync(IClientApplicationBase application,
                                                                ClaimsPrincipal user)
        {
            var      accountId = user.GetMsalAccountId();
            IAccount account   = null;

            if (accountId != null)
            {
                account = await application.GetAccountAsync(accountId);

                // Special case for guest users as the Guest oid / tenant id are not surfaced.
                if (account == null)
                {
                    var loginHint = user.GetLoginHint();
                    if (loginHint == null)
                    {
                        throw new ArgumentNullException(nameof(loginHint));
                    }
                    var accounts = await application.GetAccountsAsync();

                    account = accounts.FirstOrDefault(a => a.Username == loginHint);
                }
            }
            return(account);
        }
예제 #3
0
        public void OnBehalfOfProvider_ShouldCreateConfidentialClientApplicationWithMandatoryParams()
        {
            IClientApplicationBase clientApp = OnBehalfOfProvider.CreateClientApplication(_clientId, _redirectUri, _clientCredential);

            Assert.IsInstanceOfType(clientApp, typeof(ConfidentialClientApplication), "Unexpected client application set.");
            Assert.AreEqual(_clientId, clientApp.ClientId, "Wrong client id set.");
            Assert.AreEqual(string.Format(AuthConstants.CloudList[NationalCloud.Global], AuthConstants.Tenants.Common), clientApp.Authority, "Wrong authority set.");
        }
예제 #4
0
        public void UsernamePasswordProvider_ShouldCreatePublicClientApplicationWithMandatoryParams()
        {
            IClientApplicationBase clientApp = UsernamePasswordProvider.CreateClientApplication(_clientId);

            Assert.IsInstanceOfType(clientApp, typeof(PublicClientApplication), "Unexpected client application set.");
            Assert.AreEqual(_clientId, clientApp.ClientId, "Wrong client id set.");
            Assert.AreEqual(string.Format(AuthConstants.CloudList[NationalCloud.Global], AuthConstants.Tenants.Organizations), clientApp.Authority, "Wrong authority set.");
        }
예제 #5
0
        public void InteractiveAuthProvider_ShouldCreatePublicClientApplicationForConfiguredCloud()
        {
            string testTenant = "infotest";
            IClientApplicationBase clientApp = InteractiveAuthenticationProvider.CreateClientApplication(_clientId, null, testTenant, NationalCloud.China);

            Assert.IsInstanceOfType(clientApp, typeof(PublicClientApplication), "Unexpected client application set.");
            Assert.AreEqual(_clientId, clientApp.ClientId, "Wrong client id set.");
            Assert.AreEqual(string.Format(AuthConstants.CloudList[NationalCloud.China], testTenant), clientApp.Authority, "Wrong authority set.");
        }
예제 #6
0
        public void OnBehalfOfProvider_ShouldCreateConfidentialClientApplicationForConfiguredCloud()
        {
            string testTenant = "infotest";
            IClientApplicationBase clientApp = OnBehalfOfProvider.CreateClientApplication(_clientId, _redirectUri, _clientCredential, null, testTenant, NationalCloud.China);

            Assert.IsInstanceOfType(clientApp, typeof(ConfidentialClientApplication), "Unexpected client application set.");
            Assert.AreEqual(_clientId, clientApp.ClientId, "Wrong client id set.");
            Assert.AreEqual(string.Format(AuthConstants.CloudList[NationalCloud.China], testTenant), clientApp.Authority, "Wrong authority set.");
        }
        public async Task SetupAsync()
        {
            ClientApplication = Substitute.For <IClientApplicationBase, IClientApplicationBaseExecutor>();

            await((IClientApplicationBaseExecutor)ClientApplication).ExecuteAsync(
                Arg.Do <AcquireTokenCommonParameters>(parameters => CommonParametersReceived = parameters),
                Arg.Do <AcquireTokenSilentParameters>(parameters => SilentParametersReceived = parameters),
                CancellationToken.None).ConfigureAwait(false);
        }
        private ClientContext BuildClientContext(IClientApplicationBase application, string siteUrl, string[] scopes, ClientContextType contextType)
        {
            var clientContext = new ClientContext(siteUrl)
            {
                DisableReturnValueCache = true
            };

            clientContext.ExecutingWebRequest += (sender, args) =>
            {
                AuthenticationResult ar = null;

                var accounts = application.GetAccountsAsync().GetAwaiter().GetResult();
                if (accounts.Count() > 0)
                {
                    ar = application.AcquireTokenSilent(scopes, accounts.First()).ExecuteAsync().GetAwaiter().GetResult();
                }
                else
                {
                    switch (contextType)
                    {
                    case ClientContextType.AzureADCertificate:
                    {
                        ar = ((IConfidentialClientApplication)application).AcquireTokenForClient(scopes).ExecuteAsync().GetAwaiter().GetResult();
                        break;
                    }

                    case ClientContextType.AzureADCredentials:
                    {
                        ar = ((IPublicClientApplication)application).AcquireTokenByUsernamePassword(scopes, username, password).ExecuteAsync().GetAwaiter().GetResult();
                        break;
                    }

                    case ClientContextType.AzureADInteractive:
                    {
                        ar = ((IPublicClientApplication)application).AcquireTokenInteractive(scopes).ExecuteAsync().GetAwaiter().GetResult();
                        break;
                    }
                    }
                }
                if (ar != null && ar.AccessToken != null)
                {
                    args.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + ar.AccessToken;
                }
            };

            ClientContextSettings clientContextSettings = new ClientContextSettings()
            {
                Type    = contextType,
                SiteUrl = siteUrl,
                AuthenticationManager = this,
            };

            clientContext.AddContextSettings(clientContextSettings);

            return(clientContext);
        }
예제 #9
0
 public MsalTokenCachePowerShellSerializer(
     IClientApplicationBase msalApplication,
     List <PSObject> profiles
     ) : base()
 {
     this.msalApplication = msalApplication
                            ?? throw new ArgumentNullException(nameof(msalApplication));
     this.profiles = profiles
                     ?? throw new ArgumentNullException(nameof(profiles));
 }
예제 #10
0
        /// <summary>
        /// Attempts to acquire access token silently from the token cache.
        /// </summary>
        /// <exception cref="AuthenticationException">An exception occured when attempting to get access token silently.</exception>
        internal static async Task <AuthenticationResult> GetAccessTokenSilentAsync(this IClientApplicationBase clientApplication, AuthenticationProviderOption msalAuthProviderOption)
        {
            IAccount account;

            if (msalAuthProviderOption.UserAccount?.ObjectId != null)
            {
                // Parse GraphUserAccount to IAccount instance
                account = new GraphAccount(msalAuthProviderOption.UserAccount);
            }
            else
            {
                // If no graph user account is passed, try get the one in cache.
                IEnumerable <IAccount> accounts = await clientApplication.GetAccountsAsync();

                account = accounts.FirstOrDefault();
            }

            if (account == null)
            {
                return(null);
            }

            try
            {
                AcquireTokenSilentParameterBuilder tokenSilentBuilder = clientApplication.AcquireTokenSilent(msalAuthProviderOption.Scopes, account)
                                                                        .WithForceRefresh(msalAuthProviderOption.ForceRefresh);

                if (!ContainsWellKnownTenantName(clientApplication.Authority))
                {
                    tokenSilentBuilder.WithAuthority(clientApplication.Authority);
                }

                if (!string.IsNullOrEmpty(msalAuthProviderOption.Claims))
                {
                    tokenSilentBuilder.WithClaims(msalAuthProviderOption.Claims);
                }

                return(await tokenSilentBuilder.ExecuteAsync());
            }
            catch (MsalException)
            {
                return(null);
            }
            catch (Exception exception)
            {
                throw new AuthenticationException(
                          new Error
                {
                    Code    = ErrorConstants.Codes.GeneralException,
                    Message = ErrorConstants.Message.UnexpectedException
                },
                          exception);
            }
        }
예제 #11
0
        /// <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)
        {
            IClientApplicationBase app = GetClient(parameters.Account, parameters.Environment);

            ServiceClientTracing.Information($"[DeviceCodeAuthenticator] Calling AcquireTokenWithDeviceCode - Scopes: '{string.Join(", ", parameters.Scopes)}'");

            return(await app.AsPublicClient().AcquireTokenWithDeviceCode(parameters.Scopes, deviceCodeResult =>
            {
                WriteWarning(deviceCodeResult.Message);
                return Task.CompletedTask;
            }).ExecuteAsync(cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Apply this authenticator to the given authentication parameters.
        /// </summary>
        /// <param name="parameters">The complex object containing authentication specific information.</param>
        /// <param name="promptAction">The action used to prompt for interaction.</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="AuthenticationResult" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, Action <string> promptAction = null, CancellationToken cancellationToken = default)
        {
            IClientApplicationBase app = GetClient(parameters.Account, parameters.Environment);
            IAccount account           = await app.GetAccountAsync(parameters.Account.Identifier).ConfigureAwait(false);

            if (account != null)
            {
                return(await app.AcquireTokenSilent(parameters.Scopes, account).ExecuteAsync(cancellationToken).ConfigureAwait(false));
            }

            return(await app.AsRefreshTokenClient().AcquireTokenByRefreshToken(
                       parameters.Scopes,
                       parameters.Account.GetProperty(PartnerAccountPropertyType.RefreshToken)).ExecuteAsync(cancellationToken).ConfigureAwait(false));
        }
        /// <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="AuthenticationResult" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, CancellationToken cancellationToken = default)
        {
            IClientApplicationBase app = GetClient(parameters.Account, parameters.Environment);

            ServiceClientTracing.Information("[SilentAuthenticator] Calling GetAccountsAsync");
            IEnumerable <IAccount> accounts = await app.AsPublicClient().GetAccountsAsync().ConfigureAwait(false);

            ServiceClientTracing.Information($"[SilentAuthenticator] Calling AcquireTokenSilent - Scopes: '{string.Join(",", parameters.Scopes)}', UserId: '{((SilentParameters)parameters).UserId}', Number of accounts: '{accounts.Count()}'");
            AuthenticationResult authResult = await app.AsPublicClient().AcquireTokenSilent(
                parameters.Scopes,
                accounts.FirstOrDefault(a => a.HomeAccountId.ObjectId.Equals(((SilentParameters)parameters).UserId, StringComparison.InvariantCultureIgnoreCase)))
                                              .ExecuteAsync(cancellationToken).ConfigureAwait(false);

            return(authResult);
        }
예제 #14
0
        /// <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="AuthenticationResult" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, CancellationToken cancellationToken = default)
        {
            IClientApplicationBase app = GetClient(parameters.Account, parameters.Environment);

            ServiceClientTracing.Information("[RefreshTokenAuthenticator] Calling GetAccountsAysnc");
            IAccount account = await app.GetAccountAsync(parameters.Account.Identifier).ConfigureAwait(false);

            if (account != null)
            {
                ServiceClientTracing.Information($"[RefreshTokenAuthenticator] Calling AcquireTokenSilent - Scopes: '{string.Join(", ", parameters.Scopes)}'");
                return(await app.AcquireTokenSilent(parameters.Scopes, account).ExecuteAsync(cancellationToken).ConfigureAwait(false));
            }

            ServiceClientTracing.Information($"[RefreshTokenAuthenticator] Calling AcquireTokenByRefreshToken - Scopes: '{string.Join(", ", parameters.Scopes)}'");
            return(await app.AsRefreshTokenClient().AcquireTokenByRefreshToken(
                       parameters.Scopes,
                       parameters.Account.GetProperty(PartnerAccountPropertyType.RefreshToken)).ExecuteAsync(cancellationToken).ConfigureAwait(false));
        }
        public static void InitializeTokenCacheFromString(this IClientApplicationBase app, string content, bool updateATExpiry = false)
        {
            if (updateATExpiry)
            {
                var cacheJson = JObject.Parse(content);

                JEnumerable <JToken> tokens = cacheJson["AccessToken"].Children();
                foreach (JToken token in tokens)
                {
                    var obj = token.Children().Single() as JObject;

                    obj["expires_on"]          = DateTimeHelpers.DateTimeToUnixTimestamp(DateTimeOffset.Now.AddMinutes(100));
                    obj["extended_expires_on"] = DateTimeHelpers.DateTimeToUnixTimestamp(DateTimeOffset.Now.AddMinutes(100));
                }

                content = cacheJson.ToString();
            }

            byte[] tokenCacheBlob = new UTF8Encoding().GetBytes(content);
            ((ITokenCacheSerializer)app.UserTokenCache).DeserializeMsalV3(tokenCacheBlob);
        }
예제 #16
0
        protected override void ProcessRecord()
        {
            base.ProcessRecord();

            AuthConfig authConfig = new AuthConfig {
                TenantId = TenantId
            };
            CancellationToken cancellationToken = CancellationToken.None;

            if (ParameterSetName == Constants.UserParameterSet)
            {
                // 2 mins timeout. 1 min < HTTP timeout.
                TimeSpan authTimeout        = new TimeSpan(0, 0, Constants.MaxDeviceCodeTimeOut);
                CancellationTokenSource cts = new CancellationTokenSource(authTimeout);
                cancellationToken = cts.Token;

                authConfig.AuthType = AuthenticationType.Delegated;
                authConfig.Scopes   = Scopes ?? new string[] { "User.Read" };
            }
            else
            {
                authConfig.AuthType = AuthenticationType.AppOnly;
                authConfig.ClientId = ClientId;
                authConfig.CertificateThumbprint = CertificateThumbprint;
                authConfig.CertificateName       = CertificateName;
            }

            try
            {
                // Gets a static instance of IAuthenticationProvider when the client app hasn't changed.
                IAuthenticationProvider authProvider      = AuthenticationHelpers.GetAuthProvider(authConfig);
                IClientApplicationBase  clientApplication = null;
                if (ParameterSetName == Constants.UserParameterSet)
                {
                    clientApplication = (authProvider as DeviceCodeProvider).ClientApplication;
                }
                else
                {
                    clientApplication = (authProvider as ClientCredentialProvider).ClientApplication;
                }

                // Incremental scope consent without re-instanciating the auth provider. We will use a static instance.
                GraphRequestContext graphRequestContext = new GraphRequestContext();
                graphRequestContext.CancellationToken = cancellationToken;
                graphRequestContext.MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new AuthenticationProviderOption
                            {
                                Scopes       = authConfig.Scopes,
                                ForceRefresh = ForceRefresh
                            }
                        }
                    }
                };

                // Trigger consent.
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
                httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), graphRequestContext);
                authProvider.AuthenticateRequestAsync(httpRequestMessage).GetAwaiter().GetResult();

                var accounts = clientApplication.GetAccountsAsync().GetAwaiter().GetResult();
                var account  = accounts.FirstOrDefault();

                JwtPayload jwtPayload = JwtHelpers.DecodeToObject <JwtPayload>(httpRequestMessage.Headers.Authorization?.Parameter);
                authConfig.Scopes   = jwtPayload?.Scp?.Split(' ') ?? jwtPayload?.Roles;
                authConfig.TenantId = jwtPayload?.Tid ?? account?.HomeAccountId?.TenantId;
                authConfig.AppName  = jwtPayload?.AppDisplayname;
                authConfig.Account  = jwtPayload?.Upn ?? account?.Username;

                // Save auth config to session state.
                SessionState.PSVariable.Set(Constants.GraphAuthConfigId, authConfig);
            }
            catch (AuthenticationException authEx)
            {
                if ((authEx.InnerException is TaskCanceledException) && cancellationToken.IsCancellationRequested)
                {
                    throw new Exception($"Device code terminal timed-out after {Constants.MaxDeviceCodeTimeOut} seconds. Please try again.");
                }
                else
                {
                    throw authEx.InnerException ?? authEx;
                }
            }
            catch (Exception ex)
            {
                throw ex.InnerException ?? ex;
            }

            WriteObject("Welcome To Microsoft Graph!");
        }
예제 #17
0
        /// <summary>
        /// Registers the token cache with client application.
        /// </summary>
        /// <param name="client">The client application to be used when registering the token cache.</param>
        public override void RegisterCache(IClientApplicationBase client)
        {
            ServiceClientTracing.Information("Registering the persistent token cache.");

            base.RegisterCache(client);
        }
 /// <summary>
 /// Converts the client application to a refresh token client.
 /// </summary>
 /// <param name="app">The base client application to be converted.</param>
 /// <returns>A refresh token client represents the client application.</returns>
 public static IByRefreshToken AsRefreshTokenClient(this IClientApplicationBase app)
 {
     return(app as IByRefreshToken);
 }
 /// <summary>
 /// Converts the client application to a confidential client.
 /// </summary>
 /// <param name="app">The base client application to be converted.</param>
 /// <returns>A confidential client represents the client application.</returns>
 public static IConfidentialClientApplication AsConfidentialClient(this IClientApplicationBase app)
 {
     return(app as IConfidentialClientApplication);
 }
예제 #20
0
        /// <summary>
        /// Authenticates the client using the provided <see cref="IAuthContext"/>.
        /// </summary>
        /// <param name="authContext">The <see cref="IAuthContext"/> to authenticate.</param>
        /// <param name="forceRefresh">Whether or not to force refresh a token if one exists.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <param name="fallBackWarning">Callback to report FallBack to DeviceCode Authentication</param>
        /// <returns></returns>
        public static async Task <IAuthContext> AuthenticateAsync(IAuthContext authContext, bool forceRefresh, CancellationToken cancellationToken, Action fallBackWarning = null)
        {
            // Gets a static instance of IAuthenticationProvider when the client app hasn't changed.
            var authProvider = AuthenticationHelpers.GetAuthProvider(authContext);
            IClientApplicationBase clientApplication = null;

            switch (authContext.AuthProviderType)
            {
            case AuthProviderType.DeviceCodeProvider:
            case AuthProviderType.DeviceCodeProviderFallBack:
                clientApplication = (authProvider as DeviceCodeProvider).ClientApplication;
                break;

            case AuthProviderType.InteractiveAuthenticationProvider:
            {
                var interactiveProvider = (authProvider as InteractiveAuthenticationProvider).ClientApplication;
                //When User is not Interactive, Pre-Emptively Fallback and warn, to DeviceCode
                if (!interactiveProvider.IsUserInteractive())
                {
                    authContext.AuthProviderType = AuthProviderType.DeviceCodeProviderFallBack;
                    fallBackWarning?.Invoke();
                    var fallBackAuthContext = await AuthenticateAsync(authContext, forceRefresh, cancellationToken, fallBackWarning);

                    return(fallBackAuthContext);
                }
                break;
            }

            case AuthProviderType.ClientCredentialProvider:
            {
                clientApplication = (authProvider as ClientCredentialProvider).ClientApplication;
                break;
            }
            }
            try
            {
                // Incremental scope consent without re-instantiating the auth provider. We will use provided instance.
                GraphRequestContext graphRequestContext = new GraphRequestContext();
                graphRequestContext.CancellationToken = cancellationToken;
                graphRequestContext.MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new AuthenticationProviderOption
                            {
                                Scopes       = authContext.Scopes,
                                ForceRefresh = forceRefresh
                            }
                        }
                    }
                };

                // Trigger consent.
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
                httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), graphRequestContext);
                await authProvider.AuthenticateRequestAsync(httpRequestMessage);

                IAccount account = null;
                if (clientApplication != null)
                {
                    // Only get accounts when we are using MSAL to get an access token.
                    IEnumerable <IAccount> accounts = clientApplication.GetAccountsAsync().GetAwaiter().GetResult();
                    account = accounts.FirstOrDefault();
                }

                JwtHelpers.DecodeJWT(httpRequestMessage.Headers.Authorization?.Parameter, account, ref authContext);
                return(authContext);
            }
            catch (AuthenticationException authEx)
            {
                //Interactive Authentication Failure: Could Not Open Browser, fallback to DeviceAuth
                if (IsUnableToOpenWebPageError(authEx))
                {
                    authContext.AuthProviderType = AuthProviderType.DeviceCodeProviderFallBack;
                    //ReAuthenticate using DeviceCode as fallback.
                    var fallBackAuthContext = await AuthenticateAsync(authContext, forceRefresh, cancellationToken);

                    //Indicate that this was a Fallback
                    if (fallBackWarning != null && fallBackAuthContext.AuthProviderType == AuthProviderType.DeviceCodeProviderFallBack)
                    {
                        fallBackWarning();
                    }
                    return(fallBackAuthContext);
                }

                if (authEx.InnerException is TaskCanceledException && cancellationToken.IsCancellationRequested)
                {
                    // Authentication requets timeout.
                    throw new Exception(string.Format(CultureInfo.CurrentCulture, ErrorConstants.Message.DeviceCodeTimeout, Constants.MaxDeviceCodeTimeOut));
                }
                else if (authEx.InnerException is MsalServiceException msalServiceEx &&
                         msalServiceEx.StatusCode == 400 &&
                         msalServiceEx.ErrorCode == "invalid_scope" &&
                         string.IsNullOrWhiteSpace(authContext.TenantId) &&
                         (authContext.AuthProviderType == AuthProviderType.DeviceCodeProvider ||
                          authContext.AuthProviderType == AuthProviderType.DeviceCodeProviderFallBack))
                {
                    // MSAL scope validation error. Ask customer to specify sign-in audience or tenant Id.
                    throw new MsalClientException(msalServiceEx.ErrorCode, $"{msalServiceEx.Message}.\r\n{ErrorConstants.Message.InvalidScope}", msalServiceEx);
                }

                //Something Unknown Went Wrong
                throw authEx.InnerException ?? authEx;
            }
            catch (Exception ex)
            {
                throw ex.InnerException ?? ex;
            }
        }
예제 #21
0
        /// <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="AuthenticationResult" /> that represents the access token generated as result of a successful authenication.
        /// </returns>
        public override async Task <AuthenticationResult> AuthenticateAsync(AuthenticationParameters parameters, CancellationToken cancellationToken = default)
        {
            IClientApplicationBase app = GetClient(parameters.Account, parameters.Environment);

            return(await app.AsConfidentialClient().AcquireTokenForClient(parameters.Scopes).ExecuteAsync(cancellationToken).ConfigureAwait(false));
        }
        protected override void ProcessRecord()
        {
            base.ProcessRecord();
            IAuthContext authContext = new AuthContext {
                TenantId = TenantId
            };

            cancellationTokenSource = new CancellationTokenSource();
            // Set selected environment to the session object.
            GraphSession.Instance.Environment = environment;

            switch (ParameterSetName)
            {
            case Constants.UserParameterSet:
            {
                // 2 mins timeout. 1 min < HTTP timeout.
                TimeSpan authTimeout = new TimeSpan(0, 0, Constants.MaxDeviceCodeTimeOut);
                cancellationTokenSource = new CancellationTokenSource(authTimeout);
                authContext.AuthType    = AuthenticationType.Delegated;
                string[] processedScopes = ProcessScopes(Scopes);
                authContext.Scopes = processedScopes.Length == 0 ? new string[] { "User.Read" } : processedScopes;
                // Default to CurrentUser but allow the customer to change this via `ContextScope` param.
                authContext.ContextScope = this.IsParameterBound(nameof(ContextScope)) ? ContextScope : ContextScope.CurrentUser;
            }
            break;

            case Constants.AppParameterSet:
            {
                authContext.AuthType = AuthenticationType.AppOnly;
                authContext.ClientId = ClientId;
                authContext.CertificateThumbprint = CertificateThumbprint;
                authContext.CertificateName       = CertificateName;
                // Default to Process but allow the customer to change this via `ContextScope` param.
                authContext.ContextScope = this.IsParameterBound(nameof(ContextScope)) ? ContextScope : ContextScope.Process;
            }
            break;

            case Constants.AccessTokenParameterSet:
            {
                authContext.AuthType     = AuthenticationType.UserProvidedAccessToken;
                authContext.ContextScope = ContextScope.Process;
                // Store user provided access token to a session object.
                GraphSession.Instance.UserProvidedToken = new NetworkCredential(string.Empty, AccessToken).SecurePassword;
            }
            break;
            }

            CancellationToken cancellationToken = cancellationTokenSource.Token;

            try
            {
                // Gets a static instance of IAuthenticationProvider when the client app hasn't changed.
                IAuthenticationProvider authProvider      = AuthenticationHelpers.GetAuthProvider(authContext);
                IClientApplicationBase  clientApplication = null;
                if (ParameterSetName == Constants.UserParameterSet)
                {
                    clientApplication = (authProvider as DeviceCodeProvider).ClientApplication;
                }
                else if (ParameterSetName == Constants.AppParameterSet)
                {
                    clientApplication = (authProvider as ClientCredentialProvider).ClientApplication;
                }

                // Incremental scope consent without re-instantiating the auth provider. We will use a static instance.
                GraphRequestContext graphRequestContext = new GraphRequestContext();
                graphRequestContext.CancellationToken = cancellationToken;
                graphRequestContext.MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new AuthenticationProviderOption
                            {
                                Scopes       = authContext.Scopes,
                                ForceRefresh = ForceRefresh
                            }
                        }
                    }
                };

                // Trigger consent.
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
                httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), graphRequestContext);
                authProvider.AuthenticateRequestAsync(httpRequestMessage).GetAwaiter().GetResult();

                IAccount account = null;
                if (clientApplication != null)
                {
                    // Only get accounts when we are using MSAL to get an access token.
                    IEnumerable <IAccount> accounts = clientApplication.GetAccountsAsync().GetAwaiter().GetResult();
                    account = accounts.FirstOrDefault();
                }
                DecodeJWT(httpRequestMessage.Headers.Authorization?.Parameter, account, ref authContext);

                // Save auth context to session state.
                GraphSession.Instance.AuthContext = authContext;
            }
            catch (AuthenticationException authEx)
            {
                if ((authEx.InnerException is TaskCanceledException) && cancellationToken.IsCancellationRequested)
                {
                    // DeviceCodeTimeout
                    throw new Exception(string.Format(
                                            CultureInfo.CurrentCulture,
                                            ErrorConstants.Message.DeviceCodeTimeout,
                                            Constants.MaxDeviceCodeTimeOut));
                }
                else
                {
                    throw authEx.InnerException ?? authEx;
                }
            }
            catch (Exception ex)
            {
                throw ex.InnerException ?? ex;
            }

            WriteObject("Welcome To Microsoft Graph!");
        }
 /// <summary>
 /// Converts the client application to a public client.
 /// </summary>
 /// <param name="app">The base client application to be converted.</param>
 /// <returns>A public client represents the client application.</returns>
 public static IPublicClientApplication AsPublicClient(this IClientApplicationBase app)
 {
     return(app as IPublicClientApplication);
 }
        public static void InitializeTokenCacheFromFile(this IClientApplicationBase app, string resourceFile, bool updateATExpiry = false)
        {
            string tokenCacheAsString = File.ReadAllText(resourceFile);

            InitializeTokenCacheFromString(app, tokenCacheAsString, updateATExpiry);
        }
 public GraphMsalAuthenticationProvider(IClientApplicationBase clientApplication, string[] scopes)
 {
     _clientApplication = clientApplication;
     _scopes            = scopes;
 }
        /// <summary>
        /// Authenticates the client using the provided <see cref="IAuthContext"/>.
        /// </summary>
        /// <param name="authContext">The <see cref="IAuthContext"/> to authenticate.</param>
        /// <param name="forceRefresh">Whether or not to force refresh a token if one exists.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns></returns>
        public static async Task <IAuthContext> AuthenticateAsync(IAuthContext authContext, bool forceRefresh, CancellationToken cancellationToken)
        {
            try
            {
                // Gets a static instance of IAuthenticationProvider when the client app hasn't changed.
                IAuthenticationProvider authProvider      = AuthenticationHelpers.GetAuthProvider(authContext);
                IClientApplicationBase  clientApplication = null;
                if (authContext.AuthType == AuthenticationType.Delegated)
                {
                    clientApplication = (authProvider as DeviceCodeProvider).ClientApplication;
                }
                if (authContext.AuthType == AuthenticationType.AppOnly)
                {
                    clientApplication = (authProvider as ClientCredentialProvider).ClientApplication;
                }

                // Incremental scope consent without re-instantiating the auth provider. We will use a static instance.
                GraphRequestContext graphRequestContext = new GraphRequestContext();
                graphRequestContext.CancellationToken = cancellationToken;
                graphRequestContext.MiddlewareOptions = new Dictionary <string, IMiddlewareOption>
                {
                    {
                        typeof(AuthenticationHandlerOption).ToString(),
                        new AuthenticationHandlerOption
                        {
                            AuthenticationProviderOption = new AuthenticationProviderOption
                            {
                                Scopes       = authContext.Scopes,
                                ForceRefresh = forceRefresh
                            }
                        }
                    }
                };

                // Trigger consent.
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
                httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), graphRequestContext);
                await authProvider.AuthenticateRequestAsync(httpRequestMessage);

                IAccount account = null;
                if (clientApplication != null)
                {
                    // Only get accounts when we are using MSAL to get an access token.
                    IEnumerable <IAccount> accounts = clientApplication.GetAccountsAsync().GetAwaiter().GetResult();
                    account = accounts.FirstOrDefault();
                }

                JwtHelpers.DecodeJWT(httpRequestMessage.Headers.Authorization?.Parameter, account, ref authContext);
                return(authContext);
            }
            catch (AuthenticationException authEx)
            {
                if ((authEx.InnerException is TaskCanceledException) && cancellationToken.IsCancellationRequested)
                {
                    // DeviceCodeTimeout
                    throw new Exception(string.Format(
                                            CultureInfo.CurrentCulture,
                                            ErrorConstants.Message.DeviceCodeTimeout,
                                            Constants.MaxDeviceCodeTimeOut));
                }
                else
                {
                    throw authEx.InnerException ?? authEx;
                }
            }
            catch (Exception ex)
            {
                throw ex.InnerException ?? ex;
            }
        }