diff options
Diffstat (limited to 'samples/OAuthAuthorizationServer/Code')
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/DataClasses.dbml | 8 | ||||
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/DataClasses.dbml.layout | 6 | ||||
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/DataClasses.designer.cs | 147 | ||||
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/DatabaseKeyNonceStore.cs (renamed from samples/OAuthAuthorizationServer/Code/DatabaseNonceStore.cs) | 46 | ||||
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs | 35 | ||||
-rw-r--r-- | samples/OAuthAuthorizationServer/Code/Utilities.cs | 21 |
6 files changed, 233 insertions, 30 deletions
diff --git a/samples/OAuthAuthorizationServer/Code/DataClasses.dbml b/samples/OAuthAuthorizationServer/Code/DataClasses.dbml index 33e6eda..0ef987d 100644 --- a/samples/OAuthAuthorizationServer/Code/DataClasses.dbml +++ b/samples/OAuthAuthorizationServer/Code/DataClasses.dbml @@ -37,4 +37,12 @@ <Column Name="Timestamp" Type="System.DateTime" IsPrimaryKey="true" CanBeNull="false" /> </Type> </Table> + <Table Name="" Member="SymmetricCryptoKeys"> + <Type Name="SymmetricCryptoKey"> + <Column Name="Bucket" Type="System.String" IsPrimaryKey="true" CanBeNull="false" UpdateCheck="Never" /> + <Column Name="Handle" Type="System.String" IsPrimaryKey="true" CanBeNull="false" UpdateCheck="Never" /> + <Column Name="ExpiresUtc" Type="System.DateTime" CanBeNull="false" UpdateCheck="Never" /> + <Column Name="Secret" Type="System.Byte[]" CanBeNull="false" UpdateCheck="Never" /> + </Type> + </Table> </Database>
\ No newline at end of file diff --git a/samples/OAuthAuthorizationServer/Code/DataClasses.dbml.layout b/samples/OAuthAuthorizationServer/Code/DataClasses.dbml.layout index e2982ce..f4de725 100644 --- a/samples/OAuthAuthorizationServer/Code/DataClasses.dbml.layout +++ b/samples/OAuthAuthorizationServer/Code/DataClasses.dbml.layout @@ -40,5 +40,11 @@ <classShapeMoniker Id="895ebbc8-8352-4c04-9e53-b8e6c8302d36" /> </nodes> </associationConnector> + <classShape Id="93df6fa9-cc66-44a9-8885-960b1e670dd7" absoluteBounds="4.125, 6.25, 2, 1.5785953776041666"> + <DataClassMoniker Name="/DataClassesDataContext/SymmetricCryptoKey" /> + <nestedChildShapes> + <elementListCompartment Id="0b486eb8-31a4-4f11-b58f-09540c56319b" absoluteBounds="4.14, 6.71, 1.9700000000000002, 1.0185953776041665" name="DataPropertiesCompartment" titleTextColor="Black" itemTextColor="Black" /> + </nestedChildShapes> + </classShape> </nestedChildShapes> </ordesignerObjectsDiagram>
\ No newline at end of file diff --git a/samples/OAuthAuthorizationServer/Code/DataClasses.designer.cs b/samples/OAuthAuthorizationServer/Code/DataClasses.designer.cs index b6d070d..c8d1b19 100644 --- a/samples/OAuthAuthorizationServer/Code/DataClasses.designer.cs +++ b/samples/OAuthAuthorizationServer/Code/DataClasses.designer.cs @@ -2,7 +2,7 @@ //------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. -// Runtime Version:4.0.30319.1 +// Runtime Version:4.0.30319.225 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -42,6 +42,9 @@ namespace OAuthAuthorizationServer.Code partial void InsertNonce(Nonce instance); partial void UpdateNonce(Nonce instance); partial void DeleteNonce(Nonce instance); + partial void InsertSymmetricCryptoKey(SymmetricCryptoKey instance); + partial void UpdateSymmetricCryptoKey(SymmetricCryptoKey instance); + partial void DeleteSymmetricCryptoKey(SymmetricCryptoKey instance); #endregion public DataClassesDataContext() : @@ -105,6 +108,14 @@ namespace OAuthAuthorizationServer.Code return this.GetTable<Nonce>(); } } + + public System.Data.Linq.Table<SymmetricCryptoKey> SymmetricCryptoKeys + { + get + { + return this.GetTable<SymmetricCryptoKey>(); + } + } } [global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.[User]")] @@ -804,5 +815,139 @@ namespace OAuthAuthorizationServer.Code } } } + + [global::System.Data.Linq.Mapping.TableAttribute(Name="")] + public partial class SymmetricCryptoKey : INotifyPropertyChanging, INotifyPropertyChanged + { + + private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); + + private string _Bucket; + + private string _Handle; + + private System.DateTime _ExpiresUtc; + + private byte[] _Secret; + + #region Extensibility Method Definitions + partial void OnLoaded(); + partial void OnValidate(System.Data.Linq.ChangeAction action); + partial void OnCreated(); + partial void OnBucketChanging(string value); + partial void OnBucketChanged(); + partial void OnHandleChanging(string value); + partial void OnHandleChanged(); + partial void OnExpiresUtcChanging(System.DateTime value); + partial void OnExpiresUtcChanged(); + partial void OnSecretChanging(byte[] value); + partial void OnSecretChanged(); + #endregion + + public SymmetricCryptoKey() + { + OnCreated(); + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Bucket", CanBeNull=false, IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)] + public string Bucket + { + get + { + return this._Bucket; + } + set + { + if ((this._Bucket != value)) + { + this.OnBucketChanging(value); + this.SendPropertyChanging(); + this._Bucket = value; + this.SendPropertyChanged("Bucket"); + this.OnBucketChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Handle", CanBeNull=false, IsPrimaryKey=true, UpdateCheck=UpdateCheck.Never)] + public string Handle + { + get + { + return this._Handle; + } + set + { + if ((this._Handle != value)) + { + this.OnHandleChanging(value); + this.SendPropertyChanging(); + this._Handle = value; + this.SendPropertyChanged("Handle"); + this.OnHandleChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_ExpiresUtc", UpdateCheck=UpdateCheck.Never)] + public System.DateTime ExpiresUtc + { + get + { + return this._ExpiresUtc; + } + set + { + if ((this._ExpiresUtc != value)) + { + this.OnExpiresUtcChanging(value); + this.SendPropertyChanging(); + this._ExpiresUtc = value; + this.SendPropertyChanged("ExpiresUtc"); + this.OnExpiresUtcChanged(); + } + } + } + + [global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Secret", CanBeNull=false, UpdateCheck=UpdateCheck.Never)] + public byte[] Secret + { + get + { + return this._Secret; + } + set + { + if ((this._Secret != value)) + { + this.OnSecretChanging(value); + this.SendPropertyChanging(); + this._Secret = value; + this.SendPropertyChanged("Secret"); + this.OnSecretChanged(); + } + } + } + + public event PropertyChangingEventHandler PropertyChanging; + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void SendPropertyChanging() + { + if ((this.PropertyChanging != null)) + { + this.PropertyChanging(this, emptyChangingEventArgs); + } + } + + protected virtual void SendPropertyChanged(String propertyName) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } } #pragma warning restore 1591 diff --git a/samples/OAuthAuthorizationServer/Code/DatabaseNonceStore.cs b/samples/OAuthAuthorizationServer/Code/DatabaseKeyNonceStore.cs index a0ce19e..765696e 100644 --- a/samples/OAuthAuthorizationServer/Code/DatabaseNonceStore.cs +++ b/samples/OAuthAuthorizationServer/Code/DatabaseKeyNonceStore.cs @@ -1,16 +1,18 @@ namespace OAuthAuthorizationServer.Code { using System; + using System.Collections.Generic; using System.Data.SqlClient; + using System.Linq; using DotNetOpenAuth.Messaging.Bindings; /// <summary> /// A database-persisted nonce store. /// </summary> - public class DatabaseNonceStore : INonceStore { + public class DatabaseKeyNonceStore : INonceStore, ICryptoKeyStore { /// <summary> - /// Initializes a new instance of the <see cref="DatabaseNonceStore"/> class. + /// Initializes a new instance of the <see cref="DatabaseKeyNonceStore"/> class. /// </summary> - public DatabaseNonceStore() { + public DatabaseKeyNonceStore() { } #region INonceStore Members @@ -51,5 +53,43 @@ } #endregion + + #region ICryptoKeyStore Members + + public CryptoKey GetKey(string bucket, string handle) { + // It is critical that this lookup be case-sensitive, which can only be configured at the database. + var matches = from key in MvcApplication.DataContext.SymmetricCryptoKeys + where key.Bucket == bucket && key.Handle == handle + select new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()); + + return matches.FirstOrDefault(); + } + + public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) { + return from key in MvcApplication.DataContext.SymmetricCryptoKeys + orderby key.ExpiresUtc descending + select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc())); + } + + public void StoreKey(string bucket, string handle, CryptoKey key) { + var keyRow = new SymmetricCryptoKey() { + Bucket = bucket, + Handle = handle, + Secret = key.Key, + ExpiresUtc = key.ExpiresUtc, + }; + + MvcApplication.DataContext.SymmetricCryptoKeys.InsertOnSubmit(keyRow); + MvcApplication.DataContext.SubmitChanges(); + } + + public void RemoveKey(string bucket, string handle) { + var match = MvcApplication.DataContext.SymmetricCryptoKeys.FirstOrDefault(k => k.Bucket == bucket && k.Handle == handle); + if (match != null) { + MvcApplication.DataContext.SymmetricCryptoKeys.DeleteOnSubmit(match); + } + } + + #endregion } }
\ No newline at end of file diff --git a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs index 3be70f0..90f99f8 100644 --- a/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs +++ b/samples/OAuthAuthorizationServer/Code/OAuth2AuthorizationServer.cs @@ -13,18 +13,14 @@ internal class OAuth2AuthorizationServer : IAuthorizationServer { private static readonly RSAParameters AsymmetricTokenSigningPrivateKey = CreateRSAKey(); - private static readonly byte[] secret = CreateSecret(); - - private readonly INonceStore nonceStore = new DatabaseNonceStore(); - #region Implementation of IAuthorizationServer - public byte[] Secret { - get { return secret; } + public ICryptoKeyStore CryptoKeyStore { + get { return MvcApplication.KeyNonceStore; } } public INonceStore VerificationCodeNonceStore { - get { return this.nonceStore; } + get { return MvcApplication.KeyNonceStore; } } public RSACryptoServiceProvider CreateAccessTokenSigningCryptoServiceProvider() { @@ -75,19 +71,6 @@ } /// <summary> - /// Creates a symmetric secret used to sign and encrypt authorization server refresh tokens. - /// </summary> - /// <returns>A cryptographically strong symmetric key.</returns> - private static byte[] CreateSecret() { - // TODO: Replace this sample code with real code. - // For this sample, we just generate random secrets. - RandomNumberGenerator crypto = new RNGCryptoServiceProvider(); - var secret = new byte[32]; // 256-bit symmetric key to protect all protected resources. - crypto.GetBytes(secret); - return secret; - } - - /// <summary> /// Creates the RSA key used by all the crypto service provider instances we create. /// </summary> /// <returns>RSA data that includes the private key.</returns> @@ -126,12 +109,12 @@ private bool IsAuthorizationValid(HashSet<string> requestedScopes, string clientIdentifier, DateTime issuedUtc, string username) { var grantedScopeStrings = from auth in MvcApplication.DataContext.ClientAuthorizations - where - auth.Client.ClientIdentifier == clientIdentifier && - auth.CreatedOnUtc <= issuedUtc && - (!auth.ExpirationDateUtc.HasValue || auth.ExpirationDateUtc.Value >= DateTime.UtcNow) && - auth.User.OpenIDClaimedIdentifier == username - select auth.Scope; + where + auth.Client.ClientIdentifier == clientIdentifier && + auth.CreatedOnUtc <= issuedUtc && + (!auth.ExpirationDateUtc.HasValue || auth.ExpirationDateUtc.Value >= DateTime.UtcNow) && + auth.User.OpenIDClaimedIdentifier == username + select auth.Scope; if (!grantedScopeStrings.Any()) { // No granted authorizations prior to the issuance of this token, so it must have been revoked. diff --git a/samples/OAuthAuthorizationServer/Code/Utilities.cs b/samples/OAuthAuthorizationServer/Code/Utilities.cs new file mode 100644 index 0000000..c9109bd --- /dev/null +++ b/samples/OAuthAuthorizationServer/Code/Utilities.cs @@ -0,0 +1,21 @@ +namespace OAuthAuthorizationServer.Code { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + internal static class Utilities { + /// <summary> + /// Ensures that local times are converted to UTC times. Unspecified kinds are recast to UTC with no conversion. + /// </summary> + /// <param name="value">The date-time to convert.</param> + /// <returns>The date-time in UTC time.</returns> + internal static DateTime AsUtc(this DateTime value) { + if (value.Kind == DateTimeKind.Unspecified) { + return new DateTime(value.Ticks, DateTimeKind.Utc); + } + + return value.ToUniversalTime(); + } + } +}
\ No newline at end of file |