Consent Receipt

From MgmtWiki
Revision as of 14:04, 6 June 2018 by Tom (talk | contribs) (XML output)

Jump to: navigation, search

Full Title or Meme

Consent Receipt generated by an IDESG compliant Identifier Provider

Context

The current design of a Consent receipt is based on the theory of a transaction between a pii data controller and a pii data principle.

A Consent Receipt is defined as a "record of a consent interaction (or consent record summary linked to the record of consent)" ... "in accordance with an agreed set of terms."

A Privacy Policy is a "statement/policy and applicable terms of use in effect when the consent was obtained, and the receipt was issued".

In the context of an IDESG identifier provider best practice it was based on a state at the IdP of a user immediately after a user initiated profile update. Note that user here means whatever sort of entity has the identifier shown as "user name". It cannot be inferred that the identified user has any rights, or indeed any legal standing, under any regulation, as that would be an unwarranted privacy exposure of its own.

It might be useful for the consent receipt to carry an indication of the context (aka receipt type) at its generation.

Current draft of the Spec

Draft on which this implementation was based is listed below. In theory practice is the same as theory, in practice it is not.

Current draft of Kantara Initiative Technical Specification Recommendation, Consent Receipt Specification Version:1.1.0 DRAFT 8 Date:2018-02-20

Warning: this document is based the 1980 OECD Guidelines on the Protection of Privacy and Transborder Flows of Personal Data [OECD] focusing on consent using the ISO 29100 [ISO 29100:2011] lexicon, which means that the terms are stilted and do not reflect current usages.

Implementation on Microsoft ASP.NET Core 2 Web Site

Consent receipts were added to the IDESG best practice web site which is accessible at this site.

This site is an IdP. Several points were noted for discussion:

  1. The Consent Receipt spec is not well adapted to IdPs. It seems to focus on RPs.
  2. Some data requirements, like service address and phone number might be fine for large orgs, but if applied to small ones there will be some that just avoid the issue and hope no one notices.
  3. Termination seems like it addresses complete dissolution between the site and the user. But that is seldom good for the user if paid services or merchandise is involved. Perhaps Freeze would be a better term?
  4. My investigation leads me to believe that fields like purpose are variable between data elements. If fact it seems like the GDPR requires this as the point is made (at least in the CA initiative) that some data may be part of a core function and other data voluntary. I think that the CR should enumerate the data retained and the purpose for each item.
  5. The assumption seems to be that piiPrinciple is a sentient carbon-based life form. This is not necessarily true. In the case of a pseudonym; it is PII to even know if the principle (subject) is a carbon-based life form.

Warning that this is a work in process and it works at varying levels of support as changes continue to be added to the site.

Json classes

 // ConsentReceipt helper clases (c) 2018 tom jones
 {
   public class ConsentReceipt
   {
       [JsonObject]
       public class ProfileResponse
       {
           [JsonProperty]
           public string version { get; set; }
           [JsonProperty]
           public string jurisdiction { get; set; }
           [JsonProperty]
           public string consentTimestamp { get; set; }
           [JsonProperty]
           public string collectionMethod { get; set; }
           [JsonProperty]
           public string consentReceiptID { get; set; }
           [JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
           public string publicKey { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string language { get; set; }
           [JsonProperty]
           public string piiPrincipalId { get; set; }
           [JsonProperty]
           public Array piiControllers { get; set; }
           [JsonProperty]
           public string policyUrl { get; set; }
           [JsonProperty]
           public Array services { get; set; }
           [JsonProperty]
           public string sensitive { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string spiCat { get; set; }
       }
       [JsonObject]
       public class jsonController
       {
           public static jsonController Create(string json)
           {
               return new jsonController(json);
           }
           public static string Write(jsonController options)
           {
               return JsonConvert.SerializeObject(options);
           }
           public jsonController()
           { }
           public jsonController(string json)
           {
               try
               {
                   JsonConvert.PopulateObject(json, this);
               }
               catch (Exception ex)
               {
                   throw new Exception(string.Format("Error deserializing json:'{0}', into '{1}.", json, GetType()), ex);
               }
           }
           [JsonProperty]
           public string piiController { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string onBehalf { get; set; }
           [JsonProperty]
           public string contact { get; set; }
           [JsonProperty]
           public string address { get; set; }
           [JsonProperty]
           public string email { get; set; }
           [JsonProperty]
           public string phone { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string fax { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string piiControllerURL { get; set; }
       }
       [JsonObject]
       public class jsonService
       {
           [JsonProperty]
           public string service { get; set; }
           [JsonProperty]
           public Array purposes { get; set; }
       }
       [JsonObject]
       public class jsonPurpose
       {
           [JsonProperty]
           public string purpose { get; set; }
           [JsonProperty]
           public string[] purposeCategory { get; set; }
            [JsonProperty]
           public string consentType { get; set; }
           [JsonProperty]
           public string[] piiCategory { get; set; }
           [JsonProperty]
           public bool primaryPurpose { get; set; }
           [JsonProperty]
           public string termination { get; set; }
           [JsonProperty]
           public bool thirdPartyDisclosure { get; set; }
           [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
           public string thirdPartyName { get; set; }
       }
   }
 }

Json Initializer

           ProfileResponse profileResp = new ProfileResponse
           {
               version = "KI-CR-v1.1.0",
               jurisdiction = "WA",
               consentTimestamp = DateTime.UtcNow.ToString("o"),
               collectionMethod = "user input",
               consentReceiptID = Guid.NewGuid().ToString(),
               language = "en",
               piiPrincipalId = user.UserName,
               piiControllers = new jsonController[]
               {
                   new jsonController { piiController = "IDESGidp",
                   contact = "jerry",
                       email="jerry@ca0.net",
                       address="if required there is a class of address lists, like kids soccer, that would be in violation",
                       phone="someone needs to think this thing thru!"}
                   },
               policyUrl = "http://tomjones.us/CRpolicy",
               services = new jsonService[]
               {
                   new jsonService {
                       service = "IdP",
                       purposes = new jsonPurpose[]
                       {
                           new jsonPurpose {
                           purpose = "IdP",
                           purposeCategory= new string[] {"1 - Core Function" },
                           consentType="EXPLICIT",
                           piiCategory = new string[] {"2 - Contact" },
                           primaryPurpose= true,
                           termination="one year after last use",
                           thirdPartyDisclosure = false
                           }
                       }
                   }
               },
               sensitive = "false"
           };
           StatusMessage = JsonConvert.SerializeObject(profileResp);

Json output

Generated on a partial implementation on 2018-06-01. One thing that might seem a little odd to others is that the Consent receipt for this site never really varies. It is always that same three fields entered at this time.

One thing that becomes a little weird in the near future of this site is that the user will have the option of adding more information in the future in support of authentication at other sites. It seems that neither the GDPR nor the Consent Receipt considers that fact that users can enter data of their own free will for reasons that are not known to the IdP but will be used later at a relying party. In this case the IdP is just a trusted third party, a problem which will recur frequently in the health industry.

It is also not clear how to code the jurisdiction for US states. Maybe that is covered elsewhere?

But the real problem is, now that I have a Consent Receipt on the web site, what do I do with it?

 {
 "version": "KI-CR-v1.1.0",
 "jurisdiction": "WA",
 "consentTimestamp": "2018-06-04T02:34:12.9239336Z",
 "collectionMethod": "user input",
 "consentReceiptID": "25696cbc-9bd4-4abf-9774-7c57dd5bedc6",
 "language": "en",
 "piiPrincipalId": "tomcjones",
 "piiControllers": [
   {
     "piiController": "IDESGidp",
     "contact": "jerry",
     "address": "if required there is a class of address lists, like kids soccer, that would be in violation",
     "email": "jerry@ca0.net",
     "phone": "someone needs to think this thing thru!"
   }
 ],
 "policyUrl": "http://tomjones.us/CRpolicy",
 "services": [
   {
     "service": "IdP",
     "purposes": [
       {
         "purpose": "IdP",
         "purposeCategory": [ "1 - Core Function" ],
         "consentType": "EXPLICIT",
         "piiCategory": [ "2 - Contact" ],
         "primaryPurpose": true,
         "termination": "one year after last use",
         "thirdPartyDisclosure": false
       }
     ]
   }
 ],
 "sensitive": "false"
 }

XML output

This is a conversion of the same [JSONOBJECT] that was converted to JSON above.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="ConsentReceipt-min.xsl" ?>
<ConsentReceipt>
 <version>KI-CR-v1.1.0</version>
 <jurisdiction>WA</jurisdiction>
 <consentTimestamp>2018-06-06T21:59:57.8701013Z</consentTimestamp>
 <collectionMethod>user input</collectionMethod>
 <consentReceiptID>0b792c9c-66df-4176-bc4e-4626295e1fd9</consentReceiptID>
 <language>en</language>
 <piiPrincipalId>tomcjones</piiPrincipalId>
 <piiControllers json:Array="true" xmlns:json="http://james.newtonking.com/projects/json">
   <piiController>IDESGidp</piiController>
   <contact>jerry</contact>
   <address>requiring this eliminates a class small users</address>
   <email>jerry@ca0.net</email>
   <phone>someone needs to think this thing thru!</phone>
 </piiControllers>
 <policyUrl>http:idesg-idp.azurewebsites.net/Home/About</policyUrl>
 <services json:Array="true" xmlns:json="http://james.newtonking.com/projects/json">
   <service>IdP</service>
   <purposes>
     <purpose>Authenticate User</purpose>
     <purposeCategory json:Array="true">1 - Core Function</purposeCategory>
     <consentType>EXPLICIT</consentType>
     <piiCategory json:Array="true">2 - Contact</piiCategory>
     <primaryPurpose>true</primaryPurpose>
     <termination>one year after last use; or click this link http:idesg-idp.azurewebsites.net/Home/About</termination>
     <thirdPartyDisclosure>false</thirdPartyDisclosure>
   </purposes>
   <purposes>
     <purpose>Federated Logon</purpose>
     <purposeCategory json:Array="true">2 - not clear to me</purposeCategory>
     <consentType>IMPLICIT</consentType>
     <piiCategory>2 - Contact</piiCategory>
     <piiCategory>3 - More stuff</piiCategory>
     <primaryPurpose>false</primaryPurpose>
     <termination>same as primary purpose</termination>
     <thirdPartyDisclosure>true</thirdPartyDisclosure>
     <thirdPartyName>this will be the site you visit</thirdPartyName>
   </purposes>
 </services>
 <sensitive>false</sensitive>
</ConsentReceipt>

Simple Rendering for user site