---
lang: ja-jp
breaks: true
---
# ASP.NET Core `SignalR` サンプル `Authentication and authorization in ASP.NET Core SignalR` を動作させる 2021-09-06
> Authentication and authorization in ASP.NET Core SignalR
> https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/signalr/authn-and-authz.md
> AspNetCore.Docs/aspnetcore/signalr/authn-and-authz/sample/
> https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/signalr/authn-and-authz/sample
## 起動時にエラーが発生する場合は、ターゲットフレームワークのバージョンを `net5.0` に上げる
### *.csproj
元々のターゲットフレームワーク
```xml=
<TargetFramework>netcoreapp2.1</TargetFramework>
```
`net5.0`に変更する。
```xml=
<TargetFramework>net5.0</TargetFramework>
```
ちなみに、`net6.0`に上げるには以下を設定するが、`Index.cshtml` が有るのに無いといってエラーになるので、追加で変更が必要。
```xml=
<TargetFramework>net6.0</TargetFramework>
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
```
https://hackmd.io/XwCqr6UPRPmqR11wKUIscQ
<iframe width="100%" height="500" src="https://hackmd.io/XwCqr6UPRPmqR11wKUIscQ" frameborder="0"></iframe>
### Startup.cs
#### `app.UseMvc();` でエラーとなる場合は、以下の処理を追加。
```csharp=
public void ConfigureServices(IServiceCollection services)
{
・・・
services.AddMvc(options => options.EnableEndpointRouting = false);
}
```
#### CompatibilityVersionを変更する。
`CompatibilityVersion.Version_2_1`→`CompatibilityVersion.Latest`
#### app.UseSignalR を変更する。
変更前
```csharp=
app.UseSignalR(route =>
{
route.MapHub<ChatHub>("/chathub");
});
```
変更後
```csharp=
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
```
:::info
`app.UseRouting();`がない場合は、以下のエラーが発生します。
```shell=
System.InvalidOperationException: 'EndpointRoutingMiddleware matches endpoints setup by EndpointMiddleware and so must be added to the request execution pipeline before EndpointMiddleware. Please add EndpointRoutingMiddleware by calling 'IApplicationBuilder.UseRouting' inside the call to 'Configure(...)' in the application startup code.'
```
:::
#### `IHostingEnvironment` を `IWebHostEnvironment` に変更する。
この時、以下でエラーとなる場合は、`using Microsoft.Extensions.Hosting;` を追加する。
```csharp=
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
・・・
```
```csharp=
using Microsoft.Extensions.Hosting;
```
:::info
エラーの内容。
```shell=
dbug: HttpsConnectionAdapter[1]
Failed to authenticate HTTPS connection.
System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.BeginAuthenticateAsServer(SslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState)
at System.Net.Security.SslStream.<>c.<AuthenticateAsServerAsync>b__51_0(SslServerAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state)
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
at System.Net.Security.SslStream.AuthenticateAsServerAsync(SslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
dbug: HttpsConnectionAdapter[1]
Failed to authenticate HTTPS connection.
System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.BeginAuthenticateAsServer(SslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState)
at System.Net.Security.SslStream.<>c.<AuthenticateAsServerAsync>b__51_0(SslServerAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state)
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
at System.Net.Security.SslStream.AuthenticateAsServerAsync(SslServerAuthenticationOptions sslServerAuthenticationOptions, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
```
:::
## Register.cshtml.cs を修正する。
https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/signalr/authn-and-authz/sample/Pages/Account/Register.cshtml.cs
`OnPostAsync` メソッドを以下のように変更する。
```csharp=
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
ReturnUrl = returnUrl;
if (ModelState.IsValid)
{
#region AddEmailClaim
// create a new user
var user = new ApplicationUser {
UserName = Input.Email,
Email = Input.Email
};
IdentityResult result = await _userManager.CreateAsync(
user,
Input.Password
);
#endregion
if (result.Succeeded)
{
// add the email claim and value for this user
var claim = new Claim(
type : ClaimTypes.Email,
value: Input.Email
);
await _userManager.AddClaimAsync(user, claim);
_logger.LogInformation("User created a new account with password.");
// We don't log the user in because we don't want to set a cookie in this sample.
return LocalRedirect(Url.Page("/Index"));
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
```
###### tags: `SignalR` `ASP.NET Core` `signalr/authn-and-authz`