如何在包含外部身份验证服务的asp.net中添加自定义声明?

时间:2019-01-28 14:12:48

标签: c# jwt openid-connect

我正在使用OpenId-Connect和Cookie基础身份验证来建立一个新的dotnet项目。我从某些身份验证服务器(如azure广告)接收的令牌基于RS256对称。 我有两个问题:

1st如何在RS256中的令牌中添加自定义变量。

2nd如何在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来完成。

Startup.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,
        });
}

2 个答案:

答案 0 :(得分:0)

第一个问题,

private string GenerateAccessJwt()
{
    JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();       

    SigningCredentials credentials = new SigningCredentials("your sign key", SecurityAlgorithms.RsaSha256);

    JwtSecurityToken token = new JwtSecurityToken(
        issuer: "Your issuer",
        audience: "Your audience",
        claims: new List<Claim>()
        {
            new Claim("OneClaim", "Hey I am a custom claim."),
        },
        expires: DateTime.Now.AddMinutes(1) //Short expiration for access token,
        signingCredentials: credentials);

    return handler.WriteToken(token);
}

此代码段应该可以解决问题,您必须使用https://docs.microsoft.com/en-us/previous-versions/visualstudio/dn464181(v%3Dvs.114)

在NET Standard 2.0上为我工作。

希望有帮助。

答案 1 :(得分:0)

找到了解决方案。

1st如何在RS256中的令牌中添加自定义变量。

您不需要。从具有OpenId connect的外部服务接收的令牌基本上是用于身份验证,而不是用于授权。我们可能会使用多种外部身份验证服务,在此处添加自定义声明不是一个好主意,也不应该这样做。

2nd如何在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());
    }
}

Startup.Auth.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
    LoginPath = Microsoft.Owin.PathString.FromUriComponent("/Account/SignIn"),
    TicketDataFormat = new CustomSecureDataFormat()
});