requestor_test.go 9.16 KB
Newer Older
1
2
3
4
package sessiontest

import (
	"encoding/json"
5
	"reflect"
6
7
8
9
	"testing"

	"github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/internal/test"
10
	"github.com/privacybydesign/irmago/irmaclient"
Sietse Ringers's avatar
Sietse Ringers committed
11
	"github.com/privacybydesign/irmago/server"
12
13
14
	"github.com/stretchr/testify/require"
)

15
func requestorSessionHelper(t *testing.T, request irma.SessionRequest, client *irmaclient.Client) *server.SessionResult {
16
	StartIrmaServer(t, false)
Sietse Ringers's avatar
Sietse Ringers committed
17
	defer StopIrmaServer()
18
19
20
21
22
23
24
25
	return requestorSesionWorker(t, request, client)
}

func requestorUpdatedSessionHelper(t *testing.T, request irma.SessionRequest, client *irmaclient.Client) *server.SessionResult {
	StartIrmaServer(t, true)
	defer StopIrmaServer()
	return requestorSesionWorker(t, request, client)
}
26

27
func requestorSesionWorker(t *testing.T, request irma.SessionRequest, client *irmaclient.Client) *server.SessionResult {
28
	if client == nil {
29
		client, _ = parseStorage(t)
30
31
		defer test.ClearTestStorage(t)
	}
32

33
	clientChan := make(chan *SessionResult)
Sietse Ringers's avatar
Sietse Ringers committed
34
	serverChan := make(chan *server.SessionResult)
35

36
	qr, token, err := irmaServer.StartSession(request, func(result *server.SessionResult) {
37
38
39
40
		serverChan <- result
	})
	require.NoError(t, err)

41
	h := TestHandler{t, clientChan, client, nil}
42
43
44
45
46
47
48
49
50
	j, err := json.Marshal(qr)
	require.NoError(t, err)
	client.NewSession(string(j), h)
	clientResult := <-clientChan
	if clientResult != nil {
		require.NoError(t, clientResult.Err)
	}

	serverResult := <-serverChan
51

52
53
54
55
	require.Equal(t, token, serverResult.Token)
	return serverResult
}

56
57
// Check that nonexistent IRMA identifiers in the session request fail the session
func TestRequestorInvalidRequest(t *testing.T) {
58
	StartIrmaServer(t, false)
59
60
61
62
63
64
65
66
	defer StopIrmaServer()
	_, _, err := irmaServer.StartSession(irma.NewDisclosureRequest(
		irma.NewAttributeTypeIdentifier("irma-demo.RU.foo.bar"),
		irma.NewAttributeTypeIdentifier("irma-demo.baz.qux.abc"),
	), nil)
	require.Error(t, err)
}

Sietse Ringers's avatar
Sietse Ringers committed
67
func TestRequestorSignatureSession(t *testing.T) {
68
	client, _ := parseStorage(t)
69
	id := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
70
	serverResult := requestorSessionHelper(t, irma.NewSignatureRequest("message", id), client)
71
72
73
74

	require.Nil(t, serverResult.Err)
	require.Equal(t, irma.ProofStatusValid, serverResult.ProofStatus)
	require.NotEmpty(t, serverResult.Disclosed)
75
76
	require.Equal(t, id, serverResult.Disclosed[0][0].Identifier)
	require.Equal(t, "456", serverResult.Disclosed[0][0].Value["en"])
77
78
79
80
81
82
83
84
85
86
87
88

	// Load the updated scheme in which an attribute was added to the studentCard credential type
	schemeid := irma.NewSchemeManagerIdentifier("irma-demo")
	client.Configuration.SchemeManagers[schemeid].URL = "http://localhost:48681/irma_configuration_updated/irma-demo"
	require.NoError(t, client.Configuration.UpdateSchemeManager(schemeid, nil))
	require.NoError(t, client.Configuration.ParseFolder())
	require.Contains(t, client.Configuration.AttributeTypes, irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.newAttribute"))

	// Check that the just created credential is still valid after the new attribute has been added
	_, status, err := serverResult.Signature.Verify(client.Configuration, nil)
	require.NoError(t, err)
	require.Equal(t, irma.ProofStatusValid, status)
89
90
}

Sietse Ringers's avatar
Sietse Ringers committed
91
func TestRequestorDisclosureSession(t *testing.T) {
92
	id := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
93
	request := irma.NewDisclosureRequest(id)
94
95
	serverResult := testRequestorDisclosure(t, request)
	require.Len(t, serverResult.Disclosed, 1)
96
97
	require.Equal(t, id, serverResult.Disclosed[0][0].Identifier)
	require.Equal(t, "456", serverResult.Disclosed[0][0].Value["en"])
98
}
99

100
func TestRequestorDisclosureMultipleAttrs(t *testing.T) {
101
102
103
104
	request := irma.NewDisclosureRequest(
		irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID"),
		irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.level"),
	)
105
106
107
108
109
	serverResult := testRequestorDisclosure(t, request)
	require.Len(t, serverResult.Disclosed, 2)
}

func testRequestorDisclosure(t *testing.T, request *irma.DisclosureRequest) *server.SessionResult {
110
	serverResult := requestorSessionHelper(t, request, nil)
111
112
113
	require.Nil(t, serverResult.Err)
	require.Equal(t, irma.ProofStatusValid, serverResult.ProofStatus)
	return serverResult
114
115
}

Sietse Ringers's avatar
Sietse Ringers committed
116
func TestRequestorIssuanceSession(t *testing.T) {
117
118
119
	testRequestorIssuance(t, false)
}

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
func TestRequestorCombinedSessionMultipleAttributes(t *testing.T) {
	var ir irma.IssuanceRequest
	require.NoError(t, irma.UnmarshalValidate([]byte(`{
		"type":"issuing",
		"credentials": [
			{
				"credential":"irma-demo.MijnOverheid.root",
				"attributes" : {
					"BSN":"12345"
				}
			}
		],
		"disclose" : [
			{
				"label":"Initialen",
				"attributes":["irma-demo.RU.studentCard.studentCardNumber"]
			},
			{
				"label":"Achternaam",
				"attributes" : ["irma-demo.RU.studentCard.studentID"]
			},
			{
				"label":"Geboortedatum",
				"attributes":["irma-demo.RU.studentCard.university"]
			}
		]
	}`), &ir))

148
	require.Equal(t, server.StatusDone, requestorSessionHelper(t, &ir, nil).Status)
149
150
}

151
func testRequestorIssuance(t *testing.T, keyshare bool) {
152
	attrid := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
153
	request := irma.NewIssuanceRequest([]*irma.CredentialRequest{{
154
155
156
157
158
159
160
161
162
163
164
165
		CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.RU.studentCard"),
		Attributes: map[string]string{
			"university":        "Radboud",
			"studentCardNumber": "31415927",
			"studentID":         "s1234567",
			"level":             "42",
		},
	}, {
		CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.root"),
		Attributes: map[string]string{
			"BSN": "299792458",
		},
166
	}}, attrid)
167
168
169
170
171
172
	if keyshare {
		request.Credentials = append(request.Credentials, &irma.CredentialRequest{
			CredentialTypeID: irma.NewCredentialTypeIdentifier("test.test.mijnirma"),
			Attributes:       map[string]string{"email": "testusername"},
		})
	}
173

174
	result := requestorSessionHelper(t, request, nil)
175
176
177
	require.Nil(t, result.Err)
	require.Equal(t, irma.ProofStatusValid, result.ProofStatus)
	require.NotEmpty(t, result.Disclosed)
178
179
180
181
182
	require.Equal(t, attrid, result.Disclosed[0][0].Identifier)
	require.Equal(t, "456", result.Disclosed[0][0].Value["en"])
}

func TestConDisCon(t *testing.T) {
183
	client, _ := parseStorage(t)
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
	ir := getMultipleIssuanceRequest()
	ir.Credentials = append(ir.Credentials, &irma.CredentialRequest{
		Validity:         ir.Credentials[0].Validity,
		CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
		Attributes: map[string]string{
			"firstnames": "Jan Hendrik",
			"firstname":  "Jan",
			"familyname": "Klaassen",
			"prefix":     "van",
		},
	})
	requestorSessionHelper(t, ir, client)

	dr := irma.NewDisclosureRequest()
	dr.Disclose = irma.AttributeConDisCon{
		irma.AttributeDisCon{
			irma.AttributeCon{
				irma.NewAttributeRequest("irma-demo.MijnOverheid.root.BSN"),
				irma.NewAttributeRequest("irma-demo.MijnOverheid.fullName.firstname"),
				irma.NewAttributeRequest("irma-demo.MijnOverheid.fullName.familyname"),
			},
			irma.AttributeCon{
				irma.NewAttributeRequest("irma-demo.RU.studentCard.studentID"),
				irma.NewAttributeRequest("irma-demo.RU.studentCard.university"),
			},
		},
		//irma.AttributeDisCon{
		//	irma.AttributeCon{
		//		irma.NewAttributeRequest("irma-demo.MijnOverheid.fullName.firstname"),
		//		irma.NewAttributeRequest("irma-demo.MijnOverheid.fullName.familyname"),
		//	},
		//},
	}

	requestorSessionHelper(t, dr, client)
219
}
220
221

func TestOptionalDisclosure(t *testing.T) {
222
	client, _ := parseStorage(t)
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
	university := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.university")
	studentid := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")

	radboud := "Radboud"
	attrs1 := irma.AttributeConDisCon{
		irma.AttributeDisCon{ // Including one non-optional disjunction is required in disclosure and signature sessions
			irma.AttributeCon{irma.AttributeRequest{Type: university}},
		},
		irma.AttributeDisCon{
			irma.AttributeCon{},
			irma.AttributeCon{irma.AttributeRequest{Type: studentid}},
		},
	}
	disclosed1 := [][]*irma.DisclosedAttribute{
		{
			{
				RawValue:   &radboud,
				Value:      map[string]string{"": radboud, "en": radboud, "nl": radboud},
				Identifier: irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.university"),
				Status:     irma.AttributeProofStatusPresent,
			},
		},
		{},
	}
	attrs2 := irma.AttributeConDisCon{ // In issuance sessions, it is allowed that all disjunctions are optional
		irma.AttributeDisCon{
			irma.AttributeCon{},
			irma.AttributeCon{irma.AttributeRequest{Type: studentid}},
		},
	}
	disclosed2 := [][]*irma.DisclosedAttribute{{}}

	tests := []struct {
		request   irma.SessionRequest
		attrs     irma.AttributeConDisCon
		disclosed [][]*irma.DisclosedAttribute
	}{
		{irma.NewDisclosureRequest(), attrs1, disclosed1},
		{irma.NewSignatureRequest("message"), attrs1, disclosed1},
		{getIssuanceRequest(true), attrs1, disclosed1},
		{getIssuanceRequest(true), attrs2, disclosed2},
	}

	for _, args := range tests {
		args.request.Disclosure().Disclose = args.attrs

		// TestHandler always prefers the first option when given any choice, so it will not disclose the optional attribute
		result := requestorSessionHelper(t, args.request, client)
		require.True(t, reflect.DeepEqual(args.disclosed, result.Disclosed))
	}
}