c# - 如何在包含外部身份验证服务的 asp.net 中添加自定义声明?
问题描述
我正在使用 OpenId-Connect 和 Cookie 基础身份验证设置一个新的 dotnet 项目。我从某些身份验证服务器(如 azure ad)收到的令牌基于 RS256 对称。我有两个问题:
1st 如何在 RS256 中的令牌中添加自定义变量。
2如何在cookie中维护它们?
我已经尝试过 JWT.Serializers 但总是卡在某个点或其他点。
IJsonSerializer serializer = new JsonNetSerializer();
IDateTimeProvider provider = new UtcDateTimeProvider();
IJwtValidator validator = new JwtValidator(serializer, provider);
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
var algo = new JWT.Algorithms.RSAlgorithmFactory(() => new
Class1().GetByThumbprint("C11B7AF7C7910DEEB2273996BAB6033D73F6DC61"));
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algo);
不知道要不要继续这个。同样使用 HS256 很容易在https://jwt.io/上编辑令牌我无法使用 RS256 做到这一点。
启动.Auth.cs
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(
new CookieAuthenticationOptions()
{
AuthenticationMode = AuthenticationMode.Active,
LoginPath = Microsoft.Owin.PathString.FromUriComponent("/Account/SignIn")
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
});
}
解决方案
找到了解决方案。
1st 如何在 RS256 中的令牌中添加自定义变量。
你不需要。使用 OpenId 连接从外部服务接收到的令牌基本上是用于身份验证而不是用于授权。我们可能会使用多个外部身份验证服务,在这里添加自定义声明不是一个好主意,也不应该这样做。
2如何在cookie中维护它们?
这是我们可以修改令牌的地方。Cookie 与外部身份验证服务的对称密码不同。我们拦截 cookie 身份验证方法以添加自定义声明。
这是我的做法:
CustomSecureDataFormat.cs
public class CustomSecureDataFormat : ISecureDataFormat<AuthenticationTicket>
{
public string Protect(AuthenticationTicket data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
var claims = new List<Claim>();
//Custom claim
claims.Add(new Claim("HairCount", "46"));
data.Identity.AddClaims(claims);
string audienceId = AzureADConstants.GraphResourceId;
Guid guidClientId;
bool isValidAudience = Guid.TryParse(AzureADConstants.ClientId, out guidClientId);
if (!isValidAudience)
{
throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
}
var keyByteArray = TextEncodings.Base64Url.Decode(AzureADConstants.AppKey);
var securityKey = new SymmetricSecurityKey(keyByteArray);
var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(
securityKey,
SecurityAlgorithms.HmacSha256Signature);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
string _issuer = AzureADConstants.Authority;
var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingCredentials);
var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(token);
}
public AuthenticationTicket Unprotect(string protectedText)
{
if (string.IsNullOrWhiteSpace(protectedText))
{
throw new ArgumentNullException("protectedText");
}
var keyByteArray = TextEncodings.Base64Url.Decode(AzureADConstants.AppKey);
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyByteArray);
var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(
securityKey,
SecurityAlgorithms.HmacSha256Signature);
var handler = new JwtSecurityTokenHandler();
var securityToken = handler.ReadToken(protectedText);
string rawToken = ((JwtSecurityToken)securityToken).RawData;
string audienceId = AzureADConstants.GraphResourceId;
var validationParams = new TokenValidationParameters()
{
ValidateLifetime = false,
ValidAudience = audienceId,
ValidIssuer = audienceId,
ValidateIssuer = false,
ValidateAudience = false,
TokenDecryptionKey = securityKey,
IssuerSigningKey = securityKey
};
SecurityToken validatedToken;
var principal = handler.ValidateToken(rawToken, validationParams, out validatedToken);
var identity = principal.Identities;
return new AuthenticationTicket(identity.First(), new AuthenticationProperties());
}
}
启动.Auth.cs
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
LoginPath = Microsoft.Owin.PathString.FromUriComponent("/Account/SignIn"),
TicketDataFormat = new CustomSecureDataFormat()
});
推荐阅读
- laravel - 如何每 2 分钟从 API 获取数据并在所有项目中使用它?
- python-3.x - 创建一个函数以获取另一个函数的参数输入
- checksum - 校验和识别
- c# - SKCanvasView 事件参数仅包含 Pressed 动作类型
- javascript - 以函数式方式重构 JS 代码 - 闭包
- python - 在 Docker 容器中加载微调的 simpletransformer 模型时出错
- html - 在 Visual Studio 中发生未处理的异常,在取消该错误消息后,我网页上的 css 样式与以前不同
- android-studio - arcore中姿态检测模型的关键点作为输入
- scikit-learn - 无法导入“SelfTrainingClassifier”
- node.js - Flutter 在表单数据中发送多个文件时遇到问题