add claimtypes.email provider to auth sample & article (#10691)
* finished #6925 * augmented per @BrennanConroy * fixed css link * added method to hub * added code from sample to file * fixed user sample * removed the email version of this sample * removed last mention of the customization * Minor edits * added (and tested) claimtypes.email-supporting identity approach * referencing code in sample instead of hard-typed * fixed a dumb thing * implemented all changes suggested by @tdykstra * fixed suggestions from @scottaddie * updated metadata * Update ms.date * tweaks implemented per @BrennanConroy * Update headingpull/10751/head
parent
f3b641a099
commit
e3c3b8d125
|
@ -3,9 +3,9 @@ title: Authentication and authorization in ASP.NET Core SignalR
|
|||
author: bradygaster
|
||||
description: Learn how to use authentication and authorization in ASP.NET Core SignalR.
|
||||
monikerRange: '>= aspnetcore-2.1'
|
||||
ms.author: anurse
|
||||
ms.author: bradyg
|
||||
ms.custom: mvc
|
||||
ms.date: 06/29/2018
|
||||
ms.date: 01/31/2019
|
||||
uid: signalr/authn-and-authz
|
||||
---
|
||||
|
||||
|
@ -63,22 +63,14 @@ If [Windows authentication](xref:security/authentication/windowsauth) is configu
|
|||
|
||||
Add a new class that implements `IUserIdProvider` and retrieve one of the claims from the user to use as the identifier. For example, to use the "Name" claim (which is the Windows username in the form `[Domain]\[Username]`), create the following class:
|
||||
|
||||
```csharp
|
||||
public class NameUserIdProvider : IUserIdProvider
|
||||
{
|
||||
public string GetUserId(HubConnectionContext connection)
|
||||
{
|
||||
return connection.User?.FindFirst(ClaimTypes.Name)?.Value;
|
||||
}
|
||||
}
|
||||
```
|
||||
[!code-csharp[Name based provider](authn-and-authz/sample/nameuseridprovider.cs?name=NameUserIdProvider)]
|
||||
|
||||
Rather than `ClaimTypes.Name`, you can use any value from the `User` (such as the Windows SID identifier, etc.).
|
||||
|
||||
> [!NOTE]
|
||||
> The value you choose must be unique among all the users in your system. Otherwise, a message intended for one user could end up going to a different user.
|
||||
|
||||
Register this component in your `Startup.ConfigureServices` method **after** the call to `.AddSignalR`
|
||||
Register this component in your `Startup.ConfigureServices` method.
|
||||
|
||||
```csharp
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
|
@ -103,6 +95,27 @@ var connection = new HubConnectionBuilder()
|
|||
|
||||
Windows Authentication is only supported by the browser client when using Microsoft Internet Explorer or Microsoft Edge.
|
||||
|
||||
### Use claims to customize identity handling
|
||||
|
||||
An app that authenticates users can derive SignalR user IDs from user claims. To specify how SignalR creates user IDs, implement `IUserIdProvider` and register the implementation.
|
||||
|
||||
The sample code demonstrates how you would use claims to select the user's email address as the identifying property.
|
||||
|
||||
> [!NOTE]
|
||||
> The value you choose must be unique among all the users in your system. Otherwise, a message intended for one user could end up going to a different user.
|
||||
|
||||
[!code-csharp[Email provider](authn-and-authz/sample/EmailBasedUserIdProvider.cs?name=EmailBasedUserIdProvider)]
|
||||
|
||||
The account registration adds a claim with type `ClaimsTypes.Email` to the ASP.NET identity database.
|
||||
|
||||
[!code-csharp[Adding the email to the ASP.NET identity claims](authn-and-authz/sample/pages/account/Register.cshtml.cs?name=AddEmailClaim)]
|
||||
|
||||
Register this component in your `Startup.ConfigureServices`.
|
||||
|
||||
```csharp
|
||||
services.AddSingleton<IUserIdProvider, EmailBasedUserIdProvider>();
|
||||
```
|
||||
|
||||
## Authorize users to access hubs and hub methods
|
||||
|
||||
By default, all methods in a hub can be called by an unauthenticated user. In order to require authentication, apply the [Authorize](/dotnet/api/microsoft.aspnetcore.authorization.authorizeattribute) attribute to the hub:
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace SignalRAuthenticationSample
|
||||
{
|
||||
#region EmailBasedUserIdProvider
|
||||
public class EmailBasedUserIdProvider : IUserIdProvider
|
||||
{
|
||||
public virtual string GetUserId(HubConnectionContext connection)
|
||||
{
|
||||
return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
|
@ -2,6 +2,7 @@ using Microsoft.AspNetCore.SignalR;
|
|||
|
||||
namespace SignalRAuthenticationSample
|
||||
{
|
||||
#region NameUserIdProvider
|
||||
public class NameUserIdProvider : IUserIdProvider
|
||||
{
|
||||
public string GetUserId(HubConnectionContext connection)
|
||||
|
@ -9,4 +10,5 @@ namespace SignalRAuthenticationSample
|
|||
return connection.User?.Identity?.Name;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SignalRAuthenticationSample.Data;
|
||||
using SignalRAuthenticationSample.Services;
|
||||
|
||||
namespace SignalRAuthenticationSample.Pages.Account
|
||||
{
|
||||
|
@ -14,18 +14,15 @@ namespace SignalRAuthenticationSample.Pages.Account
|
|||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILogger<RegisterModel> _logger;
|
||||
private readonly IEmailSender _emailSender;
|
||||
|
||||
public RegisterModel(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
ILogger<RegisterModel> logger,
|
||||
IEmailSender emailSender)
|
||||
ILogger<RegisterModel> logger)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_signInManager = signInManager;
|
||||
_logger = logger;
|
||||
_emailSender = emailSender;
|
||||
}
|
||||
|
||||
[BindProperty]
|
||||
|
@ -62,8 +59,14 @@ namespace SignalRAuthenticationSample.Pages.Account
|
|||
ReturnUrl = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
#region AddEmailClaim
|
||||
// create a new user
|
||||
var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email };
|
||||
var result = await _userManager.CreateAsync(user, Input.Password);
|
||||
|
||||
// add the email claim and value for this user
|
||||
await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, Input.Email));
|
||||
#endregion
|
||||
if (result.Succeeded)
|
||||
{
|
||||
_logger.LogInformation("User created a new account with password.");
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
|
||||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
|
||||
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
|
||||
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
|
||||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
||||
</environment>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -97,6 +97,12 @@ namespace SignalRAuthenticationSample
|
|||
// If the Name claim isn't unique, users could receive messages
|
||||
// intended for a different user!
|
||||
services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
|
||||
|
||||
// Change to use email as the user identifier for SignalR
|
||||
// services.AddSingleton<IUserIdProvider, EmailBasedUserIdProvider>();
|
||||
|
||||
// WARNING: use *either* the NameUserIdProvider *or* the
|
||||
// EmailBasedUserIdProvider, but do not use both.
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
body {
|
||||
padding-top: 50px;
|
||||
padding-top: 80px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue