- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
背景:
我正在尝试支持授权代码流以启用从我的应用程序到第三方应用程序的 SSO。
现在我卡在了应该返回 AuthenticationTicket 的 Unprotect 方法的实现上。
OAuth2 服务器配置:
var allowInsecureHttp = bool.Parse(ConfigurationManager.AppSettings["AllowInsecureHttp"]);
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = allowInsecureHttp,
TokenEndpointPath = new PathString("/oauth2/token"),
AuthorizeEndpointPath = new PathString("/oauth2/authorize"),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
Provider = new CustomOAuthProvider(HlGlobals.Kernel),
AccessTokenFormat = new CustomJwtFormat(_baseUrl, HlGlobals.Kernel),
AuthorizationCodeProvider = new SimpleAuthenticationTokenProvider(),
AuthorizationCodeFormat = new CustomJwtFormat(_baseUrl, HlGlobals.Kernel)
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
JWT token 生成/保护方法:
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
// Get the client and assign to GUID -- the audience is api this token will be valid against
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
Guid clientId;
bool isValidAudience = Guid.TryParse(audienceId, out clientId);
// Check for a valid Client Guid in the Auth ticket properties
if (!isValidAudience)
{
throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
}
// Create the JWT token
string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new HmacSigningCredentials(keyByteArray);
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, signingKey);
var handler = new JwtSecurityTokenHandler();
var jwt = handler.WriteToken(token);
// Return the JWT Token
return jwt;
}
最后,'Unprotect' 方法负责验证 JWT 并返回和验证票据:
public AuthenticationTicket Unprotect(string protectedText)
{
string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
Guid clientId;
bool isValidAudience = Guid.TryParse(audienceId, out clientId);
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new HmacSigningCredentials(keyByteArray);
var tokenValidationParameters = new TokenValidationParameters
{
ValidAudience = audienceId,
ValidIssuer = _issuer,
IssuerSigningKey = signingKey // Cannot convert HMAC Signing Credentials to System.IdentityModel.Tokens.SecurityKey
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
RequireSignedTokens = true,
RequireExpirationTime = true,
ValidateIssuerSigningKey = true
};
var handler = new JwtSecurityTokenHandler();
SecurityToken token = null;
var principal = handler.ValidateToken(protectedText, tokenValidationParameters, out token);
var identity = principal.Identities;
return new AuthenticationTicket(identity.First(), new AuthenticationProperties());
}
立即发布的一个问题是发行者签名 key 。我无法提出可接受的参数。我看到错误消息:
Cannot convert HMAC Signing Credentials to System.IdentityModel.Tokens.SecurityKey
老实说,我不确定为什么 Protect 方法需要触发。我认为流程会随着 JWT token 的返回而结束,但显然不是。现在我正在努力实现 Unprotect 方法,因为这是我以前从未遇到过的事情。
即使我在 tokenValidationParamters 上将所有选项都设置为“false”,我仍然会在验证时收到以下错误:
An exception of type 'System.IdentityModel.SignatureVerificationFailedException' occurred in System.IdentityModel.Tokens.Jwt.dll but was not handled in user code
Additional information: IDX10503: Signature validation failed. Keys tried: ''.
Exceptions caught:
''.
token: '{"typ":"JWT","alg":"HS256"}.{"iss":"http://myissuer.com","aud":"346e886acabf457cb9f721f615ff996c","exp":1510925372,"nbf":1510925072}'
当我使用 JWT.IO 将这些值与解密的 token 进行比较时,所有值都按预期匹配。
任何关于我在这里可能做错了什么的指导,或者如何使用 token 验证参数上的有效签名 key 调用 validateToken 的任何指导都将非常有帮助和赞赏。
提前致谢!
编辑:
我很好奇为什么 Unprotect 会触发……我想我应该向客户端返回一个 JWT token 。返回 JWT 的方法在 Unprotect 方法之前触发,并且 JWT 永远不会返回给客户端。
我是否配置不正确?
最佳答案
在您的 Startup.cs 文件中调用以下方法。当用户实际尝试登录身份验证服务器端点时,将调用 customJwtFormat 中的 Protect 方法。当用户尝试通过“Bearer [token]”身份验证模型访问 protected api url 时,将调用 unprotect 方法。例如,如果您不在 Startup.cs 文件中说明 app.UseOAuthBearerAuthentication,您最终会收到诸如
之类的错误Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Warning: 0 : invalid bearer token received
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
{
AccessTokenFormat = _tokenFormat
});
像下面这样创建您的 customjwtFormat,您可以根据需要更改实现。
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
//var signingKey = new HmacSigningCredentials(keyByteArray);
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyByteArray);
securityKey.KeyId = ConfigurationManager.AppSettings["as:AudienceId"];
var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
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;
}
public AuthenticationTicket Unprotect(string protectedText)
{
string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
string authority = ConfigurationManager.AppSettings["Authority"];
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyByteArray);
var tokenValidationParameters = new TokenValidationParameters
{
ValidAudience = audienceId,
ValidIssuer = _issuer,
IssuerSigningKey = signingKey,
ValidateLifetime = true,
ValidateAudience = true,
ValidateIssuer = true,
RequireSignedTokens = true,
RequireExpirationTime = true,
ValidateIssuerSigningKey = true
};
var handler = new JwtSecurityTokenHandler();
SecurityToken token = null;
// Unpack token
var pt = handler.ReadJwtToken(protectedText);
string t = pt.RawData;
var principal = handler.ValidateToken(t, tokenValidationParameters, out token);
var identity = principal.Identities;
return new AuthenticationTicket(identity.First(), new AuthenticationProperties());
}
关于c# - 如何实现 ISecureDataFormat<AuthenticationTicket> Unprotect 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47351750/
我正在尝试向 Microsoft Unity 注册 ISecureDataFormat。我试过这样注册: container.RegisterType>(); 然而,当我尝试到达类时遇到以下错误: T
背景: 我正在尝试支持授权代码流以启用从我的应用程序到第三方应用程序的 SSO。 现在我卡在了应该返回 AuthenticationTicket 的 Unprotect 方法的实现上。 OAuth2
我正在将一个大型代码库从 Ninject 迁移到 Autofac,并且正在努力处理其中一个绑定(bind)(根据我的一些调试,我认为这会导致激活错误)。 注入(inject): Bind>()
我遇到了同样的问题 here没有答案,只是使用 Unity。 我正在尝试注册 ISecureDataFormat<>在最新的 VS2013(更新 2)SPA/Web Api 模板中。 我试过了 con
我是一名优秀的程序员,十分优秀!