没有ASP.NET身份的.NET Core外部身份验证 [英] .NET Core External Authentication without ASP.NET Identity

查看:97
本文介绍了没有ASP.NET身份的.NET Core外部身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用自己的JWT令牌身份验证,而不使用默认模板免费提供的asp.net身份.我到处都是关于如何在没有asp.net身份的情况下实现外部身份验证的文档/指南,但是那里的所有文章都是关于asp.net身份验证的.

I use my own JWT token authentication and not the asp.net identity that comes free with the default template. I've looked everywhere for some documentation/guidence on how to implement exernal authentication without asp.net identity but all articles out there is for the asp.net identity authentication.

我已经成功地将用户重定向到google登录页面(使用ChallengeResult),但是当提供商将其重定向回该应用程序时,我失败了.

I've managed to redirect the user to the google log in page, (using ChallengeResult), but when the provider redirects back the app fails me.

我已删除: Startup.cs 中的 app.UseAuthentication(); ,(禁用身份验证),然后我可以使用回调函数,但随后我不知道如何在不使用登录管理器的情况下从响应中检索数据.

I've removed: app.UseAuthentication(); in Startup.cs, (disabling authentication), and I was then able to reach the callback function but then I had no idea how to retrieve the data from the respons without using the sign in manager..

启动

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的堆栈跟踪

信息: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来处理以下方案的登录:Bearer 在Microsoft.AspNetCore.Authentication.AuthenticationService.d__13.MoveNext() ---从上一个引发异常的位置开始的堆栈结束跟踪--- 在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler d__12.MoveNext() ---从上一个引发异常的位置开始的堆栈结束跟踪--- 在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext() ---从上一个引发异常的位置开始的堆栈结束跟踪--- 在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext() ---从上一个引发异常的位置开始的堆栈结束跟踪--- 在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Frame`1.d__2.MoveNext()

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1] Request starting HTTP/1.1 GET http://localhost:5000/api/authentication/externalauthentication/externallogincallback?state=CfDJ8CyKJfDTf--HIDDEN DATA--52462e4156a..5cde&prompt=none fail: Microsoft.AspNetCore.Server.Kestrel[13] Connection id "0HLAKEGSHERH7", Request id "0HLAKEGSHERH7:00000002": An unhandled exception was thrown by the application. System.InvalidOperationException: No IAuthenticationSignInHandler is configured to handle sign in for the scheme: Bearer at Microsoft.AspNetCore.Authentication.AuthenticationService.d__13.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler d__12.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.d__3.MoveNext() --- End of stack trace from previous location where exception was thrown --- at 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. 关于此,我还没有找到任何文档,可以肯定,如果不使用内置的jumbo dumbo asp.net身份,我不是唯一需要外部身份验证的人吗?如果您是比我更好的Googler,请向我指出正确的方向!

推荐答案

要解决的问题:

未将IAuthenticationSignInHandler配置为处理以下内容的登录 方案:不记名

No IAuthenticationSignInHandler is configured to handle sign in for the scheme: Bearer

我必须添加一个cookie处理程序,该处理程序将临时存储外部身份验证的结果,例如外部提供商发送的索赔.这是必要的,因为在完成外部身份验证过程之前,通常涉及几个重定向.

I had to add a cookie handler that will temporarily store the outcome of the external authentication, e.g. the claims that got sent by the external provider. This is necessary since there are typically a couple of redirects involved until you are done with the external authentication process.

启动

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.这是一个字符串常量,用于存储"Cookies".虽然我们可以在代码中直接使用字符串"Cookies",但使用预设常量会更安全.这是默认情况下为AddCookies函数提供的身份验证方案名称.它可以帮助您参考cookie身份验证.

The important part here is CookieAuthenticationDefaults.AuthenticationScheme. This is a string constant that stores "Cookies". While we can directly use the string "Cookies" within our code, using the preset constant would be safer. This is the authentication scheme name given to the AddCookies function by default. It helps you reference the cookies authentication.

现在是时候从回调操作中外部身份验证提供的声明中检索用户信息了.

Now it's time to retrieve the user information from the claims provided by the external authentication in the callback action.

控制器

[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;
}

Voilà!现在,我们可以使用一些用户信息!

Voilà! We now have some user information to work with!

有用的链接

http://docs.identityserver.io/zh-CN/latest/topics/signin_external_providers.html

这篇关于没有ASP.NET身份的.NET Core外部身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆