diff --git a/docs/graph/assets/loginbutton.png b/docs/graph/assets/loginbutton.png new file mode 100644 index 00000000..87677072 Binary files /dev/null and b/docs/graph/assets/loginbutton.png differ diff --git a/docs/graph/assets/peoplepicker.png b/docs/graph/assets/peoplepicker.png new file mode 100644 index 00000000..90574a39 Binary files /dev/null and b/docs/graph/assets/peoplepicker.png differ diff --git a/docs/graph/assets/personview.png b/docs/graph/assets/personview.png new file mode 100644 index 00000000..5b16c76c Binary files /dev/null and b/docs/graph/assets/personview.png differ diff --git a/docs/graph/authentication/custom.md b/docs/graph/authentication/custom.md new file mode 100644 index 00000000..6615c4e3 --- /dev/null +++ b/docs/graph/authentication/custom.md @@ -0,0 +1,50 @@ +--- +title: Custom authentication providers +author: shweaver-MSFT +description: IProvider interface defines the basic functions of an authentication provider in the Graph toolkit. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity +dev_langs: + - csharp +--- + +# Custom authentication providers + +If you have existing authentication code in your application, you can create a custom provider to enable authentication and access to Microsoft Graph for the toolkit's Graph based controls and helpers. To bring your own authentication provider logic, start by extending `IProvider`. + +## IProvider + +`IProvider` is the base interface for creating authentication providers that work with the various controls and helpers in the toolkit. Handle authentication with one of our premade `IProvider` implementations or create your own. + +Available in the `CommunityToolkit.Authentication` package. + +```csharp +using CommunityToolkit.Authentication; + +// Create an instance of your custom IProvider implementation. +IProvider customProvider = new CustomProvider(); + +// Set the global provider using the custom instance. +ProviderManager.Instance.GlobalProvider = customProvider; +``` + +### Properties + +| Property | Type | Description | +| -- | -- | -- | +| State | ProviderState | Gets the current authentication state of the provider. | + +### Events + +| Event | Type | Description | +| -- | -- | -- | +| StateChanged | EventHandler<ProviderStateChangedEventArgs> | An event that is called whenever the login state changes. + +### Methods + +| Method | Arguments | Returns | Description | +| -- | -- | -- | -- | +| AuthenticateRequestAsync | HttpRequestMessage | Task | Authenticate an outgoing request. | +| GetTokenAsync | bool silentOnly = false | Task<string> | Retrieve a token for the authenticated user. | +| SignInAsync | | Task | Sign in a user. | +| SignOutAsync | | Task | Sign out the current user. | +| TrySilentSignInAsync | | Task<bool> | Try signing in silently, without prompts. | \ No newline at end of file diff --git a/docs/graph/authentication/msal.md b/docs/graph/authentication/msal.md new file mode 100644 index 00000000..d8056c92 --- /dev/null +++ b/docs/graph/authentication/msal.md @@ -0,0 +1,61 @@ +--- +title: MsalProvider +author: shweaver-MSFT +description: Authentication provider based on the official Microsoft Authentication Library (MSAL). +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity, msal +dev_langs: + - csharp +--- + +# MsalProvider + +The MsalProvider is an [IProvider](./custom.md) implementation built on the official Microsoft Authentication Library (MSAL). It is NetStandard 2.0 so it works in both UWP and WPF apps. + +Available in the `CommunityToolkit.Authentication.Msal` package. + +```csharp +using CommunityToolkit.Authentication; + +string clientId = "YOUR-CLIENT-ID-HERE"; +string[] scopes = new string[] { "User.Read" }; + +ProviderManager.Instance.GlobalProvider = new MsalProvider(clientId, scopes); +``` + +## Prerequisite Configure Client Id in Partner Center + +> [!IMPORTANT] +> To obtain a Client Id, first register your app in Azure following the guidance here: [Quickstart: Register an application with the Microsoft identity platform](/azure/active-directory/develop/quickstart-register-app) +> +> After finishing the initial registration, you will also need to add an additional redirect URI. Click on "Authentication -> Add a Platform", select "Mobile and desktop applications", and check the "https://login.microsoftonline.com/common/oauth2/nativeclient" checkbox on that page. Then click "Configure". + +## Constructor + +| Parameter | Type | Default | Description | +| -- | -- | -- | -- | +| clientId | string | | Registered client id. | +| scopes | string[] | null | Listof scopes to initially request. | +| redirectUri | string | `https://login.microsoftonline.com/common/oauth2/nativeclient` | Redirect URI for authentication response. | +| autoSignIn | bool | true | Determines whether the provider attempts to silently log in upon instantiation. | + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| State | ProviderState | Gets the current authentication state of the provider. | + +## Events + +| Event | Type | Description | +| -- | -- | -- | +| StateChanged | EventHandler<ProviderStateChangedEventArgs> | Event called when the provider state changes. | + +## Methods + +| Method | Arguments | Returns | Description | +| -- | -- | -- | -- | +| GetTokenAsync | bool silentOnly = false, string[] scopes = null | Task<string> | Retrieve a token for the authenticated user. | +| AuthenticateRequestAsync | HttpRequestMessage | Task | Authenticate an outgoing request. | +| SignInAsync | | Task | Sign in a user. | +| SignOutAsync | | Task | Sign out the current user. | +| TrySilentSignInAsync | | Task<bool> | Try signing in silently, without prompts. | \ No newline at end of file diff --git a/docs/graph/authentication/overview.md b/docs/graph/authentication/overview.md new file mode 100644 index 00000000..422c6dc9 --- /dev/null +++ b/docs/graph/authentication/overview.md @@ -0,0 +1,171 @@ +--- +title: Authentication Providers Overview +author: shweaver-MSFT +description: Authentication providers that enable easy access to Microsoft Graph APIs. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity, msa, wam +dev_langs: + - csharp +--- + +# Authentication Providers Overview + +Authentication is always the first step to working with Microsoft Graph. The toolkit providers enable your application to authenticate with Microsoft Identity and access Microsoft Graph in only few lines of code. Each provider handles user authentication and acquiring access tokens to call Microsoft Graph APIs, so that you don't have to write this code yourself. + +You can use the providers on their own, without components, to quickly implement authentication for your app and make calls to Microsoft Graph via the Microsoft Graph .NET SDK. + +The providers are required when using the Microsoft Graph Toolkit helpers and controls so they can access Microsoft Graph APIs. If you already have your own authentication and want to use the helpers and controls, you can use a [custom provider](./custom.md) instead. + +The toolkit includes the following providers: + +| Providers | Description | +| -- | -- | +| [Msal](./msal.md) | Uses MSAL for .NET to sign in users and acquire tokens to use with Microsoft Graph in NetStandard 2.0 applications. | +| [Windows](./windows.md) | Uses native WebAccountManager (WAM) APIs to sign in users and acquire tokens to use with Microsoft Graph in UWP applications. | +| [Custom](./custom.md) | Create a custom provider to enable authentication and access to Microsoft Graph with your application's existing authentication code. | + +## Initializing the GlobalProvider + +To use an authentication provider in your app, you need to set it as the global provider. The [ProviderManager](./providermanager.md) is the singleton that stores the globally accessible [IProvider](./custom.md) implementation and signals events in response to authentication state changes. +Set the `GlobalProvider` property at app startup and any other Graph based code will respond to any changes as users sign in and out. + +```csharp +using CommunityToolkit.Authentication; + +// Set the GlobalProvider to an IProvider implementation. +ProviderManager.Instance.GlobalProvider = new WindowsProvider(); +``` + +### Permission scopes + +We recommend adding all the permission scopes your application may need when initializing your provider. This is optional, but will improve your user experience by presenting a single consent screen to the user with an aggregated list of permissions requested by all components in your app, rather than presenting separate prompts per scope as requested by the helpers and controls. The following example shows how to do this with the WindowsProvider. + +```csharp + +using CommunityToolkit.Authentication; + +string[] scopes = new string[] { "User.Read", "People.Read" }; + +ProviderManager.Instance.GlobalProvider = new WindowsProvider(scopes); +``` + +### ProviderState + +The providers keeps track of the user's authentication state and communicate it outwards. For example, when a user successfully signs in, the `ProviderState` is updated to `SignedIn`, signaling to the application that it is now able to make calls to Microsoft Graph. + +```csharp +public enum ProviderState +{ + // The user's status is not known. + Loading, + + // The user is signed-out. + SignedOut, + + // The user is signed-in. + SignedIn, +} +``` + +## Respond to changes in the GlobalProvider state + +In some scenarios, you will want to show certain functionality or perform an action only after a user has successfully signed in. You can access and check the provider state as shown in the following example: + +```csharp +using CommunityToolkit.Authentication; + +if (ProviderManager.Instance.GlobalProvider?.State === ProviderState.SignedIn) { + // your code here +} +``` + +Use the `ProviderUpdated` and `ProviderStateChanged` events to get notified whenever provider is set or changes state. + +```csharp +using CommunityToolkit.Authentication; + +ProviderManager.Instance.ProviderUpdated += OnProviderUpdated; +ProviderManager.Instance.ProviderStateChanged += OnProviderStateChanged; + +void OnProviderUpdated(object sender, IProvider provider) +{ + // The global provider has been set. +} + +void OnProviderStateChanged(object sender, ProviderUpdatedEventArgs args) +{ + // The state of the global provider has changed. +} +``` + +### ProviderStateTrigger + +To respond to provider state changes from XAML, try out the `ProviderStateTrigger` state trigger. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +```xml + + + + + + + + + + + + + + + + +``` + +### FrameworkElement.IsVisibleWhen + +The `FrameworkElement.IsVisibleWhen` attached property makes it easy to toggle visibility for any `FrameworkElement`. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +```xml + + + +``` + +## Getting an access token + +Each provider exposes a function called `getTokenAsync` that can retrieve the current access token or retrieve a new access token for the provided scopes. The following example shows how to get a new access token or the currently signed in user: + +```csharp +using CommunityToolkit.Authentication; + +// Assuming a provider has already been initialized +IProvider provider = ProviderManager.Instance.GlobalProvider; + +string token = await provider.GetTokenAsync(silentOnly: false); +``` + +## Call Microsoft Graph APIs + +Once authenticated, you can now make API calls to Microsoft Graph using the Graph SDK or without. See the [Extensions](../helpers/extensions.md) page for an example of how to authenticate an outbound request directly. + +### Use the Graph SDK + +Access APIs using the Graph SDK through a preconfigured `GraphServiceClient` available through an extension method on `IProvider` called `GetClient()` and `GetBetaClient()`. +See [Microsoft Graph Extensions](../helpers/extensions.md) for more details. + +It's possible to authenticate and make all Graph requests manually, without the Graph SDK. This can reduce package size significantly. However, using the Graph SDK is certainly the easiest way to work with Graph in .NET because the `GraphServiceClient` offers a convenient way of building requests and includes all of the object types ready to use. + +Available in the `CommunityToolkit.Graph` package. + +```csharp +using CommunityToolkit.Authentication; +using CommunityToolkit.Graph.Extensions; + +IProvider provider = ProviderManager.Instance.GlobalProvider; +GraphServiceClient graphClient = provider.GetClient(); + +var me = await graphClient.Me.Request().GetAsync(); +``` diff --git a/docs/graph/authentication/providermanager.md b/docs/graph/authentication/providermanager.md new file mode 100644 index 00000000..5f259754 --- /dev/null +++ b/docs/graph/authentication/providermanager.md @@ -0,0 +1,44 @@ +--- +title: ProviderManager +author: shweaver-MSFT +description: ProviderManager manages access to the globally configured IProvider instance and any state change events as users sign in and out. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity +dev_langs: + - csharp +--- + +# ProviderManager + +The ProviderManager manages access to the globally configured [IProvider](./custom.md) instance and any state change events as users sign in and out. + +Available in the `CommunityToolkit.Authentication` package. + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| ClientName | string | (*Static*) Gets the name of the toolkit client to identify self in Graph calls. | +| Instance | ProviderManager | (*Static*) Get or set the instance of the globally configured IProvider. | +| State | ProviderState | Gets the current authentication state of the provider. | + +## Events + +| Event | Type | Description | +| -- | -- | -- | +| ProviderUpdated | EventHandler<IProvider> | Event called when the IProvider changes. | +| ProviderStateChanged | EventHandler<ProviderStateChangedEventArgs> | Event called when the IProvider changes. | + +## ProviderStateChangedEventArgs Object + +| Property | Type | Description | +| -- | -- | -- | +| OldState | ProviderState | Gets the previous state of the IProvider. +| NewState | ProviderState | Gets the new state of the IProvider. + +## ProviderState Enum + +| Name | Description | +| -- | -- | +| Loading | The user's status is not known. | +| SignedOut | The user is signed-out. | +| SignedIn | The user is signed-in. | diff --git a/docs/graph/authentication/windows.md b/docs/graph/authentication/windows.md new file mode 100644 index 00000000..620a634f --- /dev/null +++ b/docs/graph/authentication/windows.md @@ -0,0 +1,155 @@ +--- +title: WindowsProvider +author: shweaver-MSFT +description: Lightweight IProvider implementation that enables authentication using native Windows Account Manager APIs (WAM). +keywords: uwp, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity, wam, msa +dev_langs: + - csharp +--- + +# WindowsProvider + +The WindowsProvider is an authentication provider for accessing locally configured accounts on Windows. +It extends [IProvider](./custom.md) and uses the native Windows AccountManager (WAM) APIs and AccountsSettingsPane for sign in. + +Available in the `CommunityToolkit.Authentication.Uwp` package. + +## Prerequisite Windows Store Association in Visual Studio + +To get valid tokens and complete sign in, the app will need to be associated with the Microsoft Store. This will enable your app to authenticate consumer MSA accounts without any additional configuration. + +1. In Visual Studio Solution Explorer, right-click the UWP project, then select **Store -> Associate App with the Store...** + +2. In the wizard, click **Next**, sign in with your Windows developer account, type a name for your app in **Reserve a new app name**, then click **Reserve**. + +3. After completing the app registration, select the new app name, click **Next**, and then click **Associate**. This adds the required Windows Store registration information to the application manifest. + +> [!NOTE] +> You must have a Windows Developer account to use the WindowsProvider in your UWP app. You can [register a Microsoft developer account](https://developer.microsoft.com/store/register) if you don't already have one. + +## Prerequisite Configure Client Id in Partner Center + +If your product integrates with Azure AD and calls APIs that request either application permissions or delegated permissions that require administrator consent, you will also need to enter your Azure AD Client ID in Partner Center: + +`https://partner.microsoft.com/dashboard/products/<YOUR-APP-ID>/administrator-consent` + +This lets administrators who acquire the app for their organization grant consent for your product to act on behalf of all users in the tenant. + +> [!NOTE] +> You only need to specify the client id if you need admin consent for delegated permissions from your AAD app registration, or need to support more advanced authentication scenarios like SSO. Simple authentication for consumer MSA accounts does not require a client id or any additional configuration in Azure for basic access. + +> [!IMPORTANT] +> Make sure to Register Client Id in Azure first following the guidance here: [Quickstart: Register an application with the Microsoft identity platform](/azure/active-directory/develop/quickstart-register-app) +> +> After finishing the initial registration page, you will also need to add an additional redirect URI. Click on "Add a Redirect URI" and add the value retrieved from running `WindowsProvider.RedirectUri` at runtime. +> +> You'll also want to set the toggle to **true** for "Allow public client flows". +> +> Then click "Save". + +## Syntax + +The WindowsProvider can be used in just one line of code: + +```csharp +using CommunityToolkit.Authentication; + +// Easily create a new WindowsProvider instance and set the GlobalProvider. +// Don't forget to associate your app with the Microsoft Store before attempting sign in. +ProviderManager.Instance.GlobalProvider = new WindowsProvider(new string[] { "User.Read", "Tasks.ReadWrite" }); +``` + +The WindowsProvider can also be configured to disable auto-login or show custom content in the `AccountsSettingsPane`. +Configuration for specifying supported account types (such as AAD) is available via the `WebAccountProviderConfig` object. + +```CSharp +using CommunityToolkit.Authentication; + +// Provider config +string[] scopes = { "User.Read", "People.Read", "Calendars.Read", "Mail.Read" }; + +// Additional parameters are also available, +// such as custom settings commands for the AccountsSettingsPane. +Guid settingsCommandId = Guid.NewGuid(); +void OnSettingsCommandInvoked(IUICommand command) +{ + System.Diagnostics.Debug.WriteLine("AccountsSettingsPane command invoked: " + command.Id); +} + +// Configure which types of accounts should be available to choose from. The default is MSA, but AAD is also supported. +var webAccountProviderConfig = new WebAccountProviderConfig(WebAccountProviderType.Msa); + +// ClientId is only required for approving admin level consent in AAD tenants or for supporting advanced authentication scenarios like SSO. +//var webAccountProviderConfig = new WebAccountProviderConfig(WebAccountProviderType.Aad, "YOUR_CLIENT_ID_HERE"); + +// Configure details to present in the AccountsSettingsPane, such as custom header text and links. +var accountsSettingsPaneConfig = new AccountsSettingsPaneConfig( + headerText: "Custom header text", + commands: new List() + { + new SettingsCommand(settingsCommandId: settingsCommandId, label: "Click me!", handler: OnSettingsCommandInvoked) + }); + +// Determine it the provider should automatically sign in or not. Default is true. +// Set to false to delay silent sign in until SignInAsync or TrySilentSignInAsync is called. +bool autoSignIn = false; + +// Set the GlobalProvider with the extra configuration +ProviderManager.Instance.GlobalProvider = new WindowsProvider(scopes, accountsSettingsPaneConfig, webAccountProviderConfig, autoSignIn); +``` + +## Constructor + +| Parameter | Type | Default | Description | +| -- | -- | -- | -- | +| scopes | string[] | null | List of scopes to initially request. | +| webAccountProviderConfig | WebAccountProviderConfig? | null | Configuration value for determining the available web account providers. | +| accountsSettingsPaneConfig | AccountsSettingsPaneConfig? | null | Configuration values for the AccountsSettingsPane. | +| autoSignIn | bool | true | Determines whether the provider attempts to silently log in upon instantiation. | + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| State | ProviderState | Gets the current authentication state of the provider. | +| Scopes | string[] | List of scopes to pre-authorize on the user during authentication. | +| WebAccountsProviderConfig | WebAccountProviderConfig | configuration values for determining the available web account providers. | +| AccountsSettingsPaneConfig | AccountsSettingsPaneConfig | Configuration values for the AccountsSettingsPane, shown during authentication. | +| RedirectUri | string | Static getter for retrieving a customized redirect uri to put in the Azure app registration. | + +## Events + +| Event | Type | Description | +| -- | -- | -- | +| StateChanged | EventHandler<ProviderStateChangedEventArgs> | Event called when the provider state changes. | + +## Methods + +| Method | Arguments | Returns | Description | +| -- | -- | -- | -- | +| AuthenticateRequestAsync | HttpRequestMessage | Task | Authenticate an outgoing request. | +| GetTokenAsync | bool silentOnly = true, string[] scopes = null | Task<string> | Retrieve a token for the authenticated user. | +| SignInAsync | | Task | Sign in a user. | +| SignOutAsync | | Task | Sign out the current user. | +| TrySilentSignInAsync | | Task<bool> | Try signing in silently, without prompts. | + +## AccountsSettingsPaneConfig Object + +| Property | Type | Description | +| -- | -- | -- | +| HeaderText | string | Gets or sets the header text for the accounts settings pane. | +| Commands | IList<SettingsCommand> | Gets or sets the SettingsCommand collection for the account settings pane. | + +## WebAccountProviderConfig Object + +| Property | Type | Description | +| -- | -- | -- | +| ClientId | string | Client Id obtained from Azure registration. | +| WebAccountProviderType | WebAccountProviderType | The types of accounts providers that should be available to the user. | + +### WebAccountProviderType Enum + +| Name | Description | +| -- | -- | +| All | Enable authentication of all available account types. | +| MSA | Enable authentication of public/consumer MSA accounts. | \ No newline at end of file diff --git a/docs/graph/controls/graphpresenter.md b/docs/graph/controls/graphpresenter.md new file mode 100644 index 00000000..aab0bb88 --- /dev/null +++ b/docs/graph/controls/graphpresenter.md @@ -0,0 +1,93 @@ +--- +title: GraphPresenter XAML Control +author: shweaver +description: The GraphPresenter control enables adhoc visualization of any Graph API. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, presenter, graphpresenter, graph +dev_langs: + - csharp +--- + +# (Experimental) GraphPresenter XAML Control + +The GraphPresenter is a flexible XAML control for visualizing Graph API data. Provide an `IBaseRequestBuilder` implementation and the GraphPresenter will automatically fetch the data from the proper Graph endpoint, ready for visualization. Because every Graph entity is different, this control has no default UI of it's own. It is up to the developer to decide how the data should be presented by setting the control's `ContentTemplate`. This control is great for prototyping and experimentation purposes, but we suggest creating your own user controls for production scenarios. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +## Syntax + +### XAML + +```xml + + + + + + + + + + + + + + + + + +``` + +### Code-behind + +```csharp +public IBaseRequestBuilder RecentDriveItemsRequestBuilder { get; set; } + +public GraphPresenterSamplePage() +{ + InitializeComponent(); + + ProviderManager.Instance.ProviderStateChanged += (s, e) => UpdateRequestBuilder(); + UpdateRequestBuilder(); +} + +private void UpdateRequestBuilder() +{ + var provider = ProviderManager.Instance.GlobalProvider; + switch (provider?.State) + { + case ProviderState.SignedIn: + RecentDriveItemsRequestBuilder = provider.GetClient().Me.Drive.Recent(); + break; + + default: + RecentDriveItemsRequestBuilder = null; + break; + } +} +``` + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| RequestBuilder | IBaseRequestBuilder | Used to make a request to the graph. The results will be automatically populated to the `ContentPresenter.ContentTemplate` property. Use a `ContentPresenter.ContentTemplate` to change the presentation of the data. | +| ResponseType | Type | The type of item returned by the `RequestBuilder`. | +| IsCollection | bool | A value indicating whether the returned data from the `RequestBuilder` is a collection. | +| QueryOptions | List<QueryOption> | A list of `QueryOption` values to pass into the request built by the `RequestBuilder`. | +| OrderBy | string | A string to indicate a sorting order for the `RequestBuilder`. This is a helper to add this specific request option to the `QueryOptions`. + +## Requirements + +* **Namespace:** CommunityToolkit.Graph.Uwp.Controls +* **NuGet package:** [CommunityToolkit.Graph.Uwp](https://www.nuget.org/packages/CommunityToolkit.Graph.Uwp) + +## API + +* [GraphPresenter source code](https://github.com/windows-toolkit/Graph-Controls/tree/main/CommunityToolkit.Graph.Uwp/Controls/GraphPresenter) + +## Related Topics + +* [MGT Get Component](/graph/toolkit/components/get) diff --git a/docs/graph/controls/loginbutton.md b/docs/graph/controls/loginbutton.md new file mode 100644 index 00000000..62eff281 --- /dev/null +++ b/docs/graph/controls/loginbutton.md @@ -0,0 +1,61 @@ +--- +title: LoginButton XAML Control +author: michael-hawker +description: The LoginButton control facilitates Microsoft Identity platform authentication. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, login, loginbutton, graph +dev_langs: + - csharp +--- + +# LoginButton XAML Control + +The LoginButton is both a button and flyout control to facilitate Microsoft identity platform authentication. It provides two states: + +* When the user is not signed in, the control is a simple button to initiate the sign in process. +* When the user is signed in, the control displays the current signed in user name, profile image, and email. When clicked, a flyout is opened with a command to sign out. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +## Syntax + +```xml + + + +``` + +## Sample Output + +![LoginButton Control](../assets/loginbutton.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| UserDetails | User | Gets or sets details about this person retrieved from the graph or provided by the developer. | +| IsLoading | bool | Indicates if the control is loading and hasn't established a sign-in state. | + +## Events + +| Events | Description | +| -- | -- | +| LoginInitiated | The user clicked the sign in button to start the login process. | +| LoginCompleted | The login process was successful and the user is now signed in. | +| LoginFailed | The user canceled the login process or was unable to sign in. | +| LogoutInitiated | The user started to logout. | +| LogoutCompleted | The user signed out. | + +## Requirements + +* **Namespace:** CommunityToolkit.Graph.Uwp.Controls +* **NuGet package:** [CommunityToolkit.Graph.Uwp](https://www.nuget.org/packages/CommunityToolkit.Graph.Uwp) +* **Scope:** `User.Read` + +## API + +* [LoginButton source code](https://github.com/windows-toolkit/Graph-Controls/tree/rel/7.1.0/CommunityToolkit.Graph.Uwp/Controls/LoginButton) + +## Related Topics + +* [User Graph API](/graph/api/resources/user) +* [MGT Login Component](/graph/toolkit/components/login) diff --git a/docs/graph/controls/peoplepicker.md b/docs/graph/controls/peoplepicker.md new file mode 100644 index 00000000..fb3b1b7e --- /dev/null +++ b/docs/graph/controls/peoplepicker.md @@ -0,0 +1,47 @@ +--- +title: PeoplePicker XAML Control +author: michael-hawker +description: The PeoplePicker control searches for people and renders the list of results from Microsoft Graph. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, people, peoplepicker, picker, graph +dev_langs: + - csharp +--- + +# PeoplePicker XAML Control + +The PeoplePicker searches for people and renders the list of results from Microsoft Graph. By default, the component will search across all people. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +## Syntax + +```xml + + + +``` + +## Sample Output + +![PeoplePicker Control](../assets/peoplepicker.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| PickedPeople | ObservableCollection<Person> | Gets the set of Person objects chosen by the user. | +| SuggestedPeople | ObservableCollection<Person> | Gets or sets collection of people suggested by the graph from the user's query. | + +## Requirements + +* **Namespace:** CommunityToolkit.Graph.Uwp.Controls +* **NuGet package:** [CommunityToolkit.Graph.Uwp](https://www.nuget.org/packages/CommunityToolkit.Graph.Uwp) + +## API + +* [PeoplePicker source code](https://github.com/CommunityToolkit/Graph-Controls/tree/rel/7.1.0/CommunityToolkit.Graph.Uwp/Controls/PeoplePicker) + +## Related Topics + +* [Person Graph API](/graph/api/resources/person) +* [MGT PeoplePicker Component](/graph/toolkit/components/people-picker) diff --git a/docs/graph/controls/personview.md b/docs/graph/controls/personview.md new file mode 100644 index 00000000..942bd8ec --- /dev/null +++ b/docs/graph/controls/personview.md @@ -0,0 +1,52 @@ +--- +title: PersonView XAML Control +author: michael-hawker +description: The PersonView control displays a person or contact's photo, name, and/or email address. +keywords: windows 10, uwp, windows community toolkit, uwp community toolkit, uwp toolkit, personview, person, user, contact, graph +dev_langs: + - csharp +--- + +# (Preview) PersonView XAML Control + +The PersonView control is used to display a person or contact by using their photo, name, and/or email address. + +Available in the `CommunityToolkit.Graph.Uwp` package. + +## Syntax + +```xml + + + +``` + +## Sample Output + +![PersonView Control](../assets/personview.png) + +## Properties + +| Property | Type | Description | +| -- | -- | -- | +| Initials | string | Gets the generated initials for the person. | +| IsLargeImage | bool | Value indicating if the image/circle size should be larger. | +| PersonDetails | Person | Details about this person retrieved from the graph or provided by the developer. | +| PersonQuery | string | Automatically retrieve data on the specified query from the graph. Use 'me' to retrieve info about the current user. Otherwise, it's best to use an e-mail address as a query. | +| PersonViewType | PersonViewType | Value indicating what type of details should be displayed: `Avatar`, `OneLine`, `TwoLine` | +| UserId | string | Gets or sets the UserId of the displayed person. | +| UserPhoto | BitmapImage | Gets or sets the displayed photo. | + +## Requirements + +* **Namespace:** CommunityToolkit.Graph.Uwp.Controls +* **NuGet package:** [CommunityToolkit.Graph.Uwp](https://www.nuget.org/packages/CommunityToolkit.Graph.Uwp) + +## API + +* [PersonView source code](https://github.com/windows-toolkit/Graph-Controls/tree/rel/7.1.0/CommunityToolkit.Graph.Uwp/Controls/PersonView) + +## Related Topics + +* [Person Graph API](/graph/api/resources/person) +* [MGT Person Component](/graph/toolkit/components/person) diff --git a/docs/graph/getting-started.md b/docs/graph/getting-started.md new file mode 100644 index 00000000..383692c5 --- /dev/null +++ b/docs/graph/getting-started.md @@ -0,0 +1,92 @@ +--- +title: Getting started with WCT Graph helpers and controls +author: shweaver-MSFT +description: Get started using authentication providers and Graph powered controls and helpers from the Windows Community Toolkit. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity +dev_langs: + - csharp +--- + +# Getting started + +To get started using Graph data in your application, you'll first need to enable authentication. + +## Set the global authentication provider + +### Authenticate with MSAL + +Leverage the official Microsoft Authentication Library (MSAL) to enable authentication in NetStandard 2.0 applications using [MsalProvider](./authentication/msal.md). + +1. Register your app in Azure AAD + + Before requesting data from [Microsoft Graph](https://graph.microsoft.com), you will need to [register your application](/azure/active-directory/develop/quickstart-register-app) to get a **ClientID**. + + > After finishing the initial registration page, you will also need to add an additional redirect URI. Click on "Add a Redirect URI", then "Add a platform", and then on "Mobile and desktop applications". Check the `https://login.microsoftonline.com/common/oauth2/nativeclient` checkbox on that page. Then click "Configure". +1. Install the `CommunityToolkit.Authentication.Msal` package. +1. Set the [ProviderManager](./authentication/providermanager.md).GlobalProvider to a new instance of [MsalProvider](./authentication/msal.md) with clientId and pre-configured scopes: + + ```csharp + using CommunityToolkit.Authentication; + + string clientId = "YOUR-CLIENT-ID-HERE"; + string[] scopes = new string[] { "User.Read" }; + + ProviderManager.Instance.GlobalProvider = new MsalProvider(clientId, scopes); + ``` + +> Note: Use the `Scopes` property to preemptively request permissions from the user of your app for data your app needs to access from Microsoft Graph. + +### Authenticate with WindowsProvider + +Try out the [WindowsProvider](./authentication/windows.md) to enable authentication based on the native Windows Account Manager (WAM) APIs in your UWP apps, without requiring a dependency on MSAL. + +1. Associate your app with the Microsoft Store. The app association will act as our minimal app registration for authenticating consumer MSAs. See [WindowsProvider](./authentication/windows.md) for more details. +1. Install the `CommunityToolkit.Authentication.Uwp` package +1. Set the [ProviderManager](./authentication/providermanager.md).GlobalProvider to a new instance of [WindowsProvider](./authentication/windows.md) with pre-configured scopes: + + ```csharp + using CommunityToolkit.Authentication; + + string[] scopes = new string[] { "User.Read" }; + + ProviderManager.Instance.GlobalProvider = new WindowsProvider(scopes); + ``` + +## Sign in a user + +Call `SignInAsync` to initiate the login process. This will prompt the user to specify an account or provide credentials. + + ```csharp +using CommunityToolkit.Authentication; + +await ProviderManager.Instance.GlobalProvider.SignInAsync(); +``` + +You can also use the [LoginButton](./controls/loginbutton.md) control in UWP XAML apps to support the full sign in/out lifecycle and even display the user's photo and name when signed in. + +```xml + + + +``` + +## Make a Graph call + +Once you are authenticated, you can then make requests to the Graph using the GraphServiceClient instance via [extensions](./helpers/extensions.md). + +> Install the `CommunityToolkit.Graph` package. + +```csharp +using CommunityToolkit.Authentication; +using CommunityToolkit.Graph.Extensions; + +ProviderManager.Instance.ProviderStateChanged += (s, e) +{ + IProvider provider = ProviderManager.Instance.GlobalProvider; + if (provider?.State == ProviderState.SignedIn) + { + var graphClient = provider.GetClient(); + var me = await graphClient.Me.Request().GetAsync(); + } +} +``` diff --git a/docs/graph/helpers/extensions.md b/docs/graph/helpers/extensions.md new file mode 100644 index 00000000..f245f668 --- /dev/null +++ b/docs/graph/helpers/extensions.md @@ -0,0 +1,134 @@ +--- +title: Microsoft Graph Extensions +author: shweaver-MSFT +description: Extension methods that enable Graph API calls using the global authentication provider. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, provider, providers, extensions +dev_langs: + - csharp +--- + +# Microsoft Graph Extensions + +Use toolkit extensions to help you make calls to Graph APIs using the global authentication provider. Available in the `CommunityToolkit.Graph` package, `CommunityToolkit.Graph.Extensions` namespace. + +## Call Microsoft Graph APIs + +Once authenticated, you can make API calls to Microsoft Graph using a preconfigured `GraphServiceClient` instance. Access to the client is enabled through an extension method on [IProvider](../authentication/custom.md) called, `GetClient()`. + +```csharp +using CommunityToolkit.Authentication; +using CommunityToolkit.Graph.Extensions; + +IProvider provider = ProviderManager.Instance.GlobalProvider; + +if (provider?.State == ProviderState.SignedIn) +{ + // Get the Graph client + GraphServiceClient graphClient = provider.GetClient(); + + // Make a request for the current user. + var me = await graphClient.Me.Request().GetAsync(); +} +``` + +## Make Beta API calls + +You can also get access to a beta version of the client by calling `GetBetaClient()`. +It won't return types from the Beta SDK, but it does enable access to some beta-only content like user photos. + +```csharp +using CommunityToolkit.Authentication; +using CommunityToolkit.Graph.Extensions; + +public ImageSource GetMyPhoto() +{ + IProvider provider = ProviderManager.Instance.GlobalProvider; + + if (provider?.State == ProviderState.SignedIn) + { + // Get the beta client + GraphServiceClient betaGraphClient = provider.GetBetaClient(); + + try + { + // Make a request to the beta endpoint for the current user's photo. + var photoStream = await betaGraphClient.Me.Photo.Content.Request().GetAsync(); + + using var ras = photoStream.AsRandomAccessStream(); + var bitmap = new BitmapImage(); + await bitmap.SetSourceAsync(ras); + + return bitmap; + } + catch + { + return null; + } + } +} +``` + +## IProvider extension methods + +The following extension methods are available on `IProvider` via the `CommunityToolkit.Graph.Extensions` namespace. + +| Method | Arguments | Returns | Description | +| -- | -- | -- | -- | +| GetClient | | GraphServiceClient | Retrieve pre-configured GraphServiceClient instance for making authenticated Graph calls, using the v1 endpoint. | +| GetBetaClient | | GraphServiceClient | Retrieve pre-configured GraphServiceClient instance for making authenticated Graph calls, using the beta endpoint. | + +## Handle Graph requests manually + +Access APIs by managing requests to Microsoft Graph yourself. This is helpful for projects with existing systems for managing web requests, or for keeping package sizes minimal by excluding the Graph SDK. + +To make Graph API calls manually, use the `HttpRequestMessage.AuthenticateAsync()` extension method to authenticate any outgoing requests. + +```csharp +using CommunityToolkit.Authentication; +using CommunityToolkit.Authentication.Extensions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +private async Task> GetDefaultTaskListAsync() +{ + return await GetResponseAsync>("https://graph.microsoft.com/v1.0/me/todo/lists/tasks/tasks"); +} + +private async Task GetResponseAsync(string requestUri) +{ + // Build the request + var getRequest = new HttpRequestMessage(HttpMethod.Get, requestUri); + + // Authenticate the request using an extension on HttpRequestMessage. + await getRequest.AuthenticateAsync(); + + var httpClient = new HttpClient(); + using (httpClient) + { + // Send the request + var response = await httpClient.SendAsync(getRequest); + + if (response.IsSuccessStatusCode) + { + // Handle the request response + var jsonResponse = await response.Content.ReadAsStringAsync(); + var jObject = JObject.Parse(jsonResponse); + if (jObject.ContainsKey("value")) + { + var result = JsonConvert.DeserializeObject(jObject["value"].ToString()); + return result; + } + } + } + + return default; +} +``` + +## HttpRequestMessage extension methods + +The extension methods are available on `HttpRequestMessage` via the `CommunityToolkit.Authenticaiton.Extensions` namespace. + +| Method | Arguments | Returns | Description | +| -- | -- | -- | -- | +| AuthenticateAsync | | HttpRequestMessage | Authenticate an http request using the current GlobalProvider instance. | diff --git a/docs/graph/helpers/roaming-settings.md b/docs/graph/helpers/roaming-settings.md new file mode 100644 index 00000000..a5250c85 --- /dev/null +++ b/docs/graph/helpers/roaming-settings.md @@ -0,0 +1,164 @@ +--- +title: Roaming settings +author: shweaver-MSFT +description: Roam user settings across experiences using WCT's Graph powered storage helpers. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, roaming, settings, storage, files +dev_langs: + - csharp +--- + +# Roaming settings + +Store and roam user settings/files across experiences and devices using Microsoft Graph powered storage helpers. These Graph storage helpers implement the `Microsoft.Toolkit.Helpers.IFileStorageHelper` and `Microsoft.Toolkit.Helpers.ISettingsStorageHelper` interfaces and work well in conjunction with the `Microsoft.Toolkit.Uwp.Helpers.ApplicationDataStorageHelper` for migrating local data to roaming storage locations. + +## OneDriveStorageHelper + +The `OneDriveStorageHelper` is a storage helper for handling files and folders in a user's OneDrive AppSpecial folder. This helper is purposed for storing app specific values and does not support freely navigating the user's OneDrive root folder or other app's settings folders. + +Available in the `CommunityToolkit.Uwp.Graph` package. + +```csharp +var filePath = "TestFile.txt"; +var fileContents = "this is a test"; +var fileContents2 = "this is also a test"; +var storageHelper = await OneDriveStorageHelper.CreateForCurrentUserAsync(); + +// Create a file +await storageHelper.CreateFileAsync(filePath, fileContents); + +// Read a file +var readContents = await storageHelper.ReadFileAsync(filePath); +Assert.AreEqual(fileContents, readContents); + +// Update a file +await storageHelper.CreateFileAsync(filePath, fileContents2); +var readContents2 = await storageHelper.ReadFileAsync(filePath); +Assert.AreEqual(fileContents2, readContents2); + +// Delete a file +var itemDeleted = await storageHelper.TryDeleteItemAsync(filePath); +Assert.IsTrue(itemDeleted); +``` + +Sub-folders are also supported: + +```csharp +var folderName = "TestFolder"; +var subfolderName = "TestSubFolder"; +var subfolderPath = $"{folderName}/{subfolderName}"; +var fileName = "TestFile.txt"; +var filePath = $"{folderName}/{fileName}"; +var fileContents = "this is a test"; +var storageHelper = await OneDriveStorageHelper.CreateForCurrentUserAsync(); + +// Test preparation +await storageHelper.TryDeleteItemAsync(folderName); +await storageHelper.CreateFolderAsync(folderName); + +// Create a subfolder +await storageHelper.CreateFolderAsync(subfolderName, folderName); + +// Create a file in a folder +await storageHelper.CreateFileAsync(filePath, fileContents); + +// Read a file from a folder +var readContents = await storageHelper.ReadFileAsync(filePath); +Assert.AreEqual(fileContents, readContents); + +// List folder contents +var folderItems = await storageHelper.ReadFolderAsync(folderName); +var folderItemsList = folderItems.ToList(); +Assert.AreEqual(2, folderItemsList.Count()); +Assert.AreEqual(subfolderName, folderItemsList[0].Name); +Assert.AreEqual(DirectoryItemType.Folder, folderItemsList[0].ItemType); +Assert.AreEqual(fileName, folderItemsList[1].Name); +Assert.AreEqual(DirectoryItemType.File, folderItemsList[1].ItemType); + +// Delete a subfolder +var itemDeleted = await storageHelper.TryDeleteItemAsync(subfolderPath); +Assert.IsTrue(itemDeleted); +``` + +## UserExtensionStorageHelper + +The `UserExtensionStorageHelper` is a storage helper that leverages open extensions on the Graph User entity to store data. Use this helper for storing user specific settings as key-value-pairs. + +Available in the `CommunityToolkit.Uwp.Graph` package. + +```csharp +// Create a new storage helper for the current user. +var storageHelper = await UserExtensionStorageHelper.CreateForCurrentUserAsync("my-storage-extension-id"); + +// Save a value +storageHelper["PreferredTheme"] = "Dark"; + +// Sync with Graph to update the remote. +await storageHelper.Sync(); +``` + +### Syncing with Graph + +The `UserExtensionStorageHelper` uses synchronous methods to interop and does not automatically sync data back to Graph. Use the `Sync()` method to push changes up to Graph and retrieve any new settings. + +Common sync opportunities: + +1. On application startup, when ready to fetch values and hydrate the cache. +1. On application suspend/resume. +1. After changing one or more settings values. + +There is a known limitation with open extensions that does not allow deletion of a specific key. We suggest using a unique value to represent when a key has been deleted. To truly remove keys, the entire extension must be cleared and synced to delete the extension, then rehydrated with values and synced again. + +#### Sample 1. Set a default value + +```csharp +// Create a new storage helper for the current user. +var storageHelper = await UserExtensionStorageHelper.CreateForCurrentUserAsync("my-storage-extension-id"); + +// Individual key deletion is not supported by open extensions. +// As a workaround, save a unique value like "KEY_DELETED" on deleted keys to pseudo remove them. +storageHelper["PreferredTheme"] = "KEY_DELETED"; + +// Check for a preferred theme, if not set the default. +if (!storageHelper.TryRead("PreferredTheme", out string preferredTheme) || preferredTheme == "KEY_DELETED") +{ + // Set the default theme. + preferredTheme = "Light"; + + // Save a value to the storage helper cache. + // Changes must be explicitly synced. + storageHelper["preferredTheme"] = preferredTheme; + + // Sync with Graph push changes back up. + await storageHelper.Sync(); +} +``` + +#### Sample 2. Delete a key + +```csharp +// Create a new storage helper for the current user. +var storageHelper = await UserExtensionStorageHelper.CreateForCurrentUserAsync("my-storage-extension-id"); + +// Sync to hydrate. +await storageHelper.Sync(); + +// Get the cache and remove the target item. +Dictionary cache = storageHelper.Cache.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); +cache.Remove("PreferredTheme"); + +// Call clear to mark the extension ready for deletion/recreation +storageHelper.Clear(); + +// Reapply the cached values +foreach (var setting in cache) +{ + storageHelper[setting.Key] = setting.Value; +} + +// Sync deletion to Graph and preserve other settings values. +await storageHelper.Sync(); +``` + +## Related Topics + +* [Add custom data to users using open extensions](/graph/extensibility-open-users) diff --git a/docs/graph/overview.md b/docs/graph/overview.md new file mode 100644 index 00000000..c6b747e0 --- /dev/null +++ b/docs/graph/overview.md @@ -0,0 +1,48 @@ +--- +title: Windows Community Toolkit - Authentication and Graph +author: shweaver-MSFT +description: Authentication providers and Graph powered helpers that make it easy to work with Microsoft Graph APIs. +keywords: uwp, wpf, netstandard, windows, community, toolkit, graph, login, authentication, provider, providers, identity +dev_langs: + - csharp +--- + +# Windows Community Toolkit - Authentication and Graph + +The authentication and Graph helpers and controls are a part of the [Windows Community Toolkit](https://aka.ms/wct), focused on enabling quick and easy Windows authentication and [Microsoft Graph](https://developer.microsoft.com/en-us/graph/) powered experiences. These controls and helpers make it easy to get users authenticated and start calling Microsoft Graph APIs! + +> Note: This new library replaces the `Microsoft.Toolkit.Uwp.UI.Controls.Graph` package; however, it is not backwards compatible nor does it provide all the same features at this time. + +If you need similar controls for the web, check out the [Microsoft Graph Toolkit](https://aka.ms/mgt). + +## Supported SDKs + +| Package | Min Supported | +|--|--| +| `CommunityToolkit.Authentication` | NetStandard 2.0 | +| `CommunityToolkit.Authentication.Msal` | NetStandard 2.0 | +| `CommunityToolkit.Authentication.Uwp` | UWP Windows 10 17134 | +| `CommunityToolkit.Graph` | NetStandard 2.0 | +| `CommunityToolkit.Graph.Uwp` | UWP Windows 10 17763 | + +## Getting started + +Check out the [Getting Started](./getting-started.md) guide for details on how to get authenticated and start calling Graph APIs. + +## Learn More + +### Authentication providers + +Hook into a lightweight framework for authenticating users and responding to login state changes: [Authentication Providers Overview](./authentication/overview.md) + +### Extensions + +See [Microsoft Graph Extensions](./helpers/extensions.md) to learn how to get access to a preconfigured GraphServiceClient and make adhoc API calls using the Graph SDK. + +### Roaming settings + +Roam settings across experiences with the Graph using [Graph powered storage helpers](./helpers/roaming-settings.md). Store simple settings with open extensions on the Graph User or try the `OneDriveStorageHelper` for roaming files via OneDrive. + +### XAML controls + +Build Graph experiences with XAML controls made for UWP, such as [LoginButton](./controls/loginbutton.md) or [PersonView](./controls/personview.md).