C# Web API 2/令牌返回更多信息

C# Web API 2/令牌返回更多信息,c#,asp.net-web-api,C#,Asp.net Web Api,我正在使用OAuth为我的应用程序生成令牌,特别是JWT。我的startup类中有以下代码: private void ConfigureOAuthTokenGeneration(IAppBuilder app) { // Configure the db context and user manager to use a single instance per request app.CreatePerOwinContext(DatabaseContext.Create);

我正在使用OAuth为我的应用程序生成令牌,特别是JWT。我的startup类中有以下代码:

private void ConfigureOAuthTokenGeneration(IAppBuilder app)
{

    // Configure the db context and user manager to use a single instance per request
    app.CreatePerOwinContext(DatabaseContext.Create);
    app.CreatePerOwinContext<UserService>(UserService.Create);
    app.CreatePerOwinContext<RoleService>(RoleService.Create);

    // Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here
    var OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        //For Dev enviroment only (on production should be AllowInsecureHttp = false)
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/oauth/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = new OAuthProvider(),
        AccessTokenFormat = new CustomJwtFormat("http://localhost:58127")
    };

    // OAuth 2.0 Bearer Access Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
}
这将返回您希望从令牌(access\u-token、expires\u-in和token\u-type)获得的内容,但我也想返回一些用户信息。比如用户名、角色等


有人知道我如何做到这一点吗?

用户名和角色出现在身份验证声明中,因此保存在JWT中,并在访问令牌中发送回JWT

所以这句话:

var token=新的JwtSecurityToken(_issuer,audienceId,data.Identity.Claims,issued,expires,signingKey);

插入来自授权标识的声明:

i、 e如果我在OAuth提供程序中执行此操作:

```

IList索赔=新列表();
if(context.UserName.Equals(“spencer”)&&context.UserName.Equals(context.Password))
{                
添加(新索赔(ClaimTypes.Name,user.DisplayName));
添加(新索赔(ClaimTypes.Role,“用户”);
}
));
var索赔=新索赔(索赔);
var票证=新的身份验证票证(类别实体,空);
//现在授权和声明都在我的身份上下文中
上下文。已验证(票证);
```

因此,现在生成JWT时,这些声明都在令牌中

然后,您可以使用显式角色来修饰Api控制器,该角色将查询索赔集中的“角色”类型。如果用户在角色索赔集中没有该角色,则会发出401:

```

[路线]
[授权(Roles=“User,Admin”)]
public IHttpActionResult Get()
{
返回Ok(_产品);
}
[路线]
[授权(Roles=“Admin”)]
公共IHttpActionResult帖子(产品)
{
_产品。添加(产品);
已创建退货(string.Empty,product);
}
```

因此,在上面的例子中,如果我生成一个JWT作为我的“Spencer”,我是在用户角色中,GET将是OK(200),而POST将是未经授权的(401)

有道理吗

public class OAuthProvider : OAuthAuthorizationServerProvider
{

    /// <summary>
    /// Validate client authentication
    /// </summary>
    /// <param name="context">The current context</param>
    /// <returns></returns>
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {

        // Validate all requests (because our front end is trusted)
        context.Validated();

        // Return nothing
        return Task.FromResult<object>(null);
    }

    /// <summary>
    /// Validate user credentials
    /// </summary>
    /// <param name="context">The current context</param>
    /// <returns></returns>
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        // Allow any origin
        var allowedOrigin = "*";

        // Add the access control allow all to our headers
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

        // Get our user service
        var service = context.OwinContext.GetUserManager<UserService>();

        // Find out user
        var user = await service.FindAsync(context.UserName, context.Password);

        // If the user is not found
        if (user == null)
        {

            // Set an error
            context.SetError("invalid_grant", "The user name or password is incorrect.");

            // Return from the function
            return;
        }

        // If the user has not confirmed their account
        if (!user.EmailConfirmed)
        {

            // Set an error
            context.SetError("invalid_grant", "User did not confirm email.");

            // Return from the function
            return;
        }

        // Generate the identity for the user
        var oAuthIdentity = await user.GenerateUserIdentityAsync(service, "JWT");

        // Create a new ticket
        var ticket = new AuthenticationTicket(oAuthIdentity, null);

        // Add the ticked to the validated context
        context.Validated(ticket);
    }
}
/// <summary>
/// JWT Format
/// </summary>
public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket>
{

    // Create our private property
    private readonly string issuer;

    /// <summary>
    /// Default constructor
    /// </summary>
    /// <param name="issuer">The issuer</param>
    public CustomJwtFormat(string issuer)
    {
        this.issuer = issuer;
    }

    /// <summary>
    /// Method to create our JWT token
    /// </summary>
    /// <param name="data">The Authentication ticket</param>
    /// <returns></returns>
    public string Protect(AuthenticationTicket data)
    {

        // If no data is supplied, throw an exception
        if (data == null)
            throw new ArgumentNullException("data");

        // Get our values from our appSettings
        string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
        string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];

        // Decode our secret and encrypt the bytes
        var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
        var signingKey = new HmacSigningCredentials(keyByteArray);

        // Get our issue and expire dates in UNIX timestamps
        var issued = data.Properties.IssuedUtc;
        var expires = data.Properties.ExpiresUtc;

        // Create our new token
        var token = new JwtSecurityToken(this.issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);

        // Create a handler
        var handler = new JwtSecurityTokenHandler();

        // Write our token string
        var jwt = handler.WriteToken(token);

        // Return our token string
        return jwt;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="protectedText"></param>
    /// <returns></returns>
    public AuthenticationTicket Unprotect(string protectedText)
    {
        throw new NotImplementedException();
    }
}
// Create our new token
var token = new JwtSecurityToken(this.issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);

// Create a handler
var handler = new JwtSecurityTokenHandler();

// Write our token string
var jwt = handler.WriteToken(token);
IList<Claim> claims = new List<Claim>();

if (context.UserName.Equals("spencer") && context.UserName.Equals(context.Password))
        {                
            claims.Add(new Claim(ClaimTypes.Name, user.DisplayName));
            claims.Add(new Claim(ClaimTypes.Role, "User"));
        }
));

var claimIdentity = new ClaimsIdentity(claims);
var ticket = new AuthenticationTicket(claimIdentity, null);

//Now authed and claims are in my identity context
context.Validated(ticket);
[Route]
[Authorize(Roles ="User,Admin")]
public IHttpActionResult Get()
{
    return Ok<IEnumerable<Product>>(_products);
}

[Route]
[Authorize(Roles = "Admin")]
public IHttpActionResult Post(Product product)
{
    _products.Add(product);
    return Created(string.Empty, product);
}