C# 在WebApi中使用OAuth承载令牌生成和Owin向客户端返回更多信息

C# 在WebApi中使用OAuth承载令牌生成和Owin向客户端返回更多信息,c#,authentication,owin,asp.net-web-api2,bearer-token,C#,Authentication,Owin,Asp.net Web Api2,Bearer Token,我创建了一个WebApi和一个Cordova应用程序。 我使用HTTP请求在Cordova应用程序和WebAPI之间进行通信。 在WebAPI中,我实现了OAuth承载令牌生成 public void ConfigureOAuth(IAppBuilder app) { var oAuthServerOptions = new OAuthAuthorizationServerOptions { AllowInsecureHttp =

我创建了一个WebApi和一个Cordova应用程序。 我使用HTTP请求在Cordova应用程序和WebAPI之间进行通信。 在WebAPI中,我实现了OAuth承载令牌生成

public void ConfigureOAuth(IAppBuilder app)
    {
        var oAuthServerOptions = new OAuthAuthorizationServerOptions
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new SimpleAuthorizationServerProvider(new UserService(new Repository<User>(new RabbitApiObjectContext()), new EncryptionService()))
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(oAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    }
从Cordova应用程序成功登录API后,我收到以下JSON

{"access_token":"some token","token_type":"bearer","expires_in":86399}
问题是,我需要更多关于用户的信息。例如,我在数据库中有一个UserGuid字段,我希望在登录成功时将其发送到Cordova应用程序,并在以后的其他请求中使用它。除了
“访问令牌”、“令牌类型”
“过期”
之外,我是否可以包含其他信息以返回到客户端?如果没有,如何根据
访问令牌
在API中获取用户


编辑:

我想我找到了解决办法。 我在GrantResourceOwnerCredentials中添加了以下代码

identity.AddClaim(new Claim(ClaimTypes.Name, user.UserGuid.ToString()));
然后,我访问控制器中的GUID,如下所示:
User.Identity.Name

我还可以向guid添加自定义名称
identity.AddClaim(新声明(“guid”,user.UserGuid.ToString())


我仍然有兴趣知道是否有办法使用承载令牌JSON向客户端返回更多数据。

您可以添加任意数量的声明。
您可以从
System.Security.claims
添加标准声明集或创建自己的声明集。
声明将在您的令牌中加密,因此只能从资源服务器访问

如果您希望客户端能够读取令牌的扩展属性,您还有另一个选项:
AuthenticationProperties

假设您想添加一些内容,以便您的客户可以访问。这就是出路:

var props = new AuthenticationProperties(new Dictionary<string, string>
{
    { 
        "surname", "Smith"
    },
    { 
        "age", "20"
    },
    { 
    "gender", "Male"
    }
});
这就是您的客户将获取的结果:

.expires: "Tue, 14 Oct 2014 20:42:52 GMT"
.issued: "Tue, 14 Oct 2014 20:12:52 GMT"
access_token: "blahblahblah"
expires_in: 1799
age: "20"
gender: "Male"
surname: "Smith"
token_type: "bearer"
另一方面,如果添加声明,则可以在API控制器的资源服务器中读取声明:

public IHttpActionResult Get()
{
    ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

    return Ok();
}
您的
ClaimsPrincipal
将包含您在此处添加的新索赔的
guid

identity.AddClaim(new Claim("guid", user.UserGuid.ToString()));
如果您想更多地了解owin、承载令牌和web api,有一个非常好的教程,这将帮助您掌握授权服务器和资源服务器背后的所有概念

更新

你可以找到一个有效的例子。这是一个自托管的Web Api+Owin
这里没有数据库。 客户端是一个控制台应用程序(还有一个html+JavaScript示例),它调用传递凭据的Web Api

正如Taiseer所建议的,您需要覆盖
TokenEndpoint

public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}
public覆盖任务令牌端点(OAuthTokenEndpointContext)
{
foreach(context.Properties.Dictionary中的KeyValuePair属性)
{
AdditionalResponseParameters.Add(property.Key,property.Value);
}
返回Task.FromResult(空);
}

从解决方案->属性中启用“多个启动项目”,您可以直接运行它。

我的建议是,如果不需要,不要向令牌添加额外的声明,因为这会增加令牌的大小,并且您将在每次请求时继续发送它。 正如LeftyX建议的那样,将它们添加为属性,但确保在成功获取令牌时重写
TokenEndPoint
方法以获取这些属性作为响应,否则属性将不会在响应中返回

 public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        return Task.FromResult<object>(null);
    }
public覆盖任务令牌端点(OAuthTokenEndpointContext)
{
foreach(context.Properties.Dictionary中的KeyValuePair属性)
{
AdditionalResponseParameters.Add(property.Key,property.Value);
}
返回Task.FromResult(空);
}

您可以在这里查看完整的示例。希望能有所帮助。

谢谢您的回复。当我编写API时,我阅读了完全相同的文章,我甚至下载了代码并仔细阅读了一遍。因此我尝试使用
AuthenticationProperties
,但结果是一样的。在客户端,我仍然只在
属性中接收
access\u-token
token\u-type
expires\u。我在该项目中测试了我的解决方案,它可以正常工作。你是在用一个像小提琴手一样的嗅探器来观察发生了什么事吗?是的。我正在使用Fiddler,我也在调试API,但结果仍然是一样的。除非您从Taiseer的中重写公共重写任务TokenEndpoint(OAuthTokenEndpointContext)answer@Ers:是的,你说得对。忘了提一下。。。但那是在我的回购协议中。谢谢你的否决票。@TaiseerJoudeh你知道我是否可以把字符串数组作为属性之一吗?我需要发送一份今天的许可列表,对于Asp.NETCore来说,事情似乎有点变化
context.Properties.Dictionary
context.Ticket.Properties.Items
,但我找不到
context.AdditionalResponseParameters
等效项。有人知道吗?没关系,被ASOS联系上了author@TaiseerJoudeh可以包括其他用户模型属性,如user.birth?我在上下文中看到的唯一用户属性是context.username。?如何包含其他用户atributes?@AminM如果需要identity,可以手动将其添加为声明。AddClaim(新声明(“家族”、“家族名称值”);
public override Task TokenEndpoint(OAuthTokenEndpointContext context)
{
    foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
    {
        context.AdditionalResponseParameters.Add(property.Key, property.Value);
    }

    return Task.FromResult<object>(null);
}
 public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

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