118 lines
4.9 KiB
C#
118 lines
4.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data.SqlClient;
|
|
using System.Linq;
|
|
using DotNetOpenAuth.Messaging.Bindings;
|
|
using Microsoft.Practices.ServiceLocation;
|
|
using Taloyhtio.GeneralSSO.Server.CodeFiles.Common;
|
|
using Taloyhtio.GeneralSSO.Server.CodeFiles.Entities;
|
|
using Taloyhtio.GeneralSSO.Server.CodeFiles.Repositories;
|
|
|
|
namespace Taloyhtio.GeneralSSO.Server.CodeFiles.Infrastructure.OAuth
|
|
{
|
|
public class DataStore : INonceStore, ICryptoKeyStore
|
|
{
|
|
private ISymmetricCryptoKeyRepository keyRepository;
|
|
private INonceRepository nonceRepository;
|
|
public DataStore()
|
|
{
|
|
this.keyRepository = ServiceLocator.Current.GetInstance<ISymmetricCryptoKeyRepository>();
|
|
this.nonceRepository = ServiceLocator.Current.GetInstance<INonceRepository>();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stores a given nonce and timestamp.
|
|
/// </summary>
|
|
/// <param name="context">The context, or namespace, within which the
|
|
/// <paramref name="nonce"/> must be unique.
|
|
/// The context SHOULD be treated as case-sensitive.
|
|
/// The value will never be <c>null</c> but may be the empty string.</param>
|
|
/// <param name="nonce">A series of random characters.</param>
|
|
/// <param name="timestampUtc">The UTC timestamp that together with the nonce string make it unique
|
|
/// within the given <paramref name="context"/>.
|
|
/// The timestamp may also be used by the data store to clear out old nonces.</param>
|
|
/// <returns>
|
|
/// True if the context+nonce+timestamp (combination) was not previously in the database.
|
|
/// False if the nonce was stored previously with the same timestamp and context.
|
|
/// </returns>
|
|
/// <remarks>
|
|
/// The nonce must be stored for no less than the maximum time window a message may
|
|
/// be processed within before being discarded as an expired message.
|
|
/// This maximum message age can be looked up via the
|
|
/// <see cref="DotNetOpenAuth.Configuration.MessagingElement.MaximumMessageLifetime"/>
|
|
/// property, accessible via the <see cref="DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration"/>
|
|
/// property.
|
|
/// </remarks>
|
|
public bool StoreNonce(string context, string code, DateTime timestampUtc)
|
|
{
|
|
try
|
|
{
|
|
if (this.nonceRepository.Exists(context, code, timestampUtc))
|
|
{
|
|
// possibly replay attack, return false
|
|
return false;
|
|
}
|
|
|
|
this.nonceRepository.Save(new Nonce { Context = context, Code = code, Timestamp = timestampUtc });
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public CryptoKey GetKey(string bucket, string handle)
|
|
{
|
|
var key = this.keyRepository.GetBy(bucket, handle);
|
|
if (key == null)
|
|
{
|
|
return null;
|
|
}
|
|
return new CryptoKey(key.Secret, key.ExpirationDate);
|
|
}
|
|
|
|
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket)
|
|
{
|
|
// return from key in ServerContext.DataContext.SymmetricCryptoKeys
|
|
// where key.Bucket == bucket
|
|
// orderby key.ExpiresUtc descending
|
|
// select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()));
|
|
var keys = this.keyRepository.GetByOrderedByExpirationDesc(bucket);
|
|
if (keys.IsNullOrEmpty())
|
|
{
|
|
return new List<KeyValuePair<string, CryptoKey>>();
|
|
}
|
|
return keys.Select(k => new KeyValuePair<string, CryptoKey>(k.Handle, new CryptoKey(k.Secret, k.ExpirationDate.AsUtc())));
|
|
}
|
|
|
|
public void StoreKey(string bucket, string handle, CryptoKey key)
|
|
{
|
|
var keyRow = new SymmetricCryptoKey()
|
|
{
|
|
Bucket = bucket,
|
|
Handle = handle,
|
|
Secret = key.Key,
|
|
ExpirationDate = key.ExpiresUtc,
|
|
};
|
|
|
|
// ServerContext.DataContext.SymmetricCryptoKeys.InsertOnSubmit(keyRow);
|
|
// ServerContext.DataContext.SubmitChanges();
|
|
this.keyRepository.Save(keyRow);
|
|
}
|
|
|
|
public void RemoveKey(string bucket, string handle)
|
|
{
|
|
// var match = ServerContext.DataContext.SymmetricCryptoKeys.FirstOrDefault(k => k.Bucket == bucket && k.Handle == handle);
|
|
// if (match != null)
|
|
// {
|
|
// ServerContext.DataContext.SymmetricCryptoKeys.DeleteOnSubmit(match);
|
|
// }
|
|
var key = this.keyRepository.GetBy(bucket, handle);
|
|
if (key != null)
|
|
{
|
|
this.keyRepository.Delete(key);
|
|
}
|
|
}
|
|
}
|
|
} |