public void SharePointServiceHandlerNonsuccess(string resourceUri, GraphRequestContext context, string rawResponseContent) { if (IsEnabled(EventLevel.Informational, EventKeywords.All)) { SharePointServiceHandlerNonsuccess(resourceUri, context.ClientRequestId, rawResponseContent); } }
public void SharePointServiceHandlerPostprocess(string resourceUri, GraphRequestContext context, HttpStatusCode statusCode) { if (IsEnabled(EventLevel.Informational, EventKeywords.All)) { SharePointServiceHandlerPostprocess(resourceUri, context.ClientRequestId, $"{statusCode} ({(int)statusCode}"); } }
public void SharePointServiceHandlerPreprocess(string resourceUri, GraphRequestContext context) { if (IsEnabled(EventLevel.Informational, EventKeywords.All)) { SharePointServiceHandlerPreprocess(resourceUri, context.ClientRequestId); } }
/// <summary> /// Adds an authentication header to the incoming request by checking the application's <see cref="TokenCache"/> /// for an unexpired access token. If a token is not found or expired, it gets a new one. /// </summary> /// <param name="httpRequestMessage">A <see cref="HttpRequestMessage"/> to authenticate.</param> public async Task AuthenticateRequestAsync(HttpRequestMessage httpRequestMessage) { GraphRequestContext requestContext = httpRequestMessage.GetRequestContext(); MsalAuthenticationProviderOption msalAuthProviderOption = httpRequestMessage.GetMsalAuthProviderOption(); AuthenticationResult authenticationResult = await GetAccessTokenSilentAsync(msalAuthProviderOption); if (authenticationResult == null) { authenticationResult = await GetNewAccessTokenAsync(msalAuthProviderOption); } if (!string.IsNullOrEmpty(authenticationResult.AccessToken)) { httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(CoreConstants.Headers.Bearer, authenticationResult.AccessToken); } }
private void AddGraphRequestContextToRequest(HttpRequestMessage httpRequestMessage) { var requestContext = new GraphRequestContext { MiddlewareOptions = new Dictionary <string, IMiddlewareOption>() { { typeof(AuthenticationHandlerOption).ToString(), new AuthenticationHandlerOption { AuthenticationProvider = authProvider.Object } } }, ClientRequestId = "client-request-id" }; httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), requestContext); }
internal void LogServiceRequest(string resourceUri, GraphRequestContext context, HttpMethod requestMethod, HttpStatusCode statusCode, string rawResponseContent) { Dictionary <string, string> properties = new Dictionary <string, string>(10) { { CommunityGraphConstants.Headers.CommunityLibraryVersionHeaderName, CommunityGraphConstants.Library.AssemblyVersion }, { CommunityGraphConstants.TelemetryProperties.ResourceUri, resourceUri }, { CommunityGraphConstants.TelemetryProperties.RequestMethod, requestMethod.ToString() }, { CommunityGraphConstants.TelemetryProperties.ClientRequestId, context.ClientRequestId }, { CommunityGraphConstants.TelemetryProperties.ResponseStatus, $"{statusCode} ({(int)statusCode})" } }; if (!string.IsNullOrEmpty(rawResponseContent)) { properties.Add(CommunityGraphConstants.TelemetryProperties.RawErrorResponse, rawResponseContent); } TelemetryClient.TrackEvent("GraphCommunityRequest", properties); TelemetryClient.Flush(); }
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!"); }
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!"); }
/// <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; } }
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; } // Save auth config to session state. SessionState.PSVariable.Set(Constants.GraphAuthConfigId, authConfig); try { // Gets a static instance of IAuthenticationProvider when the client app hasn't changed. IAuthenticationProvider authProvider = AuthenticationHelpers.GetAuthProvider(authConfig); // 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 } } } }; HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me"); httpRequestMessage.Properties.Add(typeof(GraphRequestContext).ToString(), graphRequestContext); // Trigger consent. authProvider.AuthenticateRequestAsync(httpRequestMessage).GetAwaiter().GetResult(); } 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!"); // WriteObject(File.ReadAllText(".\\Art\\WelcomeText.txt")); // WriteObject(File.ReadAllText(".\\Art\\GRaphText.txt")); }
/// <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; } }