首页 > 解决方案 > 如何在包含外部身份验证服务的 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,
        });
}

标签: c#jwtopenid-connect

解决方案


找到了解决方案。

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()
});

推荐阅读