web-dev-qa-db-ja.com

ASP.NET Identityを使用しない.NET Core外部認証

私は自分のJWTトークン認証を使用し、デフォルトのテンプレートで無料で提供されるasp.net IDを使用しません。私は、asp.net IDなしで外部認証を実装する方法に関するドキュメント/ガイダンスをどこでも探しましたが、そこにあるすべての記事は、asp.net ID認証に関するものです。

(ChallengeResultを使用して)googleログインページにユーザーをリダイレクトすることに成功しましたが、プロバイダーがアプリをリダイレクトバックすると失敗します。

削除しました:app.UseAuthentication();inStartup.cs、(認証を無効にする)、コールバック関数に到達できましたが、サインインマネージャーを使用せずに応答からデータを取得する方法がわかりませんでした。

スタートアップ

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();

        Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Authentication:Secret"]));

        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,
            ValidateIssuer = true,
            ValidIssuer = Configuration["Urls:Base"],
            ValidateAudience = true,
            ValidAudience = Configuration["Urls:Base"],
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero
        };

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o =>
        {
            o.TokenValidationParameters = tokenValidationParameters;
        }
        ).AddGoogle(googleOptions =>
        {
            googleOptions.ClientId = "x";//Configuration["Authentication:Google:ClientId"];
            googleOptions.ClientSecret = "x";//Configuration["Authentication:Google:ClientSecret"];
            googleOptions.CallbackPath = "/api/authentication/externalauthentication/externallogincallback";
        });

        services.Configure<RequestLocalizationOptions>(
            opts =>
            {
                var supportedCultures = new List<CultureInfo>
                {
                        new CultureInfo("en"),
                        new CultureInfo("sv")
                };

                opts.DefaultRequestCulture = new RequestCulture(culture: "en", uiCulture: "en");
                opts.SupportedCultures = supportedCultures;
                opts.SupportedUICultures = supportedCultures;
            });

        services.AddMvc(config =>
        {
            var policy = new AuthorizationPolicyBuilder()
                             .RequireAuthenticatedUser()
                             .Build();

            config.Filters.Add(new AuthorizeFilter(policy));
        });

        services.RegisterAppSettings(Configuration);

        services.AddOptions();

        services.InjectServices();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseAuthentication();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();

            EndpointsAppSettings endpointAppSettings = new EndpointsAppSettings();
            Configuration.GetSection("Endpoints").Bind(endpointAppSettings);

            app.UseCors(builder =>
            {
                builder.WithOrigins(endpointAppSettings.Aurelia)
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();
            });
        }

        var logService = app.ApplicationServices.GetService<ILogService>();

        loggerFactory.AddProvider(new LogProvider(logService));

        app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value);

        app.UseMvc();

        app.UseDefaultFiles();

        app.UseStaticFiles();
    }
}

コントローラー

[Route("api/authentication/[controller]")]
public class ExternalAuthenticationController : Controller
{
    [AllowAnonymous]
    [HttpPost(nameof(ExternalLogin))]
    public IActionResult ExternalLogin(ExternalLoginModel model)
    {
        if (model == null || !ModelState.IsValid)
        {
            return null;
        }

        var properties = new AuthenticationProperties { RedirectUri = "http://localhost:3000/#/administration/organisations" };

        return Challenge(properties, model.Provider);
    }

    [AllowAnonymous]
    [HttpGet(nameof(ExternalLoginCallback))]
    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
    {
        if (remoteError != null)
        {
            return null;
        }

        //Help me retrieve information here!

        return null;
    }
}

ExternalLoginCallbackのスタックトレース

info:Microsoft.AspNetCore.Hosting.Internal.WebHost [1]リクエスト開始HTTP/1.1 GET http:// localhost:5000/api/authentication/externalauthentication/externallogincallback?state = CfDJ8CyKJfDTf--HIDDEN DATA --52462e4156a..5cde&Prompt = none失敗:Microsoft.AspNetCore.Server.Kestrel [13]接続ID "0HLAKEGSHERH7"、リクエストID "0HLAKEGSHERH7:00000002":ハンドルされていない例外がアプリケーションによってスローされました。 System.InvalidOperationException:スキームのサインインを処理するように構成されているIAuthenticationSignInHandlerはありません:Bearerat Microsoft.AspNetCore.Authentication.AuthenticationService.d__13.MoveNext()- -例外がスローされた以前の場所からのスタックトレースの終わり--- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler d__12.MoveNext()---例外がスローされた前の場所からのスタックトレースの終わり--- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)at Microsoft .AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext()---例外がスローされた前の場所からのスタックトレースの終わり--- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Th System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)at row。)at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext()---例外がスローされた前の場所からのスタックトレースの終わり--- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.d__2.MoveNext()

  1. 理由:スキームの署名を処理するようにIAuthenticationSignInHandlerが構成されていません:Bearerとこれはどのように解決されますか?
  2. ExternalLoginCallbackアクションでユーザー情報を取得するにはどうすればよいですか?デフォルトのmvcテンプレートを使用すると、次のように簡単でした。var info = await _signInManager.GetExternalLoginInfoAsync();サインインマネージャーは使用していません。
  3. これに関するドキュメントはまったく見つかりませんでしたが、組み込みのジャンボダンボasp.net IDを使用せずに外部認証を必要とするのは私だけではありませんか?あなたが私よりもグーグルであるなら、私を正しい方向に向けてください!
10
Reft

解決するには:

IAuthenticationSignInHandlerがスキームのサインインを処理するように構成されていません:Bearer

外部認証の結果を一時的に保存するCookieハンドラーを追加する必要がありました。外部プロバイダーから送信されたクレーム。外部認証プロセスが完了するまで、通常はいくつかのリダイレクトが含まれるため、これは必要です。

スタートアップ

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(o =>
{
    o.TokenValidationParameters = tokenValidationParameters;
})
.AddCookie()
.AddGoogle(googleOptions =>
{
    googleOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    googleOptions.ClientId = "x";//Configuration["Authentication:Google:ClientId"];
    googleOptions.ClientSecret = "x";//Configuration["Authentication:Google:ClientSecret"];
    //googleOptions.CallbackPath = "/api/authentication/externalauthentication/signin-google";
});

ここで重要な部分はCookieAuthenticationDefaults.AuthenticationSchemeです。これは「Cookie」を格納する文字列定数です。コード内で文字列「Cookies」を直接使用できますが、事前設定された定数を使用する方が安全です。これは、デフォルトでAddCookies関数に指定された認証方式名です。 Cookie認証の参照に役立ちます。

次に、コールバックアクションの外部認証によって提供されたクレームからユーザー情報を取得します。

コントローラー

[AllowAnonymous]
[HttpPost(nameof(ExternalLogin))]
public IActionResult ExternalLogin(ExternalLoginModel model)
{
    if (model == null || !ModelState.IsValid)
    {
        return null;
    }

    var properties = new AuthenticationProperties { RedirectUri = _authenticationAppSettings.External.RedirectUri };

    return Challenge(properties, model.Provider);
}

[AllowAnonymous]
[HttpGet(nameof(ExternalLoginCallback))]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    //Here we can retrieve the claims
    var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

    return null;
}

ほら!これで、使用するユーザー情報がいくつかあります!

enter image description here

役立つリンク

http://docs.identityserver.io/en/latest/topics/signin_external_providers.html

8
Reft