gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[reclaim-ui] 261/459: towards cleanup of codebase and fixes


From: gnunet
Subject: [reclaim-ui] 261/459: towards cleanup of codebase and fixes
Date: Fri, 11 Jun 2021 23:25:53 +0200

This is an automated email from the git hooks/post-receive script.

martin-schanzenbach pushed a commit to branch master
in repository reclaim-ui.

commit 091f5d2d7e075df70bda55d17fd8eab5bb3ec0c4
Author: Martin Schanzenbach <mschanzenbach@posteo.de>
AuthorDate: Thu Aug 6 00:12:57 2020 +0200

    towards cleanup of codebase and fixes
---
 .../authorization-request.component.html           |   6 +-
 .../authorization-request.component.ts             |   8 +-
 src/app/edit-identity/edit-identity.component.html | 281 ++++++++---
 src/app/edit-identity/edit-identity.component.ts   | 544 ++++++++-------------
 src/app/identity-list/identity-list.component.html |  41 +-
 src/app/identity-list/identity-list.component.ts   | 253 ++++++----
 src/app/open-id.service.ts                         | 190 ++++++-
 7 files changed, 780 insertions(+), 543 deletions(-)

diff --git a/src/app/authorization-request/authorization-request.component.html 
b/src/app/authorization-request/authorization-request.component.html
index 2041736..0b66b6d 100644
--- a/src/app/authorization-request/authorization-request.component.html
+++ b/src/app/authorization-request/authorization-request.component.html
@@ -14,12 +14,12 @@
     asks you to share personal information.<br/>
     Choose an identity to let it access the following self-asserted 
information:
     <ul>
-      <li *ngFor="let attribute of getScopes()"><strong>{{attribute}}</strong>
+      <li *ngFor="let attribute of 
getScopesDescription()"><strong>{{attribute}}</strong>
     </ul>
-    <div *ngIf="getRefScope().length > 0">
+    <div *ngIf="getRequestedClaims().length > 0">
       as well as the following third-party attested attributes:
       <ul>
-        <ng-container *ngFor="let reference of getRefScope()">
+        <ng-container *ngFor="let reference of getRequestedClaims()">
           <li *ngIf="reference[1] === true"><strong>{{reference[0]}}</strong>
             <li *ngIf="reference[1] !== true"><strong>{{reference[0]}} 
(optional)</strong>
         </ng-container>
diff --git a/src/app/authorization-request/authorization-request.component.ts 
b/src/app/authorization-request/authorization-request.component.ts
index fa7b77b..0ce2c6d 100644
--- a/src/app/authorization-request/authorization-request.component.ts
+++ b/src/app/authorization-request/authorization-request.component.ts
@@ -16,12 +16,12 @@ export class AuthorizationRequestComponent implements 
OnInit {
     this.retryVerify();
   }
 
-  getScopes() {
-    return this.oidcService.getScope();
+  getScopesDescription() {
+    return this.oidcService.getScopesDescriptionList();
   }
 
-  getRefScope() {
-    return this.oidcService.getAttestedScope();
+  getRequestedClaims() {
+    return this.oidcService.getRequestedClaims();
   }
 
   isClientVerified() {
diff --git a/src/app/edit-identity/edit-identity.component.html 
b/src/app/edit-identity/edit-identity.component.html
index a6fb0fb..e592a61 100644
--- a/src/app/edit-identity/edit-identity.component.html
+++ b/src/app/edit-identity/edit-identity.component.html
@@ -2,41 +2,215 @@
 <div class="m-2 card">
   <div class="card-avatar card-img-top">
     <div class="card-avatar-character text-dark">
-      Manage identity: <i>{{ identity.name }}</i>
+      <h2>Manage identity: <i>{{ identity.name }}</i></h2>
     </div>
   </div>
   <!-- Attribute table -->
   <div class="card-body">
     <div>
-      <h6 class="card-subtitle mb-2">Attributes:</h6>
-      <!-- Missing attributes -->
-      <table class="table pb-1" *ngIf="isAttributeMissing() || 
isAttestedMissing()">
-        <thead>
-          <tr>
-              <th>Attribute Name</th>
-              <th>Attribute Value</th>
+      <h3 class="card-subtitle mb-2" (click)="showGeneralInfo = 
!showGeneralInfo"><span *ngIf="showGeneralInfo" class="fa 
fa-chevron-down"></span><span class="fa fa-chevron-right" 
*ngIf="!showGeneralInfo"></span> General user information</h3>
+      <table class="table pb-1" *ngIf="showGeneralInfo">
+        <tbody>
+          <!-- Standard "profile" claims first -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of existingProfileClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>
+            </td>
+            <td>
+              <button class="btn btn-primary" (click)="deleteAttribute(claim)" 
*ngIf="!isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+              <button class="btn btn-primary"  
(click)="deleteAttribute(claim)" *ngIf="isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+            </td>
+          </tr>
+          <!-- Standard "profile" claims missing on the identity -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of missingProfileClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <!-- FIXME Allow adding of attestation OR plain value -->
+              <input placeholder="Value" [(ngModel)]="claim.value">
+              <!--<input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>-->
+            </td>
+            <td>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <h3 class="card-subtitle mb-2" (click)="showEmailInfo = 
!showEmailInfo"><span class="fa" [class.fa-eye-slash]="!showEmailInfo" 
[class.fa-eye]="showEmailInfo"></span> Email</h3>
+
+      <table class="table pb-1">
+        <tbody>
+          <!-- Standard "email" claims first -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of existingEmailClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>
+            </td>
+            <td>
+              <button class="btn btn-primary" (click)="deleteAttribute(claim)" 
*ngIf="!isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+              <button class="btn btn-primary"  
(click)="deleteAttribute(claim)" *ngIf="isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+            </td>
+          </tr>
+          <!-- Standard "email" claims missing on the identity -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of missingEmailClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <!-- FIXME Allow adding of attestation OR plain value -->
+              <input placeholder="Value" [(ngModel)]="claim.value">
+              <!--<input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>-->
+            </td>
+            <td>
+            </td>
           </tr>
-        </thead>
+        </tbody>
+      </table>
+
+
+      <h6 class="card-subtitle mb-2">Address:</h6>
+      <table class="table pb-1">
         <tbody>
-          <tr [class.openid]="inOpenIdFlow()" 
[class.alert-danger]="newAttribute.name === missing.name" class="text-primary" 
*ngFor="let missing of missingAttributes">
-            <td><div style="min-width: 15em">{{missing.name}}</div></td>
+          <!-- Standard "address" claims first -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of existingAddressClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>
+            </td>
+            <td>
+              <button class="btn btn-primary" (click)="deleteAttribute(claim)" 
*ngIf="!isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+              <button class="btn btn-primary"  
(click)="deleteAttribute(claim)" *ngIf="isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+            </td>
+          </tr>
+          <!-- Standard "profile" claims missing on the identity -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of missingAddressClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
             <td>
-              <input placeholder="Value" [(ngModel)]="missing.value">
+              <!-- FIXME Allow adding of attestation OR plain value -->
+              <input placeholder="Value" [(ngModel)]="claim.value">
+              <!--<input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>-->
             </td>
             <td>
             </td>
           </tr>
-          <tr [class.openid]="inOpenIdFlow()" 
[class.alert-danger]="newAttested.name === missing.name" class="text-primary" 
*ngFor="let missing of missingAttested">
-            <td><div style="min-width: 15em">{{missing.name}}</div></td>
+        </tbody>
+      </table>
+
+      <h6 class="card-subtitle mb-2">Phone:</h6>
+      <table class="table pb-1">
+        <tbody>
+          <!-- Standard "phone" claims first -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of existingPhoneClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
             <td>
-              <select class="custom-select" 
(change)="missing.attestation=$event.target.value; ">
+            </td>
+            <td>
+              <input *ngIf="!isClaimAttested(claim)" placeholder="Value" 
[(ngModel)]="claim.value">
+              <span *ngIf="isClaimAttested(claim)" >{{ getAttestedValue(claim) 
}} issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value 
}}''</span>
+            </td>
+            <td>
+              <button class="btn btn-primary" (click)="deleteAttribute(claim)" 
*ngIf="!isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+              <button class="btn btn-primary"  
(click)="deleteAttribute(claim)" *ngIf="isClaimAttested(claim)">
+                <span class="fa fa-trash"></span>
+              </button>
+            </td>
+          </tr>
+          <!-- Standard "phone" claims missing on the identity -->
+          <tr [class.openid]="inOpenIdFlow()"
+              [class.text-primary]="isClaimRequested(claim)"
+              [class.alert-danger]="newAttribute.name === claim.name"
+              *ngFor="let claim of missingPhoneClaims">
+            <td><div style="min-width: 15em"><b>{{ getDescription(claim) 
}}</b></div></td>
+            <td>
+              <select class="custom-select" 
(change)="claim.flag=$event.target.value; ">
+                <option value="0">Plain</option>
+                <option value="1">Attested</option>
+              </select>
+            </td>
+            <td>
+              <input *ngIf="claim.flag == '0'" placeholder="Value" 
[(ngModel)]="claim.value">
+              <select *ngIf="claim.flag == '1'" class="custom-select"
+                (change)="claim.attestation=$event.target.value; ">
+                <option value="">Select attestation source</option>
+                <option *ngFor="let attest of attestations" 
value={{attest.id}}>
+                {{attest.name}}
+                </option>
+              </select>
+
+              <select class="custom-select"
+                *ngIf="claim.attestation !== '' && claim.flag == '1'" 
(change)="claim.value=$event.target.value">
+                <option value="">Select claim</option>
+                <option *ngFor="let att of attestationValuesForClaim(claim)" 
value={{att.name}}>
+                {{att.value}} <i>({{att.name}})</i>
+                </option>
+              </select>
+
+            </td>
+            <td>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
+
+      <h6 class="card-subtitle mb-2">Additional information:</h6>
+
+      <!-- Missing "non-standard" claims that are requested -->
+      <table class="table pb-1" 
*ngIf="isAnyRequestedNonStandardClaimMissing()">
+        <tbody>
+          <tr [class.openid]="inOpenIdFlow()"
+            [class.alert-danger]="newAttribute.name === missing.name"
+            class="text-primary"
+            *ngFor="let missing of missingNonStandardClaims">
+            <td><div style="min-width: 15em"><b>{{missing.name}}</b></div></td>
+            <td>
+              <input *ngIf="!isClaimAttestationRequested(missing)" 
placeholder="Value" [(ngModel)]="missing.value">
+              <select *ngIf="isClaimAttestationRequested(missing)" 
class="custom-select" (change)="missing.attestation=$event.target.value; ">
                 <option value="">Select attestation source</option>
                 <option *ngFor="let attest of attestations" 
value={{attest.id}}>
                   {{attest.name}}
                 </option>
               </select>
 
-              <select class="custom-select" *ngIf="missing.attestation !== ''" 
(change)="missing.value=$event.target.value">
+              <select *ngIf="isClaimAttestationRequested(missing) && 
missing.attestation !== ''" class="custom-select" 
(change)="missing.value=$event.target.value">
                 <option value="">Select claim</option>
                 <option *ngFor="let claim of 
attestationValuesForAttested(missing)" value={{claim.name}}>
                   {{claim.value}} <i>({{claim.name}})</i>
@@ -46,29 +220,26 @@
             <td>
             </td>
           </tr>
-
         </tbody>
       </table>
-      <!-- Requested attributes -->
+      <!-- "non-standard" claims which do exist -->
       <table class="table pb-1" style="">
-        <thead *ngIf="!isAttributeMissing()">
-          <tr>
-              <th>Attribute Name</th>
-              <th>Attribute Value</th>
-          </tr>
-        </thead>
         <tbody>
-          <tr [class.openid]="inOpenIdFlow()" 
[class.text-primary]="isRequested(attribute)" 
[class.alert-danger]="newAttribute.name === attribute.name" 
[class.text-secondary]="isAttestation(attribute)" *ngFor="let attribute of 
attributes">
-            <td><div style="min-width: 15em">{{ attribute.name }}</div></td>
+          <tr [class.openid]="inOpenIdFlow()"
+            [class.text-primary]="isClaimRequested(attribute)"
+            [class.alert-danger]="newAttribute.name === attribute.name"
+            [class.text-secondary]="isClaimAttested(attribute)"
+            *ngFor="let attribute of existingNonStandardClaims">
+            <td><div style="min-width: 15em"><b>{{ attribute.name 
}}</b></div></td>
             <td>
-              <input *ngIf="!isAttestation(attribute)" placeholder="Value" 
[(ngModel)]="attribute.value">
-              <span *ngIf="isAttestation(attribute)" >{{ 
getAttestedValue(attribute) }} issued by <i>{{ getIssuer(attribute) }}</i> as 
attribute for ``{{ attribute.value }}''</span>
+              <input *ngIf="!isClaimAttested(attribute)" placeholder="Value" 
[(ngModel)]="attribute.value">
+              <span *ngIf="isClaimAttested(attribute)" >{{ 
getAttestedValue(attribute) }} issued by <i>{{ getIssuer(attribute) }}</i> as 
attribute for ``{{ attribute.value }}''</span>
             </td>
             <td>
-              <button class="btn btn-primary" 
(click)="deleteAttribute(attribute)" *ngIf="!isAttestation(attribute)">
+              <button class="btn btn-primary" 
(click)="deleteAttribute(attribute)" *ngIf="!isClaimAttested(attribute)">
                 <span class="fa fa-trash"></span>
               </button>
-              <button class="btn btn-primary"  
(click)="deleteAttribute(attribute)" *ngIf="isAttestation(attribute)">
+              <button class="btn btn-primary"  
(click)="deleteAttribute(attribute)" *ngIf="isClaimAttested(attribute)">
                 <span class="fa fa-trash"></span>
               </button>
             </td>
@@ -79,42 +250,38 @@
               <input [class.text-danger]="!attributeNameValid(newAttribute)" 
placeholder="Attribute" [(ngModel)]="newAttribute.name">
             </td>
             <td>
-              <input placeholder="Value" 
[class.text-danger]="!attributeValueValid(newAttribute)" 
[(ngModel)]="newAttribute.value">
-            </td>
-            <td>
-              <button [disabled]="!canAddAttribute(newAttribute)" class="btn 
btn-primary"  (click)="addAttribute()">
-                <span class="fa fa-plus"></span>
-              </button>
-            </td>
-          </tr>
-          <!--new Attested Attribute-->
-          <tr [class.alert-danger]="isAttestedInConflict(newAttested)" 
*ngIf="0 != attestations.length">
-            <td>
-              <input [class.text-danger]="!attestedNameValid(newAttested)" 
placeholder="Attested attribute" [(ngModel)]="newAttested.name">
+              <select class="custom-select" 
(change)="newAttribute.flag=$event.target.value; ">
+                <option value="0">Plain</option>
+                <option value="1">Attested</option>
+              </select>
             </td>
             <td>
-              <select class="custom-select" 
(change)="newAttested.attestation=$event.target.value; ">
+
+
+              <input *ngIf="newAttribute.flag == '0'" placeholder="Value" 
[class.text-danger]="!attributeValueValid(newAttribute)" 
[(ngModel)]="newAttribute.value">
+              <select *ngIf="newAttribute.flag == '1'" class="custom-select"
+                (change)="newAttribute.attestation=$event.target.value; ">
                 <option value="">Select attestation source</option>
                 <option *ngFor="let attest of attestations" 
value={{attest.id}}>
                 {{attest.name}}
                 </option>
               </select>
 
-              <select class="custom-select" *ngIf="newAttested.attestation !== 
''" (change)="newAttested.value=$event.target.value">
+              <select class="custom-select"
+                *ngIf="newAttribute.attestation !== '' && newAttribute.flag == 
'0'" (change)="newAttribute.value=$event.target.value">
                 <option value="">Select claim</option>
-                <option *ngFor="let claim of 
attestationValuesForAttested(newAttested)" value={{claim.name}}>
+                <option *ngFor="let claim of 
attestationValuesForClaim(newAttribute)" value={{claim.name}}>
                 {{claim.value}} <i>({{claim.name}})</i>
                 </option>
               </select>
-            </td>
 
+            </td>
             <td>
-              <button [disabled]="!canAddAttested(newAttested)" class="btn 
btn-primary"  (click)="addAttested()">
-                <span class="fa fa-plus"></span> 
+              <button [disabled]="!canAddAttribute(newAttribute)" class="btn 
btn-primary"  (click)="addAttribute()">
+                <span class="fa fa-plus"></span>
               </button>
             </td>
           </tr>
-
         </tbody>
       </table>
     </div>
@@ -127,22 +294,6 @@
         <li>Attribute values may not be empty!</li>
       </ul>
     </div>
-    <!-- optional attributes information -->
-    <div *ngIf="optionalAttested.length !== 0" class="text-primary">
-      <span class="fa fa-openid"></span> You may optionally provide 
attestations for:
-      <ul>
-        <li *ngFor="let attribute of 
optionalAttested"><strong>{{attribute.name}}</strong>
-      </ul>
-    </div>
-    <!-- Attested creation warning -->
-    <div *ngIf="!attestedNameValid(newAttested) || 
!attestedValueValid(newAttested)" class="alert alert-primary alert-dismissible 
fade show" role="alert">
-      <span class="fa fa-warning"></span> Note:
-      <ul>
-        <li>Only use alphanumeric attribute names.</li>
-        <li>You cannot define the same name twice.</li>
-        <li>IDs and values may not be empty!</li>
-      </ul>
-    </div>
 
     <hr/>
 
diff --git a/src/app/edit-identity/edit-identity.component.ts 
b/src/app/edit-identity/edit-identity.component.ts
index 50a6f45..4cf9706 100644
--- a/src/app/edit-identity/edit-identity.component.ts
+++ b/src/app/edit-identity/edit-identity.component.ts
@@ -26,18 +26,25 @@ export class EditIdentityComponent implements OnInit {
   attributes: Attribute[];
   attestations: Attestation[];
   attestationValues: {};
-  requestedAttributes: Attribute[];
-  missingAttributes: Attribute[];
   newAttribute: Attribute;
-  newAttested: Attribute;
-  newAttestation: Attestation;
+  newAttestedClaim: Attribute;
   missingAttested: Attribute[];
-  requestedAttested: Attribute[];
-  optionalAttested: Attribute[];
+  requestedClaims: Attribute[];
+  optionalClaims: Attribute[];
   webfingerEmail: string;
   authorizations: Authorization[];
   newIdProvider: IdProvider;
   emailNotFoundAlertClosed: boolean;
+  existingProfileClaims: Attribute[];
+  missingProfileClaims: Attribute[];
+  existingPhoneClaims: Attribute[];
+  missingPhoneClaims: Attribute[];
+  existingEmailClaims: Attribute[];
+  missingEmailClaims: Attribute[];
+  existingAddressClaims: Attribute[];
+  missingAddressClaims: Attribute[];
+  existingNonStandardClaims: Attribute[];
+  missingNonStandardClaims: Attribute[];
 
   constructor(private reclaimService: ReclaimService,
               private identityService: IdentityService,
@@ -51,7 +58,7 @@ export class EditIdentityComponent implements OnInit {
   ngOnInit() {
     this.attributes = [];
     this.attestations = [];
-    this.optionalAttested = [];
+    this.optionalClaims = [];
     this.attestationValues = {};
     this.webfingerEmail = '';
     this.emailNotFoundAlertClosed = true;
@@ -59,8 +66,7 @@ export class EditIdentityComponent implements OnInit {
     this.loadAuthorizationsFromLocalStorage();
     this.identity = new Identity('','');
     this.newAttribute = new Attribute('', '', '', '', 'STRING', '0');
-    this.newAttested = new Attribute('', '', '', '', 'STRING', '1');
-    this.newAttestation = new Attestation('', '', '', 'JWT', '', null, []);
+    this.newAttestedClaim = new Attribute('', '', '', '', 'STRING', '1');
     this.activatedRoute.params.subscribe(p => {
       if (p['id'] === undefined) {
         return;
@@ -78,31 +84,67 @@ export class EditIdentityComponent implements OnInit {
     });
   }
 
+  getDescription(claim: Attribute) : string {
+    return this.oidcService.getClaimDescription(claim);
+  }
+
+  private bootstrapClaimArray(claimTemplate: Object): Attribute[] {
+    var result = [];
+    for (let claim in claimTemplate) {
+      let attr = new Attribute(claim, '', '', '', 'STRING', '0');
+      result.push(attr);
+    }
+    return result;
+  }
 
+  private updateClaimArray(claimArray: Attribute[], attr: Attribute): 
Attribute[] {
+    var result = [];
+    for (let i = 0; i < claimArray.length; i++) {
+      if (claimArray[i].name === attr.name) {
+        result.push(attr);
+      } else {
+        result.push(claimArray[i]);
+      }
+    }
+    return result;
+  }
+
+  private cleanupClaimArray(claimArray: Attribute[]) {
+    var result = []
+    for (let attr of claimArray) {
+      if (attr.value !== '') {
+        result.push(attr);
+      }
+    }
+    return result;
+  }
 
   private updateAttributes() {
     this.reclaimService.getAttributes(this.identity).subscribe(attributes => {
-      this.attributes = [];
-      this.requestedAttributes = [];
-      this.requestedAttested = [];
-      if (attributes === null) {
-        this.getMissingAttributes();
-        return;
-      }
-      let i;
+      this.existingProfileClaims = this.bootstrapClaimArray 
(this.oidcService.getStandardProfileClaims());
+      this.existingEmailClaims = this.bootstrapClaimArray 
(this.oidcService.getStandardEmailClaims());
+      this.existingPhoneClaims = this.bootstrapClaimArray 
(this.oidcService.getStandardPhoneClaims());
+      this.existingAddressClaims = this.bootstrapClaimArray 
(this.oidcService.getStandardAddressClaims());
+      this.existingNonStandardClaims = [];
       this.attributes = attributes;
-      for (i = 0; i < attributes.length; i++) {
-        if ((attributes[i].flag === '0') &&
-            this.oidcService.getScope().includes(attributes[i].name)) {
-          this.requestedAttributes.push(attributes[i]);
-        }
-        if ((attributes[i].flag === '1') &&
-            this.oidcService.getAttestedScope().includes(attributes[i].name)) {
-          this.requestedAttested.push(attributes[i]);
+      for (let attr of this.attributes) {
+        if (this.oidcService.isStandardProfileClaim(attr)) {
+          this.existingProfileClaims = 
this.updateClaimArray(this.existingProfileClaims, attr);
+        } else if (this.oidcService.isStandardEmailClaim(attr)) {
+          this.existingEmailClaims = 
this.updateClaimArray(this.existingEmailClaims, attr);
+        } else if (this.oidcService.isStandardAddressClaim(attr)) {
+          this.existingAddressClaims = 
this.updateClaimArray(this.existingAddressClaims, attr);
+        } else if (this.oidcService.isStandardPhoneClaim(attr)) {
+          this.existingPhoneClaims = 
this.updateClaimArray(this.existingPhoneClaims, attr);
+        } else {
+          this.existingNonStandardClaims.push(attr);
         }
       }
-      this.getMissingAttributes();
-      this.getMissingAttested();
+      this.existingProfileClaims = 
this.cleanupClaimArray(this.existingProfileClaims);
+      this.existingEmailClaims = 
this.cleanupClaimArray(this.existingEmailClaims);
+      this.existingPhoneClaims = 
this.cleanupClaimArray(this.existingPhoneClaims);
+      this.existingAddressClaims = 
this.cleanupClaimArray(this.existingAddressClaims);
+      this.updateMissingAttributes();
     },
     err => {
       //this.errorInfos.push("Error retrieving attributes for ``" + 
identity.name + "''");
@@ -114,47 +156,52 @@ export class EditIdentityComponent implements OnInit {
     return this.oidcService.inOpenIdFlow();
   }
 
-  isRequested(attribute) {
-    if (undefined === this.requestedAttributes) {
+  isClaimRequested(attribute) {
+    const claims = this.oidcService.getClaimNamesForRequest();
+    if (undefined === claims) {
       return false;
     } else {
       return -1 !==
-        this.requestedAttributes.indexOf(attribute);
+        claims.indexOf(attribute.name);
     }
   }
 
-  getMissingAttributes() {
-    const scopes = this.oidcService.getScope();
-    let i;
-    for (i = 0; i < this.requestedAttributes.length; i++) {
+  updateMissingAttributes() {
+    var claims = this.oidcService.getStandardClaimNames();
+    for (let attr of this.attributes) {
       const j =
-        scopes.indexOf(this.requestedAttributes[i].name);
+        claims.indexOf(attr.name);
       if (j >= 0) {
-        scopes.splice(j, 1);
+        claims.splice(j, 1);
       }
     }
-    this.missingAttributes = [];
-    for (i = 0; i < scopes.length; i++) {
+    this.missingProfileClaims = [];
+    this.missingEmailClaims = [];
+    this.missingPhoneClaims = [];
+    this.missingAddressClaims = [];
+    this.missingNonStandardClaims = [];
+    for (let claim of claims) {
       const attribute = new Attribute('', '', '', '', 'STRING', '');
       attribute.flag = '0';
-      attribute.name = scopes[i];
-      this.missingAttributes.push(attribute);
+      attribute.name = claim;
+      if (this.oidcService.isStandardProfileClaim(attribute)) {
+        this.missingProfileClaims.push(attribute);
+      } else if (this.oidcService.isStandardEmailClaim(attribute)) {
+        this.missingEmailClaims.push(attribute);
+      } else if (this.oidcService.isStandardPhoneClaim(attribute)) {
+        this.missingPhoneClaims.push(attribute);
+      } else if (this.oidcService.isStandardAddressClaim(attribute)) {
+        this.missingAddressClaims.push(attribute);
+      } else {
+        this.missingNonStandardClaims.push(attribute);
+      }
     }
   }
 
-  isInConflict(attribute) {
-    let i;
-    if (undefined !== this.missingAttributes) {
-      for (i = 0; i < this.missingAttributes.length; i++) {
-        if (attribute.name ===
-          this.missingAttributes[i].name) {
-          return true;
-        }
-      }
-    }
-    if (undefined !== this.attributes) {
-      for (i = 0; i < this.attributes.length; i++) {
-        if (attribute.name === this.attributes[i].name) {
+  checkConflict(attrs: Attribute[], attribute: Attribute): boolean {
+    if (undefined !== attrs) {
+      for (let attr of attrs) {
+        if (attribute.name === attr.name) {
           return true;
         }
       }
@@ -162,7 +209,16 @@ export class EditIdentityComponent implements OnInit {
     return false;
   }
 
-  canAddAttribute(attribute) {
+  isInConflict(attribute: Attribute): boolean {
+    return this.checkConflict(this.missingProfileClaims, attribute) ||
+           this.checkConflict(this.missingEmailClaims, attribute) ||
+           this.checkConflict(this.missingPhoneClaims, attribute) ||
+           this.checkConflict(this.missingAddressClaims, attribute) ||
+           this.checkConflict(this.missingNonStandardClaims, attribute) ||
+           this.checkConflict(this.attributes, attribute);
+  }
+
+  canAddAttribute(attribute: Attribute): boolean {
     if ((attribute.name === '') || (attribute.value === '')) {
       return false;
     }
@@ -172,12 +228,15 @@ export class EditIdentityComponent implements OnInit {
     return !this.isInConflict(attribute);
   }
 
-  canSaveIdentity() {
-    return (this.canSaveAttribute() &&
-            this.canSaveAttested());
+  canSaveIdentity(): boolean {
+    return this.canSaveAttributes();
   }
 
-  canSaveAttribute() {
+  /**
+   * TODO fix newAttribute so that we can make
+   * it either attested or plain
+   */
+  canSaveAttributes(): boolean {
     if (this.canAddAttribute(this.newAttribute)) {
       return true;
     }
@@ -186,44 +245,18 @@ export class EditIdentityComponent implements OnInit {
       !this.isInConflict(this.newAttribute);
   }
 
-  canSaveAttested() {
-    if (this.canAddAttested(this.newAttested)) {
-      return true;
-    }
-    return ((this.newAttested.name === '') &&
-      (this.newAttested.attestation === '') &&
-      (this.newAttested.id === '')) &&
-      !this.isAttestedInConflict(this.newAttested);
-  }
-
-
-  isAttestedInConflict(attested) {
-    let i;
-    if (undefined !== this.missingAttested) {
-      for (i = 0; i < this.missingAttested.length; i++) {
-        if (attested.name ===
-          this.missingAttested[i].name) {
-          return true;
-        }
-      }
-    }
-    if (undefined !== this.attributes) {
-      for (i = 0; i < this.attributes.length; i++) {
-        if (attested.name === this.attributes[i].name) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-
   saveIdentity() {
     localStorage.removeItem("userForAttestation");
     this.saveIdentityAttributes();
   }
 
   saveIdentityAttributes() {
+    if (this.newAttribute.flag === '0') {
+      /**
+       * Make sure attestation is not still set
+       */
+      this.newAttribute.attestation = '';
+    }
     this.storeAttributes()
       .pipe(
         finalize(() => {
@@ -257,25 +290,45 @@ export class EditIdentityComponent implements OnInit {
       });
   }
 
-  private storeAttributes() {
+  private storeMissingAttributes(missing: Attribute[]): any {
     const promises = [];
     let i;
-    if (undefined !== this.missingAttributes) {
-      for (i = 0; i < this.missingAttributes.length; i++) {
-        if (this.missingAttributes[i].value === '') {
+    if (undefined !== missing) {
+      for (let attr of missing) {
+        if (attr.value === '') {
           continue;
         }
+        if (attr.flag === '0') {
+          attr.attestation = '';
+        }
         promises.push(from(this.reclaimService.addAttribute(
-          this.identity, this.missingAttributes[i])));
+          this.identity, attr)));
       }
     }
+    return promises;
+  }
+
+  /**
+   * FIXME incorporate attested attributes here!
+   */
+  private storeAttributes() {
+    var promises = [];
+    promises = promises.concat (this.storeMissingAttributes 
(this.missingProfileClaims));
+    promises = promises.concat (this.storeMissingAttributes 
(this.missingEmailClaims));
+    promises = promises.concat (this.storeMissingAttributes 
(this.missingPhoneClaims));
+    promises = promises.concat (this.storeMissingAttributes 
(this.missingAddressClaims));
+    promises = promises.concat (this.storeMissingAttributes 
(this.missingNonStandardClaims));
+
     if (undefined !== this.attributes) {
-      for (i = 0; i < this.attributes.length; i++) {
-        if (this.attributes[i].flag === '1') {
+      for (let attr of this.attributes) {
+        /*if (attr.flag === '1') {
           continue; //Is an attestation
+        }*/
+        if (attr.flag === '0') {
+          attr.attestation = '';
         }
         promises.push(
-          from(this.reclaimService.addAttribute(this.identity, 
this.attributes[i])));
+          from(this.reclaimService.addAttribute(this.identity, attr)));
       }
     }
     if (this.newAttribute.value !== '') {
@@ -285,6 +338,9 @@ export class EditIdentityComponent implements OnInit {
     return forkJoin(promises);
   }
 
+  /**
+   * Adds a new attribute, stores all changes and STAYS on this page.
+   */
   addAttribute() {
     this.storeAttributes()
       .pipe(
@@ -305,7 +361,7 @@ export class EditIdentityComponent implements OnInit {
       });
   }
 
-  attributeNameValid(attribute) {
+  attributeNameValid(attribute: Attribute): boolean {
     if (attribute.name === '' && attribute.value === '') {
       return true;
     }
@@ -325,84 +381,67 @@ export class EditIdentityComponent implements OnInit {
     return true;
   }
 
-  isAttributeMissing() {
-    if (!this.oidcService.inOpenIdFlow()) {
-      return false;
+  isAttributeNameInList(name: string, attrs: Attribute[]) {
+    for (let attr of attrs) {
+      if (name === attr.name) {
+        return true;
+      }
     }
-    if (undefined === this.requestedAttributes) {
+    return false;
+  }
+
+  isAnyRequestedNonStandardClaimMissing(): boolean {
+    if (!this.oidcService.inOpenIdFlow()) {
       return false;
     }
-    var scopes = this.oidcService.getScope();
-    for (var i = 0; i < this.requestedAttributes.length; i++) {
-      if (!scopes.includes(this.requestedAttributes[i].name))
-      {
+    var requestedClaims = this.oidcService.getClaimNamesForRequest();
+    for (let claim in requestedClaims) {
+      if (this.isAttributeNameInList(claim, this.missingNonStandardClaims)) {
         return true;
       }
     }
     return false;
-  }
 
-  private saveIdentityAttested() {
-    this.storeAttested()
-      .pipe(
-        finalize(() => {
-          this.newAttested.name = '';
-          this.newAttested.attestation = '';
-          this.newAttested.id = '';
-          this.newAttested.value = '';
-          this.newAttested.flag = '1';
-        }))
-      .subscribe(res => {
-        //FIXME success dialog/banner
-        this.updateAttributes();
-      },
-      err => {
-        console.log(err);
-        //this.errorInfos.push("Failed to update identity ``" +  
this.identityInEdit.name + "''");
-      });
   }
 
-  deleteAttested(attribute) {
-    this.reclaimService.deleteAttribute(this.identity, attribute)
-      .subscribe(res => {
-        //FIXME info dialog
-        this.updateAttributes();
-      },
-      err => {
-        //this.errorInfos.push("Failed to delete reference ``" + 
reference.name + "''");
-        console.log(err);
-      });
+  isAnyRequestedAttributeMissing(): boolean {
+    if (!this.oidcService.inOpenIdFlow()) {
+      return false;
+    }
+    var requestedClaims = this.oidcService.getClaimNamesForRequest();
+    for (let claim in requestedClaims) {
+      if (this.isAttributeNameInList(claim, this.missingProfileClaims) ||
+          this.isAttributeNameInList(claim, this.missingEmailClaims) ||
+          this.isAttributeNameInList(claim, this.missingAddressClaims) ||
+          this.isAttributeNameInList(claim, this.missingPhoneClaims) ||
+          this.isAttributeNameInList(claim, this.missingNonStandardClaims)) {
+        return true;
+      }
+    }
+    return false;
   }
 
-
-  getMissingAttested() {
-    const refscopes = this.oidcService.getAttestedScope();
-    let i;
-    for (i = 0; i < this.requestedAttested.length; i++) {
-      for (var j = 0; j < refscopes.length; j++) {
-        if (this.requestedAttested[i].name === refscopes[j][0] ) {
-          refscopes.splice(j,1);
-        }
+  isClaimAttestationRequested(attr: Attribute) {
+    //TODO check if this claim is in claims parameter and needs attestation
+    var claims = this.oidcService.getRequestedClaims();
+    for (let claim of claims) {
+      if (claim[0] == attr.name) {
+        return true;
       }
     }
-    this.missingAttested = [];
-    this.optionalAttested = [];
-    for (i = 0; i < refscopes.length; i++) {
-      const attribute = new Attribute('', '', '', '', 'STRING', '');
-      attribute.flag = '1';
-      if (refscopes[i][1] === true)
-      {
-        attribute.name = refscopes[i][0];
-        this.missingAttested.push(attribute);
-      }
-      if (refscopes[i][1] === false)
-      {
-        attribute.name = refscopes[i][0];
-        this.optionalAttested.push(attribute);
-      }
+    return false;
+  }
+
+  isClaimOptional(claim: Attribute) {
+    //TODO check if this claim is in claims parameter and optional
+    var claims = this.oidcService.getRequestedClaims();
+    for (let claim of claims) {
+      return claim[1];
     }
+    return true;
   }
 
+
   private updateAttestations() {
     this.reclaimService.getAttestations(this.identity).subscribe(attestations 
=> {
       this.attestations = attestations;
@@ -413,94 +452,11 @@ export class EditIdentityComponent implements OnInit {
     });
   }
 
-  private storeAttested() {
-    const promises = [];
-    let i;
-    if (undefined !== this.missingAttested) {
-      for (i = 0; i < this.missingAttested.length; i++) {
-        if ((this.missingAttested[i].value === '') || 
(this.missingAttested[i].attestation !== '')) {
-          console.log("Empty Attestation: " + this.missingAttested[i]);
-          continue;
-        }
-        console.log("Missing Attestation: " + this.missingAttested[i]);
-        promises.push(from(this.reclaimService.addAttribute(
-          this.identity, this.missingAttested[i])));
-      }
-    }
-    if (undefined !== this.attributes) {
-      for (i = 0; i < this.attributes.length; i++) {
-        if (this.attributes[i].attestation === '') {
-          continue;
-        }
-        promises.push(
-          from(this.reclaimService.addAttribute(this.identity, 
this.attributes[i])));
-      }
-    }
-    if ((this.newAttested.value !== '') && (this.newAttested.attestation !== 
'')
-        && (this.newAttested.name !== '')) {
-      promises.push(from(this.reclaimService.addAttribute(this.identity, 
this.newAttested)));
-    }
-
-    return forkJoin(promises);
-  }
-
-  addAttested() {
-    this.storeAttested()
-    .pipe(
-      finalize(() => {
-        this.newAttested.name = '';
-        this.newAttested.value= '';
-        this.newAttested.id = '';
-        this.newAttested.attestation = '';
-        this.newAttested.flag = '1';
-        this.updateAttributes();
-      }))
-      .subscribe(res => {
-        console.log(res);
-      },
-      err => {
-        console.log(err);
-        //this.errorInfos.push("Failed to update identity ``" +  
this.identityInEdit.name + "''");
-        EMPTY
-      });
-  }
-
-
-  isAttestation(attribute) {
+  isClaimAttested(attribute) {
     return attribute.flag === '1';
   }
 
-  canAddAttested(attribute) {
-    if ((attribute.name === '') || (attribute.value === '') || 
(attribute.attestation === '')) {
-      return false;
-    }
-    if (attribute.name.indexOf(' ') >= 0) {
-      return false;
-    }
-    return !this.isAttestedInConflict(attribute);
-  }
-
-  attestedNameValid(attribute) {
-    if (attribute.name === '' && attribute.value === '' && 
attribute.attestation === '') {
-      return true;
-    }
-    if (attribute.name.indexOf(' ') >= 0) {
-      return false;
-    }
-    if (!/^[a-zA-Z0-9-_]+$/.test(attribute.name)) {
-      return false;
-    }
-    return !this.isAttestedInConflict(attribute);
-  }
-
-  attestedValueValid(attribute: Attribute) {
-    if (attribute.value === '') {
-      return attribute.name === '';
-    }
-    return true;
-  }
-
-  attestedAttestationValid(attribute: Attribute) {
+  isClaimAttestationValid(attribute: Attribute) {
     if (attribute.attestation === '') {
       return attribute.name === '';
     }
@@ -508,88 +464,7 @@ export class EditIdentityComponent implements OnInit {
   }
 
 
-  isAttestedRequested(attribute: Attribute) {
-    if (undefined === this.requestedAttested) {
-      return false;
-    } else {
-      return -1 !==
-        this.requestedAttested.indexOf(attribute);
-    }
-  }
-
-  isAttrRefRequested(attribute: Attribute) {
-    if (undefined === this.requestedAttested) {
-      return false;
-    } else {
-      for (var j = 0; j < this.requestedAttested.length; j++) {
-        if (attribute.name === this.requestedAttested[j].name) {
-          return true;
-        }
-      }
-      return false;
-    }
-  }
-
-  isoptAttestedRequested(attribute: Attribute) {
-    if (undefined === this.optionalAttested) {
-      return false;
-    } else {
-      return -1 !==
-        this.optionalAttested.indexOf(attribute);
-    }
-  }
-
-  isAttestedMissing() {
-    if (!this.inOpenIdFlow()) {
-      return false;
-    }
-    if (undefined === this.requestedAttested) {
-      return false;
-    }
-    for (var i = 0; i < this.oidcService.getAttestedScope().length; i++) {
-      if (this.oidcService.getAttestedScope()[i][1] === true) {
-        var j;
-        for (j = 0; j < this.requestedAttested.length; j++) {
-          if (this.oidcService.getAttestedScope()[i][0] === 
this.requestedAttested[j].name){
-            break;
-          }
-        }
-        if (j === this.requestedAttested.length){
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-
-  /*private setAttestationValue(attestation) {
-    var value_string="";
-    return this.reclaimService.parseAttest(attestation).subscribe(json_string 
=>{
-    this.attestation_val[attestation.id]=json_string;
-    },
-    err => {
-  //this.errorInfos.push("Error parsing attestation ``" + attestation.name + 
"''");
-  console.log(err);
-  });
-  }*/
-
-  isAttestedValid(attribute: Attribute) {
-    for (let i = 0; i < this.attestations.length; i++) {
-      if (attribute.attestation === this.attestations[i].id) {
-        return this.isAttestationValid(this.attestations[i]);
-      }
-    }
-    return false;
-  }
-
-  isAttestationValid(attestation: Attestation) {
-    //FIXME JWT specific
-    //FIXME the expiration of the JWT should be a property of the attestation
-    //Not part of the values
-    return true;
-  }
-
-  attestationValuesForAttested(attribute: Attribute) {
+  attestationValuesForClaim(attribute: Attribute) {
     for (let i = 0; i < this.attestations.length; i++) {
       if (this.attestations[i].id == attribute.attestation) {
         return this.attestations[i].attributes;
@@ -597,21 +472,6 @@ export class EditIdentityComponent implements OnInit {
     }
   }
 
-  isAnyAttestationInvalid() {
-    if (!this.inOpenIdFlow()) {
-      return false;
-    }
-    if (undefined === this.requestedAttested) {
-      return false;
-    }
-    for (var j = 0; j < this.attestations.length; j++) {
-      if (!this.isAttestationValid(this.attestations[j])) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   //FIXME attestations need an issuer field
   getIssuer(attribute: Attribute) {
     for (let i = 0; i < this.attestations.length; i++) {
diff --git a/src/app/identity-list/identity-list.component.html 
b/src/app/identity-list/identity-list.component.html
index fc8b24a..40606d9 100644
--- a/src/app/identity-list/identity-list.component.html
+++ b/src/app/identity-list/identity-list.component.html
@@ -53,7 +53,6 @@
   <div class="card" *ngFor="let identity of identities | search: searchTerm">
     <div class="card-avatar card-img-top">
       <div class="card-avatar-character text-dark">
-        <!--<div class="icon m-1 text-uppercase" 
[style.background-color]="intToRGB(identity.pubkey)">{{ 
identity.name[0]}}</div>-->
         <i class="fa fa-user-circle"></i>
         <span class="m-1" style="display: inline-block"><i> 
{{identity.name}}</i></span>
         <button class="btn btn-primary" *ngIf="showConfirmDelete != identity" 
(click)="confirmDelete(identity)">
@@ -64,6 +63,7 @@
         </button>
       </div>
     </div>
+    <!-- Identity deletion confirmation -->
     <div class="alert alert-danger fade show" *ngIf="showConfirmDelete == 
identity">
       Do you really want to delete this identity?<br/><br/>
       <button class="btn btn-primary" (click)="deleteIdentity(identity)">
@@ -73,41 +73,36 @@
         <span class="fa fa-close"></span> Cancel
       </button>
     </div>
+    <!-- Maybe add some info to identities? - dialog -->
     <div class="alert alert-secondary fade show" 
*ngIf="!hasAttributes(identity)">
       This identity has no attributes. Maybe try <a class="buttonlink" 
[routerLink]="['/edit-identity', identity.name]">adding some?</a>
     </div>
-    <div *ngIf="isAttributeMissing(identity) || isAttestedMissing(identity)" 
class="alert alert-danger alert-dismissible fade show" role="alert">
-      <span class="fa fa-openid"></span> This identity cannot be used because 
it's missing requested information:
+    <div *ngIf="isClaimMissing(identity) || isRequestedScopeMissing(identity)" 
class="alert alert-danger alert-dismissible fade show" role="alert">
+      <span class="fa fa-openid"></span> This identity is missing some 
requested information:
       <ul>
-        <li *ngFor="let attr of getMissing(identity)">{{attr}}</li>
-        <li *ngFor="let ref of getOptional(identity)">{{ref}}(optional)</li>
+        <li *ngIf="isProfileRequested() && 
isProfileMissing(identity)">getProfileDescription()</li>
+        <li *ngIf="isEmailRequested() && 
isEmailMissing(identity)">getEmailDescription()</li>
+        <li *ngIf="isPhoneRequested() && 
isPhoneMissing(identity)">getPhoneDescription()</li>
+        <li *ngIf="isAddressRequested() && 
isAddressMissing(identity)">getAddressDescription()</li>
+        <li *ngFor="let attr of getMissingClaims(identity)">{{attr}}</li>
+        <li *ngFor="let ref of getOptional(identity)">{{ref}} (optional)</li>
       </ul>
       <button class="btn btn-primary" [routerLink]="['/edit-identity', 
identity.name]">
-        <span class="fa fa-plus"></span> Add
-      </button>
-    </div>
-    <div *ngIf="isReqReferenceInvalid(identity)" class="alert alert-danger 
alert-dismissible fade show" role="alert">
-      <span class="fa fa-openid"></span> This identity cannot be used because 
one or more attested attributes are invalid.
-      <button class="btn btn-primary" (click)="editIdentity(identity)">
-        <span class="fa fa-pencil-square-o"></span> Edit
+        <span class="fa fa-plus"></span> Edit identity
       </button>
     </div>
-    <div *ngIf="(0 < requestedAttested[identity.pubkey]?.length) && 
inOpenIdFlow()" class="alert alert-danger alert-dismissible fade show" 
role="alert">
-      <span class="fa fa-openid"></span> Please note that sharing attested 
attributes might disclose additional information stored in the attestation.
-    </div>
     <div class="card-body">
-      <!-- Attribute table --> 
+      <!-- Attribute table -->
       <div>
-        <h6 class="card-subtitle mb-2" *ngIf="hasAttributes(identity)">
-          <strong>Information:</strong>
-        </h6>
         <table class="table pb-1">
           <tbody>
-            <tr [class.openid]="inOpenIdFlow()" 
[class.text-primary]="isRequested(identity, attribute) || 
isAttestedRequested(identity, attribute)"
-               [class.text-secondary]="!isAttestedRequested(identity, 
attribute) && isAttestation(attribute)"
+            <tr [class.openid]="inOpenIdFlow()" 
[class.text-primary]="isClaimRequested(identity, attribute)"
+               [class.text-secondary]="!isClaimRequested(identity, attribute)"
                *ngFor="let attribute of attributes[identity.pubkey]">
               <td>
-                <div style="min-width: 15em"><span 
*ngIf="isRequested(identity, attribute) || isAttestedRequested(identity, 
attribute)" class="fa fa-openid"></span> {{attribute.name}}</div>
+                <div style="min-width: 15em">
+                  <span *ngIf="isClaimRequested(identity, attribute)" 
class="fa fa-openid"></span> <b>{{getAttributeDescription(attribute)}}</b>
+                </div>
               </td>
               <td>
                 <div *ngIf="attribute.value.length <= 20" style="min-width: 
15em">{{attribute.value}}</div>
@@ -123,7 +118,7 @@
       <div>
 
         <div>
-          <button *ngIf="canAuthorize(identity)" [disabled]="!inOpenIdFlow() 
|| isAttributeMissing(identity) || isAttestedMissing(identity) || 
!isClientVerified() || isReqReferenceInvalid(identity)" 
(click)="loginIdentity(identity)" class="btn btn-primary mr-1 openid-login">
+          <button *ngIf="inOpenIdFlow()" [disabled]="!isClientVerified()" 
(click)="loginIdentity(identity)" class="btn btn-primary mr-1 openid-login">
             <span *ngIf="isClientVerified()"><i class="fa fa-openid"></i> 
Share information from this identity</span>
             <span *ngIf="!isClientVerified()"><i class="fa 
fa-exclamation-circle"></i> Sharing disabled</span>
           </button>
diff --git a/src/app/identity-list/identity-list.component.ts 
b/src/app/identity-list/identity-list.component.ts
index 6ca1dbf..c491e73 100644
--- a/src/app/identity-list/identity-list.component.ts
+++ b/src/app/identity-list/identity-list.component.ts
@@ -21,11 +21,14 @@ import { from, forkJoin, EMPTY } from 'rxjs';
 
 export class IdentityListComponent implements OnInit {
 
-  requestedAttributes: any;
-  requestedAttested: any;
-  missingAttributes: any;
-  missingAttestations: any;
-  optionalAttested: any;
+  profileAttributes: any;
+  emailAttribute: any;
+  phoneAttribute: any;
+  addressAttributes: any;
+  requestedScopes: any;
+  requestedClaims: any;
+  missingClaims: any;
+  optionalClaims: any;
   attributes: any;
   attestations: any;
   identities: Identity[];
@@ -34,6 +37,7 @@ export class IdentityListComponent implements OnInit {
   modalOpened: any;
   errorInfos: any;
   searchTerm: any;
+  sortAttributeByStandardClaim: any;
 
   constructor(private route: ActivatedRoute, private oidcService: 
OpenIdService,
     private identityService: IdentityService,
@@ -49,11 +53,10 @@ export class IdentityListComponent implements OnInit {
     this.attestations = {};
     this.identities = [];
     this.showConfirmDelete = null;
-    this.requestedAttributes = {};
-    this.missingAttributes = {};
-    this.requestedAttested = {};
-    this.missingAttestations = {};
-    this.optionalAttested = {};
+    this.requestedScopes = {};
+    this.missingClaims = {};
+    this.requestedClaims = {};
+    this.optionalClaims = {};
     this.connected = false;
     this.modalOpened = false;
     if (undefined !== this.route.snapshot.queryParams["code"]) {
@@ -89,54 +92,41 @@ export class IdentityListComponent implements OnInit {
 
   hideConfirmDelete() { this.showConfirmDelete = null; }
 
-  getMissingAttributes(identity) {
-    const scopes = this.getScopes();
+  /**
+   * Returns missing claims specifically requested
+   * through the "claims" OIDC parameter
+   */
+  updateMissingClaims(identity) {
+    const refscopes = this.oidcService.getRequestedClaims();
     let i;
-    for (i = 0; i < this.requestedAttributes[identity.pubkey].length; i++) {
-      const j =
-        scopes.indexOf(this.requestedAttributes[identity.pubkey][i].name);
-      if (j >= 0) {
-        scopes.splice(j, 1);
-      }
-    }
-    this.missingAttributes[identity.pubkey] = [];
-    for (i = 0; i < scopes.length; i++) {
-      const attribute = new Attribute('', '', '', '', 'STRING', '');
-      attribute.name = scopes[i];
-      this.missingAttributes[identity.pubkey].push(attribute);
-    }
-  }
-
-  getMissingAttested(identity) {
-    const refscopes = this.oidcService.getAttestedScope();
-    let i;
-    for (i = 0; i < this.requestedAttested[identity.pubkey].length; i++) {
+    for (i = 0; i < this.attributes[identity.pubkey].length; i++) {
       for (var j = 0; j < refscopes.length; j++) {
-        if (this.requestedAttested[identity.pubkey][i].name === 
refscopes[j][0] ) {
+        if (this.attributes[identity.pubkey][i].name === refscopes[j][0] ) {
           refscopes.splice(j,1);
         }
       }
     }
-    this.missingAttestations[identity.pubkey] = [];
-    this.optionalAttested[identity.pubkey] = [];
+    this.missingClaims[identity.pubkey] = [];
+    this.optionalClaims[identity.pubkey] = [];
     for (i = 0; i < refscopes.length; i++) {
       const attested = new Attribute('', '', '', '', 'STRING', '');
       if (refscopes[i][1] === true)
       {
         attested.name = refscopes[i][0];
-        this.missingAttestations[identity.pubkey].push(attested);
+        this.missingClaims[identity.pubkey].push(attested);
       }
       if (refscopes[i][1] === false)
       {
         attested.name = refscopes[i][0];
-        this.optionalAttested[identity.pubkey].push(attested);
+        this.optionalClaims[identity.pubkey].push(attested);
       }
     }
   }
 
   private updateAttestations(identity) {
     this.attestations[identity.pubkey] = [];
-    this.requestedAttested[identity.pubkey] = [];
+    this.requestedClaims[identity.pubkey] = [];
+    this.optionalClaims[identity.pubkey] = [];
     this.reclaimService.getAttestations(identity).subscribe(attestations => {
       if (attestations !== null) {
         this.attestations[identity.pubkey] = attestations;
@@ -148,29 +138,28 @@ export class IdentityListComponent implements OnInit {
     });
   }
 
+  getAttributeDescription(attr: Attribute): string {
+    return this.oidcService.getClaimDescription(attr);
+  }
+
+  sortAttributeByStandardClaims(mylist: string[]) {
+    return function(a1: Attribute, a2: Attribute) {
+      var claimNames = mylist;
+      let idx1 = claimNames.indexOf(a1.name);
+      let idx2 = claimNames.indexOf(a2.name);
+      if ((idx1 == -1) && (idx2 != -1)) { return 1;}
+      if ((idx2 == -1) && (idx1 != -1)) { return -1;}
+      if (idx1 > idx2) {return 1;}
+      if (idx1 < idx2) {return -1;}
+      return 0;
+    }
+  }
+
   private updateAttributes(identity) {
     this.reclaimService.getAttributes(identity).subscribe(attributes => {
-      this.attributes[identity.pubkey] = [];
-      this.requestedAttributes[identity.pubkey] = [];
-      this.requestedAttested = [];
-      if (attributes === null) {
-        this.getMissingAttributes(identity);
-        return;
-      }
-      let i;
-      for (i = 0; i < attributes.length; i++) {
-        this.attributes[identity.pubkey].push(attributes[i]);
-        if ((attributes[i].flag === '0') &&
-            this.oidcService.getScope().includes(attributes[i].name)) {
-          this.requestedAttributes[identity.pubkey].push(attributes[i]);
-        }
-        if ((attributes[i].flag === '1') &&
-            this.oidcService.getAttestedScope().includes(attributes[i].name)) {
-          this.requestedAttested[identity.pubkey].push(attributes[i]);
-        }
-      }
-      this.getMissingAttributes(identity);
-      this.getMissingAttested(identity);
+      this.requestedClaims[identity.pubkey] = [];
+      this.attributes[identity.pubkey] = 
attributes.sort(this.sortAttributeByStandardClaims(this.oidcService.getStandardClaimNames()));
+      this.updateMissingClaims(identity);
     },
     err => {
       this.errorInfos.push("Error retrieving attributes for ``" + 
identity.name + "''");
@@ -191,7 +180,7 @@ export class IdentityListComponent implements OnInit {
   }
 
   loginIdentity(identity) {
-    this.oidcService.setAttestations(this.requestedAttested[identity.pubkey]);
+    this.oidcService.setAttestations(this.requestedClaims[identity.pubkey]);
     this.oidcService.login(identity).subscribe(() => {
       console.log('Successfully logged in');
       this.authorize();
@@ -217,45 +206,119 @@ export class IdentityListComponent implements OnInit {
     return this.oidcService.inOpenIdFlow();
   }
 
-  getScopes() { return this.oidcService.getScope(); }
+  getScopes() { return this.oidcService.getRequestedScope(); }
 
-  getMissing(identity) {
+  getMissingClaims(identity) {
     const arr = [];
     let i = 0;
-    for (i = 0; i < this.missingAttributes[identity.pubkey].length; i++) {
-      arr.push(this.missingAttributes[identity.pubkey][i].name);
+    for (i = 0; i < this.missingClaims[identity.pubkey].length; i++) {
+      arr.push(this.missingClaims[identity.pubkey][i].name);
     }
     return arr;
   }
 
-  canAuthorize(identity) {
-    return this.inOpenIdFlow();
-  }
-
-  isRequested(identity, attribute) {
-    if (undefined === this.requestedAttributes[identity.pubkey]) {
+  isClaimRequested(identity, attribute) {
+    if (this.isProfileRequested() &&
+        this.oidcService.isStandardProfileClaim(attribute)) {
+      return true;
+    }
+    if (this.isEmailRequested() &&
+        this.oidcService.isStandardEmailClaim(attribute)) {
+      return true;
+    }
+    if (this.isPhoneRequested() &&
+        this.oidcService.isStandardPhoneClaim(attribute)) {
+      return true;
+    }
+    if (this.isAddressRequested() &&
+        this.oidcService.isStandardAddressClaim(attribute)) {
+      return true;
+    }
+    if (undefined === this.requestedClaims[identity.pubkey]) {
       return false;
     } else {
       return -1 !==
-        this.requestedAttributes[identity.pubkey].indexOf(attribute);
+        this.requestedClaims[identity.pubkey].indexOf(attribute);
     }
   }
 
-  isAttributeMissing(identity) {
+  isProfileRequested() {
     if (!this.inOpenIdFlow()) {
       return false;
     }
-    if (undefined === this.requestedAttributes[identity.pubkey]) {
+    return this.oidcService.isProfileRequested();
+  }
+
+  isEmailRequested() {
+    if (!this.inOpenIdFlow()) {
       return false;
     }
-    var scopes = this.getScopes();
-    for (var i = 0; i < this.requestedAttributes[identity.pubkey].length; i++) 
{
-      if (!scopes.includes(this.requestedAttributes[identity.pubkey][i].name))
-        {
-        return true;
-      }
+    return this.oidcService.isEmailRequested();
+  }
+
+  isPhoneRequested() {
+    if (!this.inOpenIdFlow()) {
+      return false;
     }
-    return false;
+    return this.oidcService.isPhoneRequested();
+  }
+
+  isAddressRequested() {
+    if (!this.inOpenIdFlow()) {
+      return false;
+    }
+    return this.oidcService.isAddressRequested();
+  }
+
+  isProfileMissing(identity) {
+    if (!this.inOpenIdFlow()) {
+      return false;
+    }
+    return this.oidcService.isProfileMissing(this.attributes[identity.pubkey]);
+  }
+
+  isEmailMissing(identity) {
+    if (!this.inOpenIdFlow()) {
+      return false;
+    }
+    return this.oidcService.isEmailMissing(this.attributes[identity.pubkey]);
+  }
+
+  isPhoneMissing(identity) {
+    if (!this.inOpenIdFlow()) {
+      return false;
+    }
+    return this.oidcService.isPhoneMissing(this.attributes[identity.pubkey]);
+  }
+
+  isRequestedScopeMissing(identity) {
+    return (this.isPhoneRequested() && this.isPhoneMissing(identity)) ||
+           (this.isEmailRequested() && this.isEmailMissing(identity)) ||
+           (this.isProfileRequested() && this.isProfileMissing(identity)) ||
+           (this.isAddressRequested() && this.isAddressMissing(identity));
+  }
+
+  isAddressMissing(identity) {
+    if (!this.inOpenIdFlow()) {
+      return false;
+    }
+    return this.oidcService.isAddressMissing(this.attributes[identity.pubkey]);
+  }
+
+  getProfileDescription() {
+    return this.oidcService.getScopeDescription("profile");
+  }
+
+  getEmailDescription() {
+    return this.oidcService.getScopeDescription("email");
+  }
+
+  getPhoneDescription() {
+    return this.oidcService.getScopeDescription("phone");
+  }
+
+  getAddressDescription() {
+    return this.oidcService.getScopeDescription("address");
   }
 
   hasAttributes(identity) {
@@ -297,36 +360,34 @@ export class IdentityListComponent implements OnInit {
     return this.isConnected() && 0 != this.identities.length;
   }
 
-  isAttestedMissing(identity) {
+  isClaimMissing(identity) {
     if (!this.inOpenIdFlow()) {
       return false;
     }
-    if (undefined === this.requestedAttested) {
+    if (undefined === this.requestedClaims) {
       return false;
     }
-    for (var i = 0; i < this.oidcService.getAttestedScope().length; i++) {
-      if (this.oidcService.getAttestedScope()[i][1] === true) {
+    var claims = this.oidcService.getRequestedClaims();
+    for (var i = 0; i < claims.length; i++) {
+      if (claims[i][1] === true) {
         var j;
-        for (j = 0; j < this.requestedAttested.length; j++) {
-          if (this.oidcService.getAttestedScope()[i][0] === 
this.requestedAttested[j].name){
-            break;
+        for (j = 0; j < this.requestedClaims.length; j++) {
+          if (claims[i][0] === this.requestedClaims[j].name){
+            return true;
           }
         }
-        if (j === this.requestedAttested.length){
-          return true;
-        }
       }
     }
     return false;
   }
 
   isAttestedRequested(identity: Identity, attribute: Attribute) {
-    if (undefined === this.requestedAttested[identity.pubkey]) {
+    if (undefined === this.requestedClaims[identity.pubkey]) {
       return false;
     } else {
-      for (var j = 0; j < this.requestedAttested[identity.pubkey].length; j++) 
{
+      for (var j = 0; j < this.requestedClaims[identity.pubkey].length; j++) {
         if ((attribute.flag === '1') &&
-            (attribute.name === 
this.requestedAttested[identity.pubkey][j].name)) {
+            (attribute.name === 
this.requestedClaims[identity.pubkey][j].name)) {
           return true;
         }
       }
@@ -345,17 +406,17 @@ export class IdentityListComponent implements OnInit {
     return false; //FIXME actually handle this 
https://gitlab.com/voggenre/ui/commit/dd9b6656dee7dbf59809dcc9bc2508ee70d8afe6
   }
 
-  getOptional(identity) {
+  getOptionalClaims(identity) {
     const arr = [];
     let i = 0;
     if (!this.inOpenIdFlow()) {
       return [];
     }
-    if (undefined === this.optionalAttested[identity.pubkey]) {
+    if (undefined === this.optionalClaims[identity.pubkey]) {
       return [];
     }
-    for (i = 0; i < this.optionalAttested[identity.pubkey].length; i++) {
-        arr.push(this.optionalAttested[identity.pubkey][i].name);
+    for (i = 0; i < this.optionalClaims[identity.pubkey].length; i++) {
+        arr.push(this.optionalClaims[identity.pubkey][i].name);
     }
     return arr;
   }
diff --git a/src/app/open-id.service.ts b/src/app/open-id.service.ts
index 7181445..6264783 100644
--- a/src/app/open-id.service.ts
+++ b/src/app/open-id.service.ts
@@ -14,6 +14,10 @@ export class OpenIdService {
   clientNameVerified: Boolean;
   clientName: String;
   referenceString: String;
+  scopesDescriptions = {"profile": "User profile access such as email, 
(nick)name, gender and birthdate.",
+                        "email": "Your email information.",
+                        "address": "Your physical address information.",
+                        "phone": "Your phone number."};
 
   constructor(private http: HttpClient,
     private config: ConfigService,
@@ -121,7 +125,7 @@ export class OpenIdService {
     return this.params['client_id'];
   }
 
-  getScope(): any {
+  getRequestedScope(): any {
     if (!this.inOpenIdFlow()) {
       return [];
     }
@@ -130,36 +134,202 @@ export class OpenIdService {
     }
 
     const scopes = this.params['scope'].split(' ');
+    /* Ignore openid scope */
     var i = scopes.indexOf('openid');
     if (i >= 0)
     {
       scopes.splice(i, 1);
     }
-    i = scopes.indexOf('profile');
-    if (i >= 0)
-    {
-      scopes.splice(i, 1);
-    }
     return scopes;
   }
 
-  getAttestedScope(): any {
+  getScopeDescription(scope: string) {
+    if (undefined === this.scopesDescriptions[scope]) {
+      return scope;
+    }
+    return this.scopesDescriptions[scope];
+  }
+
+  getScopesDescriptionList(): any {
+    var scopes = this.getRequestedScope();
+    var res = [];
+    for (var i = 0; i < scopes.length; i++) {
+      res.push(this.scopesDescriptions[scopes[i]])
+    }
+    return res;
+  }
+
+  isClaimsMissing(attributes: Attribute[], claims: Object): boolean {
+    for (let attr of attributes) {
+      for (let claim in claims) {
+        /* if any attribute for profile exists, we are good */
+        if (attr.name === claim) {
+          return false;
+        }
+      }
+    }
+    return false;
+  }
+
+  isProfileMissing(attributes: Attribute[]): boolean {
+    let profileClaims = this.getStandardProfileClaims();
+    return this.isClaimsMissing(attributes, profileClaims);
+  }
+
+  isEmailMissing(attributes: Attribute[]): boolean {
+    let profileClaims = this.getStandardEmailClaims();
+    return this.isClaimsMissing(attributes, profileClaims);
+  }
+
+  isPhoneMissing(attributes: Attribute[]): boolean {
+    let profileClaims = this.getStandardPhoneClaims();
+    return this.isClaimsMissing(attributes, profileClaims);
+  }
+
+  isAddressMissing(attributes: Attribute[]): boolean {
+    let profileClaims = this.getStandardAddressClaims();
+    return this.isClaimsMissing(attributes, profileClaims);
+  }
+
+  isProfileRequested(): boolean {
+    return this.getRequestedScope().include("profile");
+  }
+
+  isEmailRequested(): boolean {
+    return this.getRequestedScope().include("email");
+  }
+
+  isPhoneRequested(): boolean {
+    return this.getRequestedScope().include("phone");
+  }
+
+  isAddressRequested(): boolean {
+    return this.getRequestedScope().include("address");
+  }
+
+  getStandardProfileClaims(): Object {
+    return {"family_name": "Family name",
+            "given_name": "Given name",
+            "middle_name": "Middle name",
+            "nickname": "Nickname",
+            "preferred_username": "Preferred username",
+            //"profile": "Profile URL",
+            "picture": "Picture URL",
+            "website": "Website URL",
+            "gender": "Gender",
+            //"birthdate": "Birthdate YYYY-MM-DD", FIXME make pretty calendar
+            //"zoneinfo": "Timezone, e.g. Europe/Paris", Make pretty dropdown
+            //"locale": "Locale, e.g. en-US" Make pretty dropdown
+    };
+  }
+
+  getStandardEmailClaims(): Object {
+    return {"email": "Email address"};
+  }
+
+  getStandardPhoneClaims(): Object {
+    return {"phone": "Phone number"};
+  }
+
+  getStandardAddressClaims(): Object {
+    return {"street_address": "Street",
+            "locality": "City",
+            "region": "State, province or prefecture",
+            "postal_code": "Zip code",
+            "country": "Country"};
+  }
+
+  /**
+   * Return all claim names requested implicitly
+   * using scope and explicitly using claims parameter.
+   */
+  getClaimNamesForRequest(): string[] {
+    var scopes = this.getRequestedScope();
+    var result = [];
+    if (scopes.includes("profile")) {
+      result = result.concat(Object.keys(this.getStandardProfileClaims()));
+    }
+    if (scopes.includes("email")) {
+      result = result.concat(Object.keys(this.getStandardEmailClaims()));
+    }
+    if (scopes.includes("address")) {
+      result = result.concat(Object.keys(this.getStandardAddressClaims()));
+    }
+    if (scopes.includes("phone")) {
+      result = result.concat(Object.keys(this.getStandardPhoneClaims()));
+    }
+    result = result.concat(this.getRequestedClaimNames());
+
+    return result;
+  }
+
+  getStandardClaimNames(): string[] {
+    var result = [];
+    result = result.concat(Object.keys(this.getStandardProfileClaims()));
+    result = result.concat(Object.keys(this.getStandardEmailClaims()));
+    result = result.concat(Object.keys(this.getStandardAddressClaims()));
+    result = result.concat(Object.keys(this.getStandardPhoneClaims()));
+    return result;
+  }
+
+  getClaimDescription(claim: Attribute) {
+    if (undefined !== this.getStandardProfileClaims()[claim.name]) {
+      return this.getStandardProfileClaims()[claim.name];
+    }
+    if (undefined !== this.getStandardEmailClaims()[claim.name]) {
+      return this.getStandardEmailClaims()[claim.name];
+    }
+    if (undefined !== this.getStandardAddressClaims()[claim.name]) {
+      return this.getStandardAddressClaims()[claim.name];
+    }
+    if (undefined !== this.getStandardPhoneClaims()[claim.name]) {
+      return this.getStandardPhoneClaims()[claim.name];
+    }
+    return claim.name;
+  }
+
+  isStandardProfileClaim(attribute: Attribute): boolean {
+    return -1 != 
Object.keys(this.getStandardProfileClaims()).indexOf(attribute.name);
+  }
+
+  isStandardEmailClaim(attribute: Attribute): boolean {
+    return -1 != 
Object.keys(this.getStandardEmailClaims()).indexOf(attribute.name);
+  }
+
+  isStandardPhoneClaim(attribute: Attribute): boolean {
+    return -1 != 
Object.keys(this.getStandardPhoneClaims()).indexOf(attribute.name);
+  }
+
+  isStandardAddressClaim(attribute: Attribute): boolean {
+    return -1 != 
Object.keys(this.getStandardAddressClaims()).indexOf(attribute.name);
+  }
+
+  getRequestedClaims(): any {
     if (!this.inOpenIdFlow()) {
       return [];
     }
     if ((this.params['claims'] === "") || (this.params['claims'] === 
undefined)) {
       return [];
     }
-    var scope = [];
+    var claims = [];
     var json = JSON.parse(this.params['claims'])['userinfo'];
     for(var key in json)
     {
       if (json[key]['attestation'] === true)
         {
-          scope.push([key, json[key]['essential'], json[key]['attestation'], 
json[key]['format']]);
+          claims.push([key, json[key]['essential'], json[key]['attestation'], 
json[key]['format']]);
         }
     }
-    return scope;
+    return claims;
+  }
+
+  getRequestedClaimNames(): string[] {
+    var claimNames = [];
+    var claims = this.getRequestedClaims();
+    for (let claim in claims) {
+      claimNames.push(claim[0]);
+    }
+    return claimNames;
   }
 
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]