Skip to content

Commit 494a237

Browse files
Merge pull request #57 from authlete/feature/mdoc
[feature] issuance of mdoc-based verifiable credentials
2 parents 4bad192 + 932381b commit 494a237

File tree

8 files changed

+491
-18
lines changed

8 files changed

+491
-18
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
<authlete.java.common.version>3.88</authlete.java.common.version>
1616
<authlete.java.jaxrs.version>2.70</authlete.java.jaxrs.version>
17+
<authlete.cbor.version>1.13</authlete.cbor.version>
1718
<javax.servlet-api.version>3.0.1</javax.servlet-api.version>
1819
<jersey.version>2.30.1</jersey.version>
1920
<jetty.version>9.4.27.v20200227</jetty.version>
@@ -61,6 +62,12 @@
6162
<version>${authlete.java.jaxrs.version}</version>
6263
</dependency>
6364

65+
<dependency>
66+
<groupId>com.authlete</groupId>
67+
<artifactId>cbor</artifactId>
68+
<version>${authlete.cbor.version}</version>
69+
</dependency>
70+
6471
<dependency>
6572
<groupId>javax.servlet</groupId>
6673
<artifactId>javax.servlet-api</artifactId>

src/main/java/com/authlete/jaxrs/server/api/vci/AbstractCredentialEndpoint.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import com.authlete.jaxrs.server.vc.UnsupportedCredentialFormatException;
4040
import com.authlete.jaxrs.server.vc.UnsupportedCredentialTypeException;
4141
import com.google.gson.Gson;
42-
import com.google.gson.GsonBuilder;
4342

4443

4544
public abstract class AbstractCredentialEndpoint extends BaseResourceEndpoint
@@ -298,18 +297,14 @@ private OrderFormat getOrderFormat(CredentialRequestInfo info) throws Unsupporte
298297

299298
protected String errorJson(ErrorCode errorCode, Throwable cause)
300299
{
301-
Map<String, Object> map = new LinkedHashMap<>();
302-
303-
// "error"
304-
map.put("error", errorCode.name());
305-
306-
if (cause != null)
300+
if (cause == null)
307301
{
308-
// "error_description"
309-
map.put("error_description", cause.getMessage());
302+
return String.format(
303+
"{%n \"error\": \"%s\"%n}%n", errorCode.name());
310304
}
311305

312-
// The content of the error response.
313-
return new GsonBuilder().setPrettyPrinting().create().toJson(map);
306+
return String.format(
307+
"{%n \"error\": \"%s\",%n \"error_description\": \"%s\"%n}%n",
308+
errorCode.name(), cause.getMessage());
314309
}
315310
}

src/main/java/com/authlete/jaxrs/server/api/vci/CredentialOfferPageModel.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ public class CredentialOfferPageModel extends AuthorizationPageModel
5858

5959

6060
private static final String DEFAULT_CREDENTIALS = "[\n" +
61-
" \"IdentityCredential\"\n" +
61+
" \"IdentityCredential\",\n" +
62+
" \"mDL\"\n" +
6263
"]";
6364

6465

src/main/java/com/authlete/jaxrs/server/db/UserDao.java

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2016-2022 Authlete, Inc.
2+
* Copyright (C) 2016-2023 Authlete, Inc.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,12 +19,17 @@
1919

2020
import java.time.LocalDate;
2121
import java.time.ZoneOffset;
22+
import java.util.ArrayList;
2223
import java.util.Arrays;
2324
import java.util.Date;
2425
import java.util.HashMap;
26+
import java.util.LinkedHashMap;
27+
import java.util.List;
2528
import java.util.Map;
2629
import com.authlete.common.dto.Address;
2730
import com.authlete.common.types.User;
31+
import com.authlete.mdoc.constants.MDLClaimNames;
32+
import com.authlete.mdoc.constants.MDLConstants;
2833

2934

3035
/**
@@ -68,12 +73,65 @@ public class UserDao
6873
null, null, "Inga", "Silverstone", null, null,
6974
"https://example.com/inga/profile", "https://example.com/inga/me.jpg",
7075
"https://example.com/inga/", "female", "America/Toronto", "en-US",
71-
"inga", "1991-11-06", toDate("2022-04-30")
72-
)
76+
"inga", "1991-11-06", toDate("2022-04-30"))
77+
.setAttribute(MDLConstants.DOC_TYPE_MDL, createMDLData1004())
7378
);
7479
};
7580

7681

82+
private static Map<String, Object> createMDLData1004()
83+
{
84+
// Some string claim values in the data below have the prefix "cbor:".
85+
// They are interpreted by Authlete server. See the JavaDoc of the
86+
// CredentialIssuanceOrder class in the authlete-java-common library
87+
// for details.
88+
//
89+
// CredentialIssuerOrder JavaDoc
90+
// https://authlete.github.io/authlete-java-common/com/authlete/common/dto/CredentialIssuanceOrder.html
91+
//
92+
93+
// {
94+
// "vehicle_category_code" : "A",
95+
// "issue_date" : "2023-01-01",
96+
// "expiry_date" : "2043-01-01"
97+
// }
98+
Map<String, Object> vehicleA = new LinkedHashMap<>();
99+
vehicleA.put("vehicle_category_code", "A");
100+
vehicleA.put("issue_date", "cbor:1004(\"2023-01-01\")");
101+
vehicleA.put("expiry_date", "cbor:1004(\"2043-01-01\")");
102+
103+
// [
104+
// vehicleA
105+
// ]
106+
List<Map<String, Object>> drivingPrivileges = new ArrayList<>();
107+
drivingPrivileges.add(vehicleA);
108+
109+
// {
110+
// "family_name" : "Silverstone",
111+
// "given_name" : "Inga",
112+
// "birth_date" : "1991-11-06",
113+
// "issuing_country" : "US",
114+
// "document_number" : "12345678",
115+
// "driving_privileges" : drivingPrivileges
116+
// }
117+
Map<String, Object> nameSpace = new LinkedHashMap<>();
118+
nameSpace.put(MDLClaimNames.FAMILY_NAME, "Silverstone");
119+
nameSpace.put(MDLClaimNames.GIVEN_NAME, "Inga");
120+
nameSpace.put(MDLClaimNames.BIRTH_DATE, "cbor:1004(\"1991-11-06\")");
121+
nameSpace.put(MDLClaimNames.ISSUING_COUNTRY, "US");
122+
nameSpace.put(MDLClaimNames.DOCUMENT_NUMBER, "12345678");
123+
nameSpace.put(MDLClaimNames.DRIVING_PRIVILEGES, drivingPrivileges);
124+
125+
// {
126+
// "org.iso.18013.5.1" : nameSpace
127+
// }
128+
Map<String, Object> root = new LinkedHashMap<>();
129+
root.put(MDLConstants.NAME_SPACE_MDL, nameSpace);
130+
131+
return root;
132+
}
133+
134+
77135
private static Date toDate(String input)
78136
{
79137
return Date.from(LocalDate.parse(input).atStartOfDay().toInstant(ZoneOffset.UTC));

src/main/java/com/authlete/jaxrs/server/db/UserEntity.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.Serializable;
2121
import java.net.URI;
2222
import java.util.Date;
23+
import java.util.HashMap;
2324
import java.util.List;
2425
import java.util.Map;
2526
import com.authlete.common.dto.Address;
@@ -107,6 +108,10 @@ public class UserEntity implements User, Serializable
107108
private List<String> nationalities;
108109

109110

111+
// Attributes
112+
private Map<String, Object> attributes = new HashMap<>();
113+
114+
110115
/**
111116
* Constructor with initial values.
112117
*/
@@ -372,12 +377,19 @@ public Object getAttribute(String attributeName)
372377
return code;
373378

374379
default:
375-
// Unsupported attribute.
376-
return null;
380+
return attributes.get(attributeName);
377381
}
378382
}
379383

380384

385+
public UserEntity setAttribute(String attributeName, Object attributeValue)
386+
{
387+
attributes.put(attributeName, attributeValue);
388+
389+
return this;
390+
}
391+
392+
381393
public List<String> getNationalities()
382394
{
383395
return nationalities;
@@ -403,6 +415,6 @@ private static Map<String, Object> toMap(Address address)
403415
// This Gson instance does not serialize properties with null values.
404416
Gson gson = new Gson();
405417

406-
return (Map<String, Object>)gson.fromJson(gson.toJson(address), Map.class);
418+
return gson.fromJson(gson.toJson(address), Map.class);
407419
}
408420
}

src/main/java/com/authlete/jaxrs/server/vc/AbstractOrderProcessor.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private CredentialIssuanceOrder createOrder(
114114
.setRequestIdentifier(info.getIdentifier())
115115
.setCredentialPayload(payload)
116116
.setIssuanceDeferred(deferred)
117+
.setCredentialDuration(computeCredentialDuration())
117118
;
118119
}
119120

@@ -167,4 +168,22 @@ protected abstract void checkPermissions(
167168
protected abstract Map<String, Object> collectClaims(
168169
OrderContext context, User user, String format,
169170
Map<String, Object> requestedCredential) throws VerifiableCredentialException;
171+
172+
173+
/**
174+
* Compute the credential duration in seconds.
175+
*
176+
* <p>
177+
* The default implementation of this method returns 0, which tells
178+
* Authlete to try to generate a VC that does not expire. Subclasses
179+
* may override this method to set duration.
180+
* </p>
181+
*
182+
* @return
183+
* The credential duration in seconds.
184+
*/
185+
protected long computeCredentialDuration()
186+
{
187+
return 0;
188+
}
170189
}

0 commit comments

Comments
 (0)