IdentityServer4使用asp.net核心中的密码授予请求JWT/访问承载令牌 [英] IdentityServer4 requesting a JWT / Access Bearer Token using the password grant in asp.net core

查看:102
本文介绍了IdentityServer4使用asp.net核心中的密码授予请求JWT/访问承载令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在asp.net核心中使用IdentityServer4使用密码授予来搜索请求JWT/访问承载令牌的全部内容,但是我似乎找不到正确的方法.

I've searched all over on requesting a JWT / Access Bearer Token using the password grant using IdentityServer4 in asp.net core, but I cant seem to find the right way to do it.

下面是我注册用户的POST请求.

Below is the POST Request from which I register my user.

http://localhost:52718/account/register

下面是Bearer Token GET Request,我可以使用IdentityServer4从中获取JWT Token

Below is the Bearer Token GET Request from which I can get JWT Token using IdentityServer4

http://localhost:52718/connect/token

下面是我从我的用户登录的POST请求

Below is the POST Request from which I Login my user

http://localhost:52718/account/signin

现在,我要执行的操作是登录用户时,我想要一个与从此处获得的JWT/承载令牌相同的 http://localhost:52718/connect/token .当我点击此URL时.

Now, what I'm trying to do is when I login my user then I want a JWT / Bearer Token same as I get from here http://localhost:52718/connect/token. When I hit this URL.

这是我的AccountController代码:

Here is my AccountController Code:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Server.Models;
using Server.Models.AccountViewModels;
using Server.Models.UserViewModels;

namespace Server.Controllers
{
    public class AccountController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly RoleManager<IdentityRole> _roleManager;

        public AccountController(
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager
            )
        {
            _userManager = userManager;
            _roleManager = roleManager;
        }

        [HttpPost]
        public async Task<IActionResult> Register([FromBody]RegisterViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new ApplicationUser { UserName = model.UserName, FirstName = model.FirstName, LastName = model.LastName, Email = model.Email };

            var result = await _userManager.CreateAsync(user, model.Password);

            string role = "Basic User";

            if (result.Succeeded)
            {
                if (await _roleManager.FindByNameAsync(role) == null)
                {
                    await _roleManager.CreateAsync(new IdentityRole(role));
                }
                await _userManager.AddToRoleAsync(user, role);
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("userName", user.UserName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("firstName", user.FirstName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("lastName", user.LastName));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("email", user.Email));
                await _userManager.AddClaimAsync(user, new System.Security.Claims.Claim("role", role));

                return Ok(new ProfileViewModel(user));
            }

            return BadRequest(result.Errors);


        }

        public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var result = await _userManager.FindByNameAsync(model.UserName);

            if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
            {
                return Ok(new ProfileViewModel(result));
            }

            return BadRequest("Invalid username or password.");
        }
    }
}

当我点击登录方法时,我成功获取了用户的数据.

When I hit signin method I successfully get the data of user.

但是当用户登录我的应用程序时,我还需要一个jwt/访问令牌.

But I also need a jwt / access token when user login my app.

现在我的实际问题是:

我的登录方法可以做什么,因此当用户登录时,它会向我返回令牌以及其他用户数据.我希望我简短地解释我的问题.

What can I do in my signin method so when user login it returns me token along with other user data. I hope I briefly explain my question.

谢谢

推荐答案

我找到了自己的问题答案.在开始之前,我向您展示我在定义客户端的那个代码.

I've found my own question answer. Before starting I show you my that code where I'm Defining the client.

public static IEnumerable<Client> GetClients()
{
        // client credentials client
    return new List<Client>
    {

        // resource owner password grant client
        new Client
        {
            ClientId = "ro.angular",
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,

            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.Address,
                "api1"
            }
        }
    };
}

现在我在登录方法中要做的就是使用TokenClient类来请求令牌.要创建实例,您需要传递令牌端点地址,客户端ID和密码.

Now what I do in my Signin Method is to use the TokenClient class to request the token. To create an instance you need to pass in the token endpoint address, client id and secret.

接下来,我正在使用

Next I'm using Requesting a token using the password grant to allows a client to send username and password to the token service and get an access token back that represents that user.

这是我需要修改的登录代码:

Here is my Signin Code which I need to modify:

public async Task<IActionResult> Signin([FromBody]LoginViewModel model)
{
    var disco = await DiscoveryClient.GetAsync("http://localhost:52718");
    if (disco.IsError)
    {
        return BadRequest(disco.Error);
    }

    var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.angular", "secret");
    var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync(model.UserName, model.Password, "api1 openid");

    if (tokenResponse.IsError)
    {
        return BadRequest(tokenResponse.Error);
    }

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = _userManager.FindByNameAsync(model.UserName);

    var result = await _userManager.FindByNameAsync(model.UserName);

    if (result != null && await _userManager.CheckPasswordAsync(result, model.Password))
    {
        return Ok(new ProfileViewModel(result, tokenResponse));
    }

        return BadRequest("Invalid username or password.");
}

我还修改了ProfileViewModel类,并添加了两个新的令牌&到期时间:

Also I modify ProfileViewModel Class and add two new Token & Expiry:

public class ProfileViewModel
{
    public string Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }

    public string Token { get; set; }

    public int Expiry { get; set; }

    public ProfileViewModel()
    {

    }

    public ProfileViewModel(ApplicationUser user, TokenResponse UToken = null)
    {
        Id = user.Id;
        FirstName = user.FirstName;
        LastName = user.LastName;
        Email = user.Email;
        Token = UToken.AccessToken;
        Expiry = UToken.ExpiresIn;
    }

    public static IEnumerable<ProfileViewModel> GetUserProfiles(IEnumerable<ApplicationUser> users)
    {
        var profiles = new List<ProfileViewModel> { };
        foreach (ApplicationUser user in users)
        {
            profiles.Add(new ProfileViewModel(user));
        }

        return profiles;
    }
}

现在这是我的愿望输出.希望这个答案可以帮助其他人.

Now Here is my desire output. Hope this answer help others.

这篇关于IdentityServer4使用asp.net核心中的密码授予请求JWT/访问承载令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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