Skip to content

Commit 000c51d

Browse files
authored
Merge pull request #246621 from MicrosoftDocs/main
7/28/2023 AM Publish
2 parents e7c32c3 + 8411261 commit 000c51d

File tree

128 files changed

+1791
-1033
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1791
-1033
lines changed

.openpublishing.redirection.active-directory.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,26 @@
16001600
"redirect_url": "/azure/active-directory/external-identities/customers/web-app-quickstart-portal-node-js-ciam",
16011601
"redirect_document_id": true
16021602
},
1603+
{
1604+
"source_path_from_root": "/articles/active-directory/external-identities/customers/how-to-web-app-node-sign-in-overview.md",
1605+
"redirect_url": "/azure/active-directory/external-identities/customers/tutorial-web-app-node-sign-in-prepare-tenant",
1606+
"redirect_document_id": true
1607+
},
1608+
{
1609+
"source_path_from_root": "/articles/active-directory/external-identities/customers/how-to-web-app-node-sign-in-prepare-tenant.md",
1610+
"redirect_url": "/azure/active-directory/external-identities/customers/tutorial-web-app-node-sign-in-prepare-tenant",
1611+
"redirect_document_id": false
1612+
},
1613+
{
1614+
"source_path_from_root": "/articles/active-directory/external-identities/customers/how-to-web-app-node-sign-in-prepare-app.md",
1615+
"redirect_url": "/azure/active-directory/external-identities/customers/tutorial-web-app-node-sign-in-prepare-tenant",
1616+
"redirect_document_id": false
1617+
},
1618+
{
1619+
"source_path_from_root": "/articles/active-directory/external-identities/customers/how-to-web-app-node-sign-in-sign-in-out.md",
1620+
"redirect_url": "/azure/active-directory/external-identities/customers/tutorial-web-app-node-sign-in-prepare-tenant",
1621+
"redirect_document_id": false
1622+
},
16031623
{
16041624
"source_path_from_root": "/articles/active-directory/external-identities/customers/how-to-daemon-node-call-api-overview.md",
16051625
"redirect_url": "/azure/active-directory/external-identities/customers/tutorial-daemon-node-call-api-prepare-tenant",

articles/active-directory/develop/tutorial-blazor-server.md

Lines changed: 35 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ In this tutorial:
2222

2323
> [!div class="checklist"]
2424
>
25-
> - Create a new Blazor Server app configured to use Azure AD for authentication
25+
> - Create a new Blazor Server app configured to use Azure AD for authentication for users in a single organization (in the Azure Active Directory tenant the app is registered)
2626
> - Handle both authentication and authorization using `Microsoft.Identity.Web`
2727
> - Retrieve data from a protected web API, Microsoft Graph
2828
@@ -34,169 +34,64 @@ In this tutorial:
3434
- [Application administrator](../roles/permissions-reference.md#application-administrator)
3535
- [Application developer](../roles/permissions-reference.md#application-developer)
3636
- [Cloud application administrator](../roles/permissions-reference.md#cloud-application-administrator)
37-
38-
## Register the app in the Azure portal
39-
40-
Every app that uses Azure AD for authentication must be registered with Azure AD. Follow the instructions in [Register an application](quickstart-register-app.md) with these additions:
41-
42-
- For **Supported account types**, select **Accounts in this organizational directory only**.
43-
- Leave the **Redirect URI** drop down set to **Web** and enter `https://localhost:5001/signin-oidc`. The default port for an app running on Kestrel is `5001`. If the app is available on a different port, specify that port number instead of `5001`.
44-
45-
Under **Manage**, select **Authentication** > **Implicit grant and hybrid flows**. Select **ID tokens**, and then select **Save**.
46-
47-
Finally, because the app calls a protected API (in this case Microsoft Graph), it needs a client secret in order to verify its identity when it requests an access token to call that API.
48-
49-
1. Within the same app registration, under **Manage**, select **Certificates & secrets** and then **Client secrets**.
50-
2. Create a **New client secret** that never expires.
51-
3. Make note of the secret's **Value** as you'll use it in the next step. You can’t access it again once you navigate away from this pane. However, you can recreate it as needed.
37+
- The tenant-id or domain of the Azure Active Directory associated with your Azure Account
5238

5339
## Create the app using the .NET CLI
5440

55-
To create the application, run the following command. Replace the placeholders in the command with the proper information from your app's overview page and execute the command in a command shell. The output location specified with the `-o|--output` option creates a project folder if it doesn't exist and becomes part of the app's name.
56-
5741
```dotnetcli
58-
dotnet new blazorserver --auth SingleOrg --calls-graph -o {APP NAME} --client-id "{CLIENT ID}" --tenant-id "{TENANT ID}" --domain "{DOMAIN}" -f net7.0
42+
mkdir <new-project-folder>
43+
cd <new-project-folder>
44+
dotnet new blazorserver --auth SingleOrg --calls-graph
5945
```
6046

61-
| Placeholder | Azure portal name | Example |
62-
| ------------- | ----------------------- | -------------------------------------- |
63-
| `{APP NAME}` | &mdash; | `BlazorSample` |
64-
| `{CLIENT ID}` | Application (client) ID | `41451fa7-0000-0000-0000-69eff5a761fd` |
65-
| `{TENANT ID}` | Directory (tenant) ID | `e86c78e2-0000-0000-0000-918e0565a45e` |
66-
| `{DOMAIN}` | Primary domain | `tenantname.onmicrosoft.com` |
67-
68-
Now, navigate to your new Blazor app in your editor and add the client secret to the _appsettings.json_ file, replacing the text "secret-from-app-registration".
47+
## Install the Microsoft Identity App Sync .NET Tool
6948

70-
```json
71-
"ClientSecret": "secret-from-app-registration",
49+
```dotnetcli
50+
dotnet tool install --global msidentity-app-sync
7251
```
7352

74-
## Test the app
53+
This tool will automate the following tasks for you:
7554

76-
In your terminal, run the following command:
55+
- Register your application in Azure Active Directory
56+
- Create a secret for your registered application
57+
- Register redirect URIs based on your launchsettings.json
58+
- Initialize the use of user secrets in your project
59+
- Store your application secret in user secrets storage
60+
- Update your appsettings.json with the client-id, tenant-id, and others.
7761

78-
```dotnetcli
79-
dotnet run
80-
```
62+
.NET Tools extend the capabilities of the dotnet CLI command. To learn more about .NET Tools, see [.NET Tools](/dotnet/core/tools/global-tools).
8163

82-
In your browser, navigate to `https://localhost:<port number> `, and log in using an Azure AD user account to see the app running.
64+
For more information on user secrets storage, see [safe storage of app secrets during development](/aspnet/core/security/app-secrets).
8365

84-
## Retrieving data from Microsoft Graph
66+
## Use the Microsoft Identity App Sync Tool
8567

86-
[Microsoft Graph](/graph/overview) offers a range of APIs that provide access to your users' Microsoft 365 data. By using the Microsoft identity platform as the identity provider for your app, you have easier access to this information since Microsoft Graph directly supports the tokens issued by the Microsoft identity platform. In this section, you add code to display the signed in user's emails on the application's "fetch data" page.
68+
Run the following command to register your app in your tenant and update the .NET configuration of your application. Provide the username/upn belonging to your Azure Account (for instance, `[email protected]`) and the tenant ID or domain name of the Azure Active Directory associated with your Azure Account. If you use an account that is signed in in either Visual Studio, Azure CLI, or Azure PowerShell, you'll benefit from single sign-on (SSO).
8769

88-
Before you start, log out of your app since you'll be making changes to the required permissions, and your current token won't work. If you haven't already, run your app again and select **Log out** before updating the code below.
70+
```dotnetcli
71+
msidentity-app-sync --username <username/upn> --tenant-id <tenantID>
72+
```
8973

90-
Now you'll update your app's registration and code to pull a user's email and display the messages within the app. To achieve this, first extend the app registration permissions in Azure AD to enable access to the email data. Then, add code to the Blazor app to retrieve and display this data in one of the pages.
74+
> [!Note]
75+
> - You don't need to provide the username if you are signed in with only one account in the developer tools.
76+
> - You don't need to provide the tenant-id if the tenant in which you want to create the application is your home tenant.
9177
92-
1. In the Azure portal, select your app in **App registrations**.
93-
1. Under **Manage**, select **API permissions**.
94-
1. Select **Add a permission** > **Microsoft Graph**.
95-
1. Select **Delegated Permissions**, then search for and select the **Mail.Read** permission.
96-
1. Select **Add permissions**.
78+
## Optional - Create a development SSL certificate
9779

98-
In the _appsettings.json_ file, update your code so it fetches the appropriate token with the right permissions. Add `mail.read` after the `user.read` scope under `DownstreamAPI`. This is specifying which scopes (or permissions) the app will request access to.
80+
In order to avoid SSL errors/warnings when browsing the running application, you can use the following on macOS and Windows to generate a self-signed SSL certificate for use by .NET Core.
9981

100-
```json
101-
"Scopes": "user.read mail.read"
82+
```dotnetcli
83+
dotnet dev-certs https --trust
10284
```
10385

104-
Next, in the _Pages_ folder, update the code in the _FetchData.razor_ file to retrieve email data instead of the default (random) weather details. Replace the code in that file with the following code snippet:
105-
106-
```csharp
107-
@page "/fetchdata"
108-
109-
@inject IHttpClientFactory HttpClientFactory
110-
@inject Microsoft.Identity.Web.ITokenAcquisition TokenAcquisitionService
111-
112-
<p>This component demonstrates fetching data from a service.</p>
113-
114-
@if (messages == null)
115-
{
116-
<p><em>Loading...</em></p>
117-
}
118-
else
119-
{
120-
<h1>Hello @userDisplayName !!!!</h1>
121-
<table class="table">
122-
<thead>
123-
<tr>
124-
<th>Subject</th>
125-
<th>Sender</th>
126-
<th>Received Time</th>
127-
</tr>
128-
</thead>
129-
<tbody>
130-
@foreach (var mail in messages)
131-
{
132-
<tr>
133-
<td>@mail.Subject</td>
134-
<td>@mail.Sender</td>
135-
<td>@mail.ReceivedTime</td>
136-
</tr>
137-
}
138-
</tbody>
139-
</table>
140-
}
141-
142-
@code {
143-
144-
private string userDisplayName;
145-
private List<MailMessage> messages = new List<MailMessage>();
146-
147-
private HttpClient _httpClient;
148-
149-
protected override async Task OnInitializedAsync()
150-
{
151-
_httpClient = HttpClientFactory.CreateClient();
152-
153-
154-
// get a token
155-
var token = await TokenAcquisitionService.GetAccessTokenForUserAsync(new string[] { "User.Read", "Mail.Read" });
156-
157-
// make API call
158-
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
159-
var dataRequest = await _httpClient.GetAsync("https://graph.microsoft.com/beta/me");
160-
161-
if (dataRequest.IsSuccessStatusCode)
162-
{
163-
var userData = System.Text.Json.JsonDocument.Parse(await dataRequest.Content.ReadAsStreamAsync());
164-
userDisplayName = userData.RootElement.GetProperty("displayName").GetString();
165-
}
166-
167-
var mailRequest = await _httpClient.GetAsync("https://graph.microsoft.com/beta/me/messages?$select=subject,receivedDateTime,sender&$top=10");
168-
169-
if (mailRequest.IsSuccessStatusCode)
170-
{
171-
var mailData = System.Text.Json.JsonDocument.Parse(await mailRequest.Content.ReadAsStreamAsync());
172-
var messagesArray = mailData.RootElement.GetProperty("value").EnumerateArray();
173-
174-
foreach (var m in messagesArray)
175-
{
176-
var message = new MailMessage();
177-
message.Subject = m.GetProperty("subject").GetString();
178-
message.Sender = m.GetProperty("sender").GetProperty("emailAddress").GetProperty("address").GetString();
179-
message.ReceivedTime = m.GetProperty("receivedDateTime").GetDateTime();
180-
messages.Add(message);
181-
}
182-
}
183-
}
184-
185-
public class MailMessage
186-
{
187-
public string Subject;
188-
public string Sender;
189-
public DateTime ReceivedTime;
190-
}
191-
}
86+
## Run the app
19287

193-
```
194-
195-
Launch the app. You’ll notice that you're prompted for the newly added permissions, indicating that everything is working as expected. Now, beyond basic user profile data, the app is requesting access to email data.
88+
In your terminal, run the following command:
19689

197-
After granting consent, navigate to the "Fetch data" page to read some email.
90+
```dotnetcli
91+
dotnet run
92+
```
19893

199-
:::image type="content" source="./media/tutorial-blazor-server/final-app-2.png" alt-text="Screenshot of the final app. It has a heading that says Hello Nicholas and it shows a list of emails belonging to Nicholas.":::
94+
Browse to the running web application using the URL outputted by the command line.
20095

20196
## Next steps
20297

0 commit comments

Comments
 (0)