diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2011-05-20 08:26:54 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2011-05-20 08:26:54 -0700 |
commit | 9aa1e046c6ccd6fa0859709419c091bf6b52f465 (patch) | |
tree | 739c8704e96cec4ee1eb9846e854d32478b856f5 /samples/OpenIdProviderWebForms/Code | |
parent | 9ba3d8e9f066132c68501fbc191acd50fba905f4 (diff) | |
download | DotNetOpenAuth-9aa1e046c6ccd6fa0859709419c091bf6b52f465.zip DotNetOpenAuth-9aa1e046c6ccd6fa0859709419c091bf6b52f465.tar.gz DotNetOpenAuth-9aa1e046c6ccd6fa0859709419c091bf6b52f465.tar.bz2 |
Providers and Relying Parties both implement a unified pair of ICryptoKeyStore and INonceStore.
OPs can configure to use encoded association handles or database-backed ones based on a simple web.config switch.
Diffstat (limited to 'samples/OpenIdProviderWebForms/Code')
3 files changed, 193 insertions, 181 deletions
diff --git a/samples/OpenIdProviderWebForms/Code/CustomStore.cs b/samples/OpenIdProviderWebForms/Code/CustomStore.cs index 7e05842..0b2aed7 100644 --- a/samples/OpenIdProviderWebForms/Code/CustomStore.cs +++ b/samples/OpenIdProviderWebForms/Code/CustomStore.cs @@ -6,8 +6,11 @@ namespace OpenIdProviderWebForms.Code { using System; + using System.Collections.Generic; using System.Data; using System.Globalization; + using DotNetOpenAuth; + using DotNetOpenAuth.Configuration; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OpenId; using DotNetOpenAuth.OpenId.Provider; @@ -25,45 +28,6 @@ namespace OpenIdProviderWebForms.Code { public class CustomStore : IProviderApplicationStore { private static CustomStoreDataSet dataSet = new CustomStoreDataSet(); - #region IProviderAssociationStore - - /// <summary> - /// Stores an association and returns a handle for it. - /// </summary> - /// <param name="secret">The association secret.</param> - /// <param name="expiresUtc">The UTC time that the association should expire.</param> - /// <param name="privateAssociation">A value indicating whether this is a private association.</param> - /// <returns> - /// The association handle that represents this association. - /// </returns> - public string Serialize(byte[] secret, DateTime expiresUtc, bool privateAssociation) { - var assocRow = dataSet.Association.NewAssociationRow(); - assocRow.IsPrivateAssociation = privateAssociation; - assocRow.Expires = expiresUtc; - assocRow.PrivateData = secret; - assocRow.Handle = OpenIdUtilities.GenerateRandomAssociationHandle(); - dataSet.Association.AddAssociationRow(assocRow); - - return assocRow.Handle; - } - - /// <summary> - /// Retrieves an association given an association handle. - /// </summary> - /// <param name="containingMessage">The OpenID message that referenced this association handle.</param> - /// <param name="isPrivateAssociation">A value indicating whether a private association is expected.</param> - /// <param name="handle">The association handle.</param> - /// <returns> - /// An association instance, or <c>null</c> if the association has expired or the signature is incorrect (which may be because the OP's symmetric key has changed). - /// </returns> - /// <exception cref="ProtocolException">Thrown if the association is not of the expected type.</exception> - public Association Deserialize(DotNetOpenAuth.Messaging.IProtocolMessage containingMessage, bool isPrivateAssociation, string handle) { - var assocRow = dataSet.Association.FindByIsPrivateAssociationHandle(isPrivateAssociation, handle); - return Association.Deserialize(assocRow.Handle, assocRow.Expires, assocRow.PrivateData); - } - - #endregion - #region INonceStore Members /// <summary> @@ -74,7 +38,7 @@ namespace OpenIdProviderWebForms.Code { /// 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="timestamp">The timestamp that together with the nonce string make it unique. + /// <param name="timestampUtc">The timestamp that together with the nonce string make it unique. /// The timestamp may also be used by the data store to clear out old nonces.</param> /// <returns> /// True if the nonce+timestamp (combination) was not previously in the database. @@ -87,7 +51,7 @@ namespace OpenIdProviderWebForms.Code { /// is retrieved or set using the /// <see cref="StandardExpirationBindingElement.MaximumMessageAge"/> property. /// </remarks> - public bool StoreNonce(string context, string nonce, DateTime timestamp) { + public bool StoreNonce(string context, string nonce, DateTime timestampUtc) { // IMPORTANT: If actually persisting to a database that can be reached from // different servers/instances of this class at once, it is vitally important // to protect against race condition attacks by one or more of these: @@ -99,30 +63,73 @@ namespace OpenIdProviderWebForms.Code { // at you in the result of a race condition somewhere in your web site UI code // and display some message to have the user try to log in again, and possibly // warn them about a replay attack. - timestamp = timestamp.ToLocalTime(); lock (this) { - if (dataSet.Nonce.FindByIssuedCodeContext(timestamp, nonce, context) != null) { + if (dataSet.Nonce.FindByIssuedUtcCodeContext(timestampUtc, nonce, context) != null) { return false; } - TimeSpan maxMessageAge = DotNetOpenAuth.Configuration.DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime; - dataSet.Nonce.AddNonceRow(context, nonce, timestamp, timestamp + maxMessageAge); + TimeSpan maxMessageAge = DotNetOpenAuthSection.Configuration.Messaging.MaximumMessageLifetime; + dataSet.Nonce.AddNonceRow(context, nonce, timestampUtc, timestampUtc + maxMessageAge); return true; } } public void ClearExpiredNonces() { - this.removeExpiredRows(dataSet.Nonce, dataSet.Nonce.ExpiresColumn.ColumnName); + this.removeExpiredRows(dataSet.Nonce, dataSet.Nonce.ExpiresUtcColumn.ColumnName); } #endregion - private void removeExpiredRows(DataTable table, string expiredColumnName) { + #region ICryptoKeyStore Members + + public CryptoKey GetKey(string bucket, string handle) { + var assocRow = dataSet.CryptoKey.FindByBucketHandle(bucket, handle); + return new CryptoKey(assocRow.Secret, assocRow.ExpiresUtc); + } + + public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) { + // properly escape the URL to prevent injection attacks. + string value = bucket.Replace("'", "''"); string filter = string.Format( CultureInfo.InvariantCulture, - "{0} < #{1}#", - expiredColumnName, - DateTime.Now); + "{0} = '{1}'", + dataSet.CryptoKey.BucketColumn.ColumnName, + value); + string sort = dataSet.CryptoKey.ExpiresUtcColumn.ColumnName + " DESC"; + DataView view = new DataView(dataSet.CryptoKey, filter, sort, DataViewRowState.CurrentRows); + if (view.Count == 0) { + yield break; + } + + foreach (CustomStoreDataSet.CryptoKeyRow row in view) { + yield return new KeyValuePair<string, CryptoKey>(row.Handle, new CryptoKey(row.Secret, row.ExpiresUtc)); + } + } + + public void StoreKey(string bucket, string handle, CryptoKey key) { + var cryptoKeyRow = dataSet.CryptoKey.NewCryptoKeyRow(); + cryptoKeyRow.Bucket = bucket; + cryptoKeyRow.Handle = handle; + cryptoKeyRow.ExpiresUtc = key.ExpiresUtc; + cryptoKeyRow.Secret = key.Key; + dataSet.CryptoKey.AddCryptoKeyRow(cryptoKeyRow); + } + + public void RemoveKey(string bucket, string handle) { + var row = dataSet.CryptoKey.FindByBucketHandle(bucket, handle); + if (row != null) { + dataSet.CryptoKey.RemoveCryptoKeyRow(row); + } + } + + #endregion + + internal void ClearExpiredSecrets() { + this.removeExpiredRows(dataSet.CryptoKey, dataSet.CryptoKey.ExpiresUtcColumn.ColumnName); + } + + private void removeExpiredRows(DataTable table, string expiredColumnName) { + string filter = string.Format(CultureInfo.InvariantCulture, "{0} < #{1}#", expiredColumnName, DateTime.UtcNow); DataView view = new DataView(table, filter, null, DataViewRowState.CurrentRows); for (int i = view.Count - 1; i >= 0; i--) { view.Delete(i); diff --git a/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.Designer.cs b/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.Designer.cs index a781018..19ac88f 100644 --- a/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.Designer.cs +++ b/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.Designer.cs @@ -24,7 +24,7 @@ namespace OpenIdProviderWebForms.Code { [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] public partial class CustomStoreDataSet : global::System.Data.DataSet { - private AssociationDataTable tableAssociation; + private CryptoKeyDataTable tableCryptoKey; private NonceDataTable tableNonce; @@ -56,8 +56,8 @@ namespace OpenIdProviderWebForms.Code { if ((this.DetermineSchemaSerializationMode(info, context) == global::System.Data.SchemaSerializationMode.IncludeSchema)) { global::System.Data.DataSet ds = new global::System.Data.DataSet(); ds.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema))); - if ((ds.Tables["Association"] != null)) { - base.Tables.Add(new AssociationDataTable(ds.Tables["Association"])); + if ((ds.Tables["CryptoKey"] != null)) { + base.Tables.Add(new CryptoKeyDataTable(ds.Tables["CryptoKey"])); } if ((ds.Tables["Nonce"] != null)) { base.Tables.Add(new NonceDataTable(ds.Tables["Nonce"])); @@ -84,9 +84,9 @@ namespace OpenIdProviderWebForms.Code { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] [global::System.ComponentModel.Browsable(false)] [global::System.ComponentModel.DesignerSerializationVisibility(global::System.ComponentModel.DesignerSerializationVisibility.Content)] - public AssociationDataTable Association { + public CryptoKeyDataTable CryptoKey { get { - return this.tableAssociation; + return this.tableCryptoKey; } } @@ -167,8 +167,8 @@ namespace OpenIdProviderWebForms.Code { this.Reset(); global::System.Data.DataSet ds = new global::System.Data.DataSet(); ds.ReadXml(reader); - if ((ds.Tables["Association"] != null)) { - base.Tables.Add(new AssociationDataTable(ds.Tables["Association"])); + if ((ds.Tables["CryptoKey"] != null)) { + base.Tables.Add(new CryptoKeyDataTable(ds.Tables["CryptoKey"])); } if ((ds.Tables["Nonce"] != null)) { base.Tables.Add(new NonceDataTable(ds.Tables["Nonce"])); @@ -206,10 +206,10 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] internal void InitVars(bool initTable) { - this.tableAssociation = ((AssociationDataTable)(base.Tables["Association"])); + this.tableCryptoKey = ((CryptoKeyDataTable)(base.Tables["CryptoKey"])); if ((initTable == true)) { - if ((this.tableAssociation != null)) { - this.tableAssociation.InitVars(); + if ((this.tableCryptoKey != null)) { + this.tableCryptoKey.InitVars(); } } this.tableNonce = ((NonceDataTable)(base.Tables["Nonce"])); @@ -228,15 +228,15 @@ namespace OpenIdProviderWebForms.Code { this.Namespace = "http://tempuri.org/CustomStoreDataSet.xsd"; this.EnforceConstraints = true; this.SchemaSerializationMode = global::System.Data.SchemaSerializationMode.IncludeSchema; - this.tableAssociation = new AssociationDataTable(); - base.Tables.Add(this.tableAssociation); + this.tableCryptoKey = new CryptoKeyDataTable(); + base.Tables.Add(this.tableCryptoKey); this.tableNonce = new NonceDataTable(); base.Tables.Add(this.tableNonce); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - private bool ShouldSerializeAssociation() { + private bool ShouldSerializeCryptoKey() { return false; } @@ -302,7 +302,7 @@ namespace OpenIdProviderWebForms.Code { } [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public delegate void AssociationRowChangeEventHandler(object sender, AssociationRowChangeEvent e); + public delegate void CryptoKeyRowChangeEventHandler(object sender, CryptoKeyRowChangeEvent e); [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] public delegate void NonceRowChangeEventHandler(object sender, NonceRowChangeEvent e); @@ -312,20 +312,20 @@ namespace OpenIdProviderWebForms.Code { ///</summary> [global::System.Serializable()] [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] - public partial class AssociationDataTable : global::System.Data.TypedTableBase<AssociationRow> { + public partial class CryptoKeyDataTable : global::System.Data.TypedTableBase<CryptoKeyRow> { - private global::System.Data.DataColumn columnIsPrivateAssociation; + private global::System.Data.DataColumn columnBucket; private global::System.Data.DataColumn columnHandle; - private global::System.Data.DataColumn columnExpires; + private global::System.Data.DataColumn columnExpiresUtc; - private global::System.Data.DataColumn columnPrivateData; + private global::System.Data.DataColumn columnSecret; [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationDataTable() { - this.TableName = "Association"; + public CryptoKeyDataTable() { + this.TableName = "CryptoKey"; this.BeginInit(); this.InitClass(); this.EndInit(); @@ -333,7 +333,7 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - internal AssociationDataTable(global::System.Data.DataTable table) { + internal CryptoKeyDataTable(global::System.Data.DataTable table) { this.TableName = table.TableName; if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { this.CaseSensitive = table.CaseSensitive; @@ -350,16 +350,16 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - protected AssociationDataTable(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + protected CryptoKeyDataTable(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : base(info, context) { this.InitVars(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public global::System.Data.DataColumn IsPrivateAssociationColumn { + public global::System.Data.DataColumn BucketColumn { get { - return this.columnIsPrivateAssociation; + return this.columnBucket; } } @@ -373,17 +373,17 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public global::System.Data.DataColumn ExpiresColumn { + public global::System.Data.DataColumn ExpiresUtcColumn { get { - return this.columnExpires; + return this.columnExpiresUtc; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public global::System.Data.DataColumn PrivateDataColumn { + public global::System.Data.DataColumn SecretColumn { get { - return this.columnPrivateData; + return this.columnSecret; } } @@ -398,56 +398,56 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRow this[int index] { + public CryptoKeyRow this[int index] { get { - return ((AssociationRow)(this.Rows[index])); + return ((CryptoKeyRow)(this.Rows[index])); } } [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public event AssociationRowChangeEventHandler AssociationRowChanging; + public event CryptoKeyRowChangeEventHandler CryptoKeyRowChanging; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public event AssociationRowChangeEventHandler AssociationRowChanged; + public event CryptoKeyRowChangeEventHandler CryptoKeyRowChanged; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public event AssociationRowChangeEventHandler AssociationRowDeleting; + public event CryptoKeyRowChangeEventHandler CryptoKeyRowDeleting; [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public event AssociationRowChangeEventHandler AssociationRowDeleted; + public event CryptoKeyRowChangeEventHandler CryptoKeyRowDeleted; [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public void AddAssociationRow(AssociationRow row) { + public void AddCryptoKeyRow(CryptoKeyRow row) { this.Rows.Add(row); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRow AddAssociationRow(bool IsPrivateAssociation, string Handle, System.DateTime Expires, byte[] PrivateData) { - AssociationRow rowAssociationRow = ((AssociationRow)(this.NewRow())); + public CryptoKeyRow AddCryptoKeyRow(string Bucket, string Handle, System.DateTime ExpiresUtc, byte[] Secret) { + CryptoKeyRow rowCryptoKeyRow = ((CryptoKeyRow)(this.NewRow())); object[] columnValuesArray = new object[] { - IsPrivateAssociation, + Bucket, Handle, - Expires, - PrivateData}; - rowAssociationRow.ItemArray = columnValuesArray; - this.Rows.Add(rowAssociationRow); - return rowAssociationRow; + ExpiresUtc, + Secret}; + rowCryptoKeyRow.ItemArray = columnValuesArray; + this.Rows.Add(rowCryptoKeyRow); + return rowCryptoKeyRow; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRow FindByIsPrivateAssociationHandle(bool IsPrivateAssociation, string Handle) { - return ((AssociationRow)(this.Rows.Find(new object[] { - IsPrivateAssociation, + public CryptoKeyRow FindByBucketHandle(string Bucket, string Handle) { + return ((CryptoKeyRow)(this.Rows.Find(new object[] { + Bucket, Handle}))); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] public override global::System.Data.DataTable Clone() { - AssociationDataTable cln = ((AssociationDataTable)(base.Clone())); + CryptoKeyDataTable cln = ((CryptoKeyDataTable)(base.Clone())); cln.InitVars(); return cln; } @@ -455,62 +455,65 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override global::System.Data.DataTable CreateInstance() { - return new AssociationDataTable(); + return new CryptoKeyDataTable(); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] internal void InitVars() { - this.columnIsPrivateAssociation = base.Columns["IsPrivateAssociation"]; + this.columnBucket = base.Columns["Bucket"]; this.columnHandle = base.Columns["Handle"]; - this.columnExpires = base.Columns["Expires"]; - this.columnPrivateData = base.Columns["PrivateData"]; + this.columnExpiresUtc = base.Columns["ExpiresUtc"]; + this.columnSecret = base.Columns["Secret"]; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] private void InitClass() { - this.columnIsPrivateAssociation = new global::System.Data.DataColumn("IsPrivateAssociation", typeof(bool), null, global::System.Data.MappingType.Element); - base.Columns.Add(this.columnIsPrivateAssociation); + this.columnBucket = new global::System.Data.DataColumn("Bucket", typeof(string), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnBucket); this.columnHandle = new global::System.Data.DataColumn("Handle", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnHandle); - this.columnExpires = new global::System.Data.DataColumn("Expires", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); - base.Columns.Add(this.columnExpires); - this.columnPrivateData = new global::System.Data.DataColumn("PrivateData", typeof(byte[]), null, global::System.Data.MappingType.Element); - base.Columns.Add(this.columnPrivateData); + this.columnExpiresUtc = new global::System.Data.DataColumn("ExpiresUtc", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnExpiresUtc); + this.columnSecret = new global::System.Data.DataColumn("Secret", typeof(byte[]), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnSecret); this.Constraints.Add(new global::System.Data.UniqueConstraint("PrimaryKey", new global::System.Data.DataColumn[] { - this.columnIsPrivateAssociation, + this.columnBucket, this.columnHandle}, true)); - this.columnIsPrivateAssociation.AllowDBNull = false; + this.columnBucket.AllowDBNull = false; + this.columnBucket.ReadOnly = true; this.columnHandle.AllowDBNull = false; - this.columnExpires.AllowDBNull = false; - this.columnPrivateData.AllowDBNull = false; + this.columnHandle.ReadOnly = true; + this.columnExpiresUtc.AllowDBNull = false; + this.columnExpiresUtc.DateTimeMode = global::System.Data.DataSetDateTime.Utc; + this.columnSecret.AllowDBNull = false; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRow NewAssociationRow() { - return ((AssociationRow)(this.NewRow())); + public CryptoKeyRow NewCryptoKeyRow() { + return ((CryptoKeyRow)(this.NewRow())); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override global::System.Data.DataRow NewRowFromBuilder(global::System.Data.DataRowBuilder builder) { - return new AssociationRow(builder); + return new CryptoKeyRow(builder); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override global::System.Type GetRowType() { - return typeof(AssociationRow); + return typeof(CryptoKeyRow); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override void OnRowChanged(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanged(e); - if ((this.AssociationRowChanged != null)) { - this.AssociationRowChanged(this, new AssociationRowChangeEvent(((AssociationRow)(e.Row)), e.Action)); + if ((this.CryptoKeyRowChanged != null)) { + this.CryptoKeyRowChanged(this, new CryptoKeyRowChangeEvent(((CryptoKeyRow)(e.Row)), e.Action)); } } @@ -518,8 +521,8 @@ namespace OpenIdProviderWebForms.Code { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override void OnRowChanging(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanging(e); - if ((this.AssociationRowChanging != null)) { - this.AssociationRowChanging(this, new AssociationRowChangeEvent(((AssociationRow)(e.Row)), e.Action)); + if ((this.CryptoKeyRowChanging != null)) { + this.CryptoKeyRowChanging(this, new CryptoKeyRowChangeEvent(((CryptoKeyRow)(e.Row)), e.Action)); } } @@ -527,8 +530,8 @@ namespace OpenIdProviderWebForms.Code { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override void OnRowDeleted(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleted(e); - if ((this.AssociationRowDeleted != null)) { - this.AssociationRowDeleted(this, new AssociationRowChangeEvent(((AssociationRow)(e.Row)), e.Action)); + if ((this.CryptoKeyRowDeleted != null)) { + this.CryptoKeyRowDeleted(this, new CryptoKeyRowChangeEvent(((CryptoKeyRow)(e.Row)), e.Action)); } } @@ -536,14 +539,14 @@ namespace OpenIdProviderWebForms.Code { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] protected override void OnRowDeleting(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleting(e); - if ((this.AssociationRowDeleting != null)) { - this.AssociationRowDeleting(this, new AssociationRowChangeEvent(((AssociationRow)(e.Row)), e.Action)); + if ((this.CryptoKeyRowDeleting != null)) { + this.CryptoKeyRowDeleting(this, new CryptoKeyRowChangeEvent(((CryptoKeyRow)(e.Row)), e.Action)); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public void RemoveAssociationRow(AssociationRow row) { + public void RemoveCryptoKeyRow(CryptoKeyRow row) { this.Rows.Remove(row); } @@ -570,7 +573,7 @@ namespace OpenIdProviderWebForms.Code { type.Attributes.Add(attribute1); global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute2.Name = "tableTypeName"; - attribute2.FixedValue = "AssociationDataTable"; + attribute2.FixedValue = "CryptoKeyDataTable"; type.Attributes.Add(attribute2); type.Particle = sequence; global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); @@ -622,9 +625,9 @@ namespace OpenIdProviderWebForms.Code { private global::System.Data.DataColumn columnCode; - private global::System.Data.DataColumn columnIssued; + private global::System.Data.DataColumn columnIssuedUtc; - private global::System.Data.DataColumn columnExpires; + private global::System.Data.DataColumn columnExpiresUtc; [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] @@ -677,17 +680,17 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public global::System.Data.DataColumn IssuedColumn { + public global::System.Data.DataColumn IssuedUtcColumn { get { - return this.columnIssued; + return this.columnIssuedUtc; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public global::System.Data.DataColumn ExpiresColumn { + public global::System.Data.DataColumn ExpiresUtcColumn { get { - return this.columnExpires; + return this.columnExpiresUtc; } } @@ -728,13 +731,13 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public NonceRow AddNonceRow(string Context, string Code, System.DateTime Issued, System.DateTime Expires) { + public NonceRow AddNonceRow(string Context, string Code, System.DateTime IssuedUtc, System.DateTime ExpiresUtc) { NonceRow rowNonceRow = ((NonceRow)(this.NewRow())); object[] columnValuesArray = new object[] { Context, Code, - Issued, - Expires}; + IssuedUtc, + ExpiresUtc}; rowNonceRow.ItemArray = columnValuesArray; this.Rows.Add(rowNonceRow); return rowNonceRow; @@ -742,9 +745,9 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public NonceRow FindByIssuedCodeContext(System.DateTime Issued, string Code, string Context) { + public NonceRow FindByIssuedUtcCodeContext(System.DateTime IssuedUtc, string Code, string Context) { return ((NonceRow)(this.Rows.Find(new object[] { - Issued, + IssuedUtc, Code, Context}))); } @@ -768,8 +771,8 @@ namespace OpenIdProviderWebForms.Code { internal void InitVars() { this.columnContext = base.Columns["Context"]; this.columnCode = base.Columns["Code"]; - this.columnIssued = base.Columns["Issued"]; - this.columnExpires = base.Columns["Expires"]; + this.columnIssuedUtc = base.Columns["IssuedUtc"]; + this.columnExpiresUtc = base.Columns["ExpiresUtc"]; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] @@ -779,18 +782,20 @@ namespace OpenIdProviderWebForms.Code { base.Columns.Add(this.columnContext); this.columnCode = new global::System.Data.DataColumn("Code", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnCode); - this.columnIssued = new global::System.Data.DataColumn("Issued", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); - base.Columns.Add(this.columnIssued); - this.columnExpires = new global::System.Data.DataColumn("Expires", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); - base.Columns.Add(this.columnExpires); + this.columnIssuedUtc = new global::System.Data.DataColumn("IssuedUtc", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnIssuedUtc); + this.columnExpiresUtc = new global::System.Data.DataColumn("ExpiresUtc", typeof(global::System.DateTime), null, global::System.Data.MappingType.Element); + base.Columns.Add(this.columnExpiresUtc); this.Constraints.Add(new global::System.Data.UniqueConstraint("Constraint1", new global::System.Data.DataColumn[] { - this.columnIssued, + this.columnIssuedUtc, this.columnCode, this.columnContext}, true)); this.columnContext.AllowDBNull = false; this.columnCode.AllowDBNull = false; - this.columnIssued.AllowDBNull = false; - this.columnExpires.AllowDBNull = false; + this.columnIssuedUtc.AllowDBNull = false; + this.columnIssuedUtc.DateTimeMode = global::System.Data.DataSetDateTime.Utc; + this.columnExpiresUtc.AllowDBNull = false; + this.columnExpiresUtc.DateTimeMode = global::System.Data.DataSetDateTime.Utc; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] @@ -920,25 +925,25 @@ namespace OpenIdProviderWebForms.Code { /// <summary> ///Represents strongly named DataRow class. ///</summary> - public partial class AssociationRow : global::System.Data.DataRow { + public partial class CryptoKeyRow : global::System.Data.DataRow { - private AssociationDataTable tableAssociation; + private CryptoKeyDataTable tableCryptoKey; [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - internal AssociationRow(global::System.Data.DataRowBuilder rb) : + internal CryptoKeyRow(global::System.Data.DataRowBuilder rb) : base(rb) { - this.tableAssociation = ((AssociationDataTable)(this.Table)); + this.tableCryptoKey = ((CryptoKeyDataTable)(this.Table)); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public bool IsPrivateAssociation { + public string Bucket { get { - return ((bool)(this[this.tableAssociation.IsPrivateAssociationColumn])); + return ((string)(this[this.tableCryptoKey.BucketColumn])); } set { - this[this.tableAssociation.IsPrivateAssociationColumn] = value; + this[this.tableCryptoKey.BucketColumn] = value; } } @@ -946,32 +951,32 @@ namespace OpenIdProviderWebForms.Code { [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] public string Handle { get { - return ((string)(this[this.tableAssociation.HandleColumn])); + return ((string)(this[this.tableCryptoKey.HandleColumn])); } set { - this[this.tableAssociation.HandleColumn] = value; + this[this.tableCryptoKey.HandleColumn] = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public System.DateTime Expires { + public System.DateTime ExpiresUtc { get { - return ((global::System.DateTime)(this[this.tableAssociation.ExpiresColumn])); + return ((global::System.DateTime)(this[this.tableCryptoKey.ExpiresUtcColumn])); } set { - this[this.tableAssociation.ExpiresColumn] = value; + this[this.tableCryptoKey.ExpiresUtcColumn] = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public byte[] PrivateData { + public byte[] Secret { get { - return ((byte[])(this[this.tableAssociation.PrivateDataColumn])); + return ((byte[])(this[this.tableCryptoKey.SecretColumn])); } set { - this[this.tableAssociation.PrivateDataColumn] = value; + this[this.tableCryptoKey.SecretColumn] = value; } } } @@ -1014,23 +1019,23 @@ namespace OpenIdProviderWebForms.Code { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public System.DateTime Issued { + public System.DateTime IssuedUtc { get { - return ((global::System.DateTime)(this[this.tableNonce.IssuedColumn])); + return ((global::System.DateTime)(this[this.tableNonce.IssuedUtcColumn])); } set { - this[this.tableNonce.IssuedColumn] = value; + this[this.tableNonce.IssuedUtcColumn] = value; } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public System.DateTime Expires { + public System.DateTime ExpiresUtc { get { - return ((global::System.DateTime)(this[this.tableNonce.ExpiresColumn])); + return ((global::System.DateTime)(this[this.tableNonce.ExpiresUtcColumn])); } set { - this[this.tableNonce.ExpiresColumn] = value; + this[this.tableNonce.ExpiresUtcColumn] = value; } } } @@ -1039,22 +1044,22 @@ namespace OpenIdProviderWebForms.Code { ///Row event argument class ///</summary> [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public class AssociationRowChangeEvent : global::System.EventArgs { + public class CryptoKeyRowChangeEvent : global::System.EventArgs { - private AssociationRow eventRow; + private CryptoKeyRow eventRow; private global::System.Data.DataRowAction eventAction; [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRowChangeEvent(AssociationRow row, global::System.Data.DataRowAction action) { + public CryptoKeyRowChangeEvent(CryptoKeyRow row, global::System.Data.DataRowAction action) { this.eventRow = row; this.eventAction = action; } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "4.0.0.0")] - public AssociationRow Row { + public CryptoKeyRow Row { get { return this.eventRow; } diff --git a/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.xsd b/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.xsd index de0d935..cf3b62e 100644 --- a/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.xsd +++ b/samples/OpenIdProviderWebForms/Code/CustomStoreDataSet.xsd @@ -12,36 +12,36 @@ <xs:element name="CustomStoreDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:EnableTableAdapterManager="true" msprop:Generator_DataSetName="CustomStoreDataSet" msprop:Generator_UserDSName="CustomStoreDataSet"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> - <xs:element name="Association" msprop:Generator_UserTableName="Association" msprop:Generator_RowEvArgName="AssociationRowChangeEvent" msprop:Generator_TableVarName="tableAssociation" msprop:Generator_TablePropName="Association" msprop:Generator_RowDeletingName="AssociationRowDeleting" msprop:Generator_RowChangingName="AssociationRowChanging" msprop:Generator_RowDeletedName="AssociationRowDeleted" msprop:Generator_TableClassName="AssociationDataTable" msprop:Generator_RowChangedName="AssociationRowChanged" msprop:Generator_RowEvHandlerName="AssociationRowChangeEventHandler" msprop:Generator_RowClassName="AssociationRow"> + <xs:element name="CryptoKey" msprop:Generator_UserTableName="CryptoKey" msprop:Generator_RowEvArgName="CryptoKeyRowChangeEvent" msprop:Generator_TableVarName="tableCryptoKey" msprop:Generator_TablePropName="CryptoKey" msprop:Generator_RowDeletingName="CryptoKeyRowDeleting" msprop:Generator_RowChangingName="CryptoKeyRowChanging" msprop:Generator_RowDeletedName="CryptoKeyRowDeleted" msprop:Generator_RowEvHandlerName="CryptoKeyRowChangeEventHandler" msprop:Generator_RowChangedName="CryptoKeyRowChanged" msprop:Generator_TableClassName="CryptoKeyDataTable" msprop:Generator_RowClassName="CryptoKeyRow"> <xs:complexType> <xs:sequence> - <xs:element name="IsPrivateAssociation" msprop:Generator_ColumnVarNameInTable="columnIsPrivateAssociation" msprop:Generator_ColumnPropNameInRow="IsPrivateAssociation" msprop:Generator_ColumnPropNameInTable="IsPrivateAssociationColumn" msprop:Generator_UserColumnName="IsPrivateAssociation" type="xs:boolean" /> - <xs:element name="Handle" msprop:Generator_ColumnVarNameInTable="columnHandle" msprop:Generator_ColumnPropNameInRow="Handle" msprop:Generator_ColumnPropNameInTable="HandleColumn" msprop:Generator_UserColumnName="Handle" type="xs:string" /> - <xs:element name="Expires" msprop:Generator_ColumnVarNameInTable="columnExpires" msprop:Generator_ColumnPropNameInRow="Expires" msprop:Generator_ColumnPropNameInTable="ExpiresColumn" msprop:Generator_UserColumnName="Expires" type="xs:dateTime" /> - <xs:element name="PrivateData" msprop:Generator_ColumnVarNameInTable="columnPrivateData" msprop:Generator_ColumnPropNameInRow="PrivateData" msprop:Generator_ColumnPropNameInTable="PrivateDataColumn" msprop:Generator_UserColumnName="PrivateData" type="xs:base64Binary" /> + <xs:element name="Bucket" msdata:ReadOnly="true" msprop:Generator_ColumnVarNameInTable="columnBucket" msprop:Generator_ColumnPropNameInRow="Bucket" msprop:Generator_ColumnPropNameInTable="BucketColumn" msprop:Generator_UserColumnName="Bucket" type="xs:string" /> + <xs:element name="Handle" msdata:ReadOnly="true" msprop:Generator_ColumnVarNameInTable="columnHandle" msprop:Generator_ColumnPropNameInRow="Handle" msprop:Generator_ColumnPropNameInTable="HandleColumn" msprop:Generator_UserColumnName="Handle" type="xs:string" /> + <xs:element name="ExpiresUtc" msdata:DateTimeMode="Utc" msprop:Generator_ColumnVarNameInTable="columnExpiresUtc" msprop:Generator_ColumnPropNameInRow="ExpiresUtc" msprop:Generator_ColumnPropNameInTable="ExpiresUtcColumn" msprop:Generator_UserColumnName="ExpiresUtc" type="xs:dateTime" /> + <xs:element name="Secret" msprop:Generator_ColumnVarNameInTable="columnSecret" msprop:Generator_ColumnPropNameInRow="Secret" msprop:Generator_ColumnPropNameInTable="SecretColumn" msprop:Generator_UserColumnName="Secret" type="xs:base64Binary" /> </xs:sequence> </xs:complexType> </xs:element> - <xs:element name="Nonce" msprop:Generator_UserTableName="Nonce" msprop:Generator_RowEvArgName="NonceRowChangeEvent" msprop:Generator_TableVarName="tableNonce" msprop:Generator_TablePropName="Nonce" msprop:Generator_RowDeletingName="NonceRowDeleting" msprop:Generator_RowChangingName="NonceRowChanging" msprop:Generator_RowDeletedName="NonceRowDeleted" msprop:Generator_TableClassName="NonceDataTable" msprop:Generator_RowChangedName="NonceRowChanged" msprop:Generator_RowEvHandlerName="NonceRowChangeEventHandler" msprop:Generator_RowClassName="NonceRow"> + <xs:element name="Nonce" msprop:Generator_UserTableName="Nonce" msprop:Generator_RowEvArgName="NonceRowChangeEvent" msprop:Generator_TableVarName="tableNonce" msprop:Generator_TablePropName="Nonce" msprop:Generator_RowDeletingName="NonceRowDeleting" msprop:Generator_RowChangingName="NonceRowChanging" msprop:Generator_RowDeletedName="NonceRowDeleted" msprop:Generator_RowEvHandlerName="NonceRowChangeEventHandler" msprop:Generator_RowChangedName="NonceRowChanged" msprop:Generator_TableClassName="NonceDataTable" msprop:Generator_RowClassName="NonceRow"> <xs:complexType> <xs:sequence> <xs:element name="Context" msprop:Generator_ColumnVarNameInTable="columnContext" msprop:Generator_ColumnPropNameInRow="Context" msprop:Generator_ColumnPropNameInTable="ContextColumn" msprop:Generator_UserColumnName="Context" type="xs:string" /> <xs:element name="Code" msprop:Generator_ColumnVarNameInTable="columnCode" msprop:Generator_ColumnPropNameInRow="Code" msprop:Generator_ColumnPropNameInTable="CodeColumn" msprop:Generator_UserColumnName="Code" type="xs:string" /> - <xs:element name="Issued" msprop:Generator_ColumnVarNameInTable="columnIssued" msprop:Generator_ColumnPropNameInRow="Issued" msprop:Generator_ColumnPropNameInTable="IssuedColumn" msprop:Generator_UserColumnName="Issued" type="xs:dateTime" /> - <xs:element name="Expires" msprop:Generator_ColumnVarNameInTable="columnExpires" msprop:Generator_ColumnPropNameInRow="Expires" msprop:Generator_ColumnPropNameInTable="ExpiresColumn" msprop:Generator_UserColumnName="Expires" type="xs:dateTime" /> + <xs:element name="IssuedUtc" msdata:DateTimeMode="Utc" msprop:Generator_ColumnVarNameInTable="columnIssuedUtc" msprop:Generator_ColumnPropNameInRow="IssuedUtc" msprop:Generator_ColumnPropNameInTable="IssuedUtcColumn" msprop:Generator_UserColumnName="IssuedUtc" type="xs:dateTime" /> + <xs:element name="ExpiresUtc" msdata:DateTimeMode="Utc" msprop:Generator_ColumnVarNameInTable="columnExpiresUtc" msprop:Generator_ColumnPropNameInRow="ExpiresUtc" msprop:Generator_ColumnPropNameInTable="ExpiresUtcColumn" msprop:Generator_UserColumnName="ExpiresUtc" type="xs:dateTime" /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> <xs:unique name="PrimaryKey" msdata:PrimaryKey="true"> - <xs:selector xpath=".//mstns:Association" /> - <xs:field xpath="mstns:IsPrivateAssociation" /> + <xs:selector xpath=".//mstns:CryptoKey" /> + <xs:field xpath="mstns:Bucket" /> <xs:field xpath="mstns:Handle" /> </xs:unique> <xs:unique name="Constraint1" msdata:PrimaryKey="true"> <xs:selector xpath=".//mstns:Nonce" /> - <xs:field xpath="mstns:Issued" /> + <xs:field xpath="mstns:IssuedUtc" /> <xs:field xpath="mstns:Code" /> <xs:field xpath="mstns:Context" /> </xs:unique> |