【发布时间】:2017-07-09 05:49:50
【问题描述】:
我正在尝试创建 Jwt 令牌授权。为此,我有发行者部分的代码如下:
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] {"*"});
Users user;
using (var db = new UserStore())
{
user = Task.Run(()=> db.FindUser(context.UserName, context.Password, context.ClientId)).Result;
}
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect");
return Task.FromResult<object>(null);
}
var identity = new ClaimsIdentity("JWT");
identity.AddClaim(new Claim(ClaimTypes.Name, user.Email));
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim(ClaimTypes.Role, user.Roles.Name));
var props = new AuthenticationProperties(new Dictionary<string, string>
{
{
"audience", context.ClientId ?? string.Empty
}
});
var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
return Task.FromResult<object>(null);
}
以及应该接受不记名令牌的“资源”部分:
public void ConfigureOAuth(IAppBuilder app)
{
var issuer = SiteGlobal.Issuer;
var audience = SiteGlobal.Audience;
var secret = TextEncodings.Base64Url.Decode(SiteGlobal.Secret);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
});
}
据我所知,颁发的令牌是有效的(我在 jwt.io 上进行了验证),所以问题出在其他地方。当我在 Postman 中发送令牌并调用受 [Authorize] 属性保护的控制器时,它总是返回 401 代码。您能告诉我如何解决这个问题吗?
附:这就是我实现自定义 Jwt 格式的方式:
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null;
if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
Audience audience;
using (var store = new AudienceStore())
{
audience = Task.Run(()=> store.FindAudience(audienceId)).Result;
}
var symmetricKeyAsBase64 = audience.Base64Secret;
var signingKey = new InMemorySymmetricSecurityKey(Encoding.UTF8.GetBytes(symmetricKeyAsBase64));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingCredentials);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(token);
return jwt;
}
附:伙计们,我很抱歉,但我忘了解释代码的“发行者”部分是独立应用程序,同时“受众”是受保护的 web api。这是两个独立运行的不同应用程序。
【问题讨论】:
-
对此我不确定。标头有问题吗,我会收到类似错误的请求但不是未经授权的。
-
我没有得到
jwt的 exp,只有通过 URL 进行的REST查询,其中需要请求标头Authorization : Basic <encrypted user:pass>并且如果有问题(通过/名称/语法),它向我扔了 401。 -
@Tatranskymedved 这就是您将用于基本身份验证的方法,而不是 JWT。 JWT 需要
Authorization: Bearer <jwt>格式。 -
我在设置 JWT 并不断收到 401 时遇到了类似的问题。尝试更改启动类中的顺序,以便在其他任何事情之前完成 ConfigureOAuth。这为我解决了这个问题(Asp.Net Core WebAPI)。
标签: c# oauth-2.0 authorization owin jwt