在多个服务中使用Oauth票证?

时间:2014-02-16 00:40:08

标签: oauth-2.0 owin

我目前有一对基于OWIN的服务,每个服务都对同一组用户使用OAuth身份验证。我打算隔离授权服务器(即令牌端点),并以某种方式配置我的两个服务以接受此令牌。我假设这将涉及我的所有服务的一些配置,以允许在所有相关服务上解密该令牌。这可能吗?

4 个答案:

答案 0 :(得分:20)

在对原帖的评论中与Brock Allen交谈之后,我无法保证这是一个好的/安全的解决方案,但这是我最终使用的代码。 (注意:此代码的版本以a nuget package提供。)

我创建了一个使用AES的IDataProtector实现:

internal class AesDataProtectorProvider : IDataProtector
{
    // Fields
    private byte[] key;

    // Constructors
    public AesDataProtectorProvider(string key)
    {
        using (var sha1 = new SHA256Managed())
        {
            this.key = sha1.ComputeHash(Encoding.UTF8.GetBytes(key));
        }
    }

    // IDataProtector Methods
    public byte[] Protect(byte[] data)
    {
        byte[] dataHash;
        using (var sha = new SHA256Managed())
        {
            dataHash = sha.ComputeHash(data);
        }

        using (AesManaged aesAlg = new AesManaged())
        {
            aesAlg.Key = this.key;
            aesAlg.GenerateIV();

            using (var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
            using (var msEncrypt = new MemoryStream())
            {
                msEncrypt.Write(aesAlg.IV, 0, 16);

                using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                using (var bwEncrypt = new BinaryWriter(csEncrypt))
                {
                    bwEncrypt.Write(dataHash);
                    bwEncrypt.Write(data.Length);
                    bwEncrypt.Write(data);
                }
                var protectedData = msEncrypt.ToArray();
                return protectedData;
            }
        }
    }

    public byte[] Unprotect(byte[] protectedData)
    {
        using (AesManaged aesAlg = new AesManaged())
        {
            aesAlg.Key = this.key;

            using (var msDecrypt = new MemoryStream(protectedData))
            {
                byte[] iv = new byte[16];
                msDecrypt.Read(iv, 0, 16);

                aesAlg.IV = iv;

                using (var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
                using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                using (var brDecrypt = new BinaryReader(csDecrypt))
                {
                    var signature = brDecrypt.ReadBytes(32);
                    var len = brDecrypt.ReadInt32();
                    var data = brDecrypt.ReadBytes(len);

                    byte[] dataHash;
                    using (var sha = new SHA256Managed())
                    {
                        dataHash = sha.ComputeHash(data);
                    }

                    if (!dataHash.SequenceEqual(signature))
                        throw new SecurityException("Signature does not match the computed hash");

                    return data;
                }
            }
        }
    }
}

然后在ISecureDataFormat实现中使用它,如下所示:

public class SecureTokenFormatter : ISecureDataFormat<AuthenticationTicket>
{
    // Fields
    private TicketSerializer serializer;
    private IDataProtector protector;
    private ITextEncoder encoder;

    // Constructors
    public SecureTokenFormatter(string key)
    {
        this.serializer = new TicketSerializer();
        this.protector = new AesDataProtectorProvider(key);
        this.encoder = TextEncodings.Base64Url;
    }

    // ISecureDataFormat<AuthenticationTicket> Members
    public string Protect(AuthenticationTicket ticket)
    {
        var ticketData = this.serializer.Serialize(ticket);
        var protectedData = this.protector.Protect(ticketData);
        var protectedString = this.encoder.Encode(protectedData);
        return protectedString;
    }

    public AuthenticationTicket Unprotect(string text)
    {
        var protectedData = this.encoder.Decode(text);
        var ticketData = this.protector.Unprotect(protectedData);
        var ticket = this.serializer.Deserialize(ticketData);
        return ticket;
    }
}

然后,构造函数上的'key'参数可以在许多服务上设置为相同的值,并且它们都能够解密('unprotect')并使用该票证。

答案 1 :(得分:9)

Katana OAuth2授权服务器中间件并非真正针对此方案设计(主要是因为它依赖于机器密钥进行令牌验证)。

如果您希望集中标记生成,那么您应该查看专为此设计的OAuth2授权服务器。 Thinktecture AuthorizationServer是一个开源服务器,它执行此操作:http://thinktecture.github.io/Thinktecture.AuthorizationServer/

答案 2 :(得分:0)

我知道这是一个老问题,但我有一个类似的用例。根据文档,OWIN OAuth使用机器密钥来保护数据。由于您控制所有实例,我认为只需在Web配置中设置machinekey即可。

参考:http://msdn.microsoft.com/en-us/library/microsoft.owin.security.oauth.oauthauthorizationserveroptions(v=vs.113).aspx

答案 3 :(得分:0)

您可以使用此nuget包https://www.nuget.org/packages/Owin.Security.AesDataProtectorProvider/

它包含IAppBuilder的扩展方法,允许您设置自己的密钥

appBuilder.UseAesDataProtectorProvider(key);