AspNetCore WebApi / Angular与Twitter连接,然后创建JWT令牌

时间:2019-02-23 22:53:34

标签: angular .net-core asp.net-identity

我有一个角度应用程序使用的dotNetCore webapi项目。

我希望用户通过Twitter连接

然后用户填写其“电子邮件”

然后他将可以访问我的webApi。

对于一个mvc / razor网站,它可以正常工作,也是Asp.Net core 2 / VS2017中的基本模板

但是对于棱角怎么办?

身份库通过内部控制器支持最后阶段 / Identity / Account / ExternalLogin?ReturnUrl =%2F

Into Startup.cs吗?

var key = Encoding.ASCII.GetBytes(Configuration["Secret:JWT"]);
services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

services.AddAuthentication().AddTwitter(options =>
{
    options.ConsumerKey = Configuration["Twitter:ConsumerKey"];
    options.ConsumerSecret = Configuration["Twitter:ConsumerSecret"];
});

1 个答案:

答案 0 :(得分:0)

我通过咨询AspNetCore存储库代码找到了实现方法: https://github.com/aspnet/AspNetCore/tree/master/src/Identity/samples/IdentitySample.Mvc/Controllers/AccountController.cs

https://github.com/aspnet/AspNetCore/tree/master/src/Mvc/benchmarkapps/BasicApi

我的控制器

[Authorize]
public class ConnectController : ControllerBase
{
    private readonly SignInManager<IdentityUser> _signInManager;
    private readonly SigningCredentials _credentials;
    private readonly JwtBearerOptions _options;
    private readonly UserManager<IdentityUser> _userManager;

    public ConnectController(
        UserManager<IdentityUser> userManager,
        SignInManager<IdentityUser> signInManager, 
        IOptionsSnapshot<JwtBearerOptions> options,
        SigningCredentials credentials)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _options = options.Get(JwtBearerDefaults.AuthenticationScheme);
        _credentials = credentials;
    }
    [HttpPost]
    [HttpGet]
    [AllowAnonymous]
    [Route("connect/{provider}")]
    public IActionResult ExternalLogin(string provider)
    {
        var normalizeProvider = provider.First().ToString().ToUpper() + provider.Substring(1).ToLower();
        var properties = _signInManager.ConfigureExternalAuthenticationProperties(normalizeProvider, "");
        properties.RedirectUri = Url.Action(nameof(ExternalLoginCallback));
        return Challenge(properties, normalizeProvider);
    }

    [AllowAnonymous]
    public async Task<IActionResult> ExternalLoginCallback()
    {
        var info = await _signInManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return Unauthorized();
        }
        // Sign in the user with this external login provider if the user already has a login.
        var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false);
        if (result.Succeeded)
        {
            // Update any authentication tokens if login succeeded
            await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
            return Content(GetToken(info));
        }
        if (result.IsLockedOut)
        {
            return Unauthorized();
        }
        // If the user does not have an account, then ask the user to create an account.
        return Ok(ActionRegisterModel.GetAction(Request.Cookies["identity.External"]));
    }

    // replay cookie identity.External
    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> Register([FromBody]RegisterModel registerModel)
    {
        // Get the information about the user from the external login provider
        // how to use header and not cookie identity.External ??
        //AuthenticateResult auth = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);
        var info = await _signInManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return Unauthorized();
        }
        var user = new IdentityUser { UserName = registerModel.Email, Email = registerModel.Email };
        var result = await _userManager.CreateAsync(user);
        if (result.Succeeded)
        {
            result = await _userManager.AddLoginAsync(user, info);
            if (result.Succeeded)
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                // Update any authentication tokens as well
                await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
                return Content(GetToken(info));
            }
        }
        return Unauthorized();
    }

    public string GetToken(ExternalLoginInfo info)
    {
        var identity = (ClaimsIdentity)info.Principal.Identity;
        var handler = _options.SecurityTokenValidators.OfType<JwtSecurityTokenHandler>().First();

        var securityToken = handler.CreateJwtSecurityToken(
            issuer: _options.TokenValidationParameters.ValidIssuer,
            audience: _options.TokenValidationParameters.ValidAudience,
            signingCredentials: _credentials,
            subject: identity);

        var token = handler.WriteToken(securityToken);
        return token;
    }
}

并进入startup.cs

var rsa = new RSACryptoServiceProvider(2048);
var key = new RsaSecurityKey(rsa.ExportParameters(true));

services.AddSingleton(new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature));

services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
        //options.RequireHttpsMetadata = false;
        options.SaveToken = true;
        options.TokenValidationParameters.IssuerSigningKey = key;
        options.TokenValidationParameters.ValidAudience = "MyDomain";
        options.TokenValidationParameters.ValidIssuer = "MyAPI";
    });