Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: introduce pairing support to protect against shoulder surfing #98

Merged
merged 77 commits into from
Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
61a8f6b
Feat: introduce binding support to protect against shoulder surfing
ivard Jun 9, 2020
7ff0ab0
Refactor: minor code style changes
ivard Jun 9, 2020
234a219
Added more tests for binding and fixed usage variable name clientAuth
ivard Jun 10, 2020
c754c0d
Make irma session fully support binding
ivard Jun 10, 2020
4b316ca
Added support for responding to binding message in irma session
ivard Jun 10, 2020
44d39c4
Introduce binding as a separate server status
ivard Jun 10, 2020
f3a401d
Minor fixes for shoulder surfing feature
ivard Jun 10, 2020
e9561e6
Changed outline of frontend endpoints for binding
ivard Jul 8, 2020
97a06a4
Added binding method to option request
ivard Jul 9, 2020
ccea19e
Added binding method to session options struct
ivard Jul 9, 2020
00d7ea7
Improve comment to explain session state check
ivard Jul 13, 2020
758bd0f
Simplify unmarshalling of SessionInfo struct
ivard Jul 27, 2020
0b223ac
Some code refactors and improved error handling
ivard Jul 28, 2020
0526c38
Code refactors in irma cmd package
ivard Jul 29, 2020
34f66b9
Refactored sessiontest to better integrate binding support
ivard Jul 30, 2020
e3fe42d
Refactor type of irma.BackendToken
ivard Aug 3, 2020
edbd13e
Refactor type of irma.ClientToken
ivard Aug 3, 2020
6117add
Refactor type of irma.FrontendToken
ivard Aug 3, 2020
627b1b6
Include authenticationMiddleware in handleSessionGet
ivard Aug 3, 2020
4e27593
Improved error handling in irmaclient's session.go
ivard Aug 3, 2020
9d6f345
Let handleGetInfo return an interface instead of two values
ivard Aug 3, 2020
92c4e43
Do an early return in updateFrontendOptions
ivard Aug 3, 2020
8a1e2bd
Remove duplicate assignment to binding method field
ivard Aug 3, 2020
bc8963e
Improved checkCache documentation
ivard Aug 3, 2020
075b129
Cancel sse channel when closing it prematurely
ivard Aug 4, 2020
599fe63
Move handleBinding to session.go + fix session options marshalling
ivard Aug 4, 2020
f8c6cad
Split off request binding permission in separate function
ivard Aug 4, 2020
7319dc3
Improved request binding permission instruction
ivard Aug 4, 2020
1a650f3
Refactor: Move ClientRequest to irma package
ivard Aug 4, 2020
1fbedbe
Small refactors and improvement of comments
ivard Aug 4, 2020
e79b135
Minor improvements
ivard Aug 5, 2020
4ad743d
Return error in getClientRequest and getRequest instead of RemoteError
ivard Aug 5, 2020
5889b0b
Rename server.Status type and move to irma package
ivard Sep 3, 2020
3e6a02e
Use reflection to set maxVersion on irmaclient in tests
ivard Sep 4, 2020
fde6f41
Remove pointer usage for SessionDismisser in tests
ivard Sep 4, 2020
acdb670
Refactor BackendToken to RequestorToken
ivard Sep 4, 2020
736c713
Refactor FrontendToken to FrontendAuthorization
ivard Sep 4, 2020
a056cf3
Improve error handling of SetFrontendOptions and BindingCompleted
ivard Sep 4, 2020
43e0692
Make comment on ServerStatusBinding more clear
ivard Sep 4, 2020
ffbddf8
Use early return in bindingHandler
ivard Sep 4, 2020
cd3d9fb
Check error type in TestIssuanceBinding
ivard Sep 4, 2020
8e9ea56
Implement Validate method for ClientRequest
ivard Sep 4, 2020
96f7b87
In cmd's postRequest return nil for transport when returning an error
ivard Sep 4, 2020
ded859f
Add library call to irma server to subscribe on statuses using channels
ivard Sep 4, 2020
d33e947
Fixed ServerStatus refactor in TestIssueExpiredKey
ivard Sep 4, 2020
7bd962d
Fixed spelling mistake in comment getSessionInfo
ivard Sep 6, 2020
491b557
Fail if client diverts from protocol in handleGetClientRequest
ivard Sep 6, 2020
85d66d8
Revert earlier change of returning pointers to session request in han…
ivard Sep 6, 2020
e6ced48
Make GetSessionStatus to only accept requestor tokens
ivard Sep 29, 2020
c9aa64b
Add comment to explain use of reflection in ClientRequest's Validate
ivard Sep 29, 2020
88e6ed2
Use buffered channel for status updates
ivard Oct 6, 2020
2010853
Test for specific error when disabling binding after client connected
ivard Oct 6, 2020
57c03d9
Some more code style fixes
ivard Oct 6, 2020
d884570
Fixed WaitStatus spawning multiple nil's on error channel
ivard Oct 7, 2020
f8f6627
Remove code duplication in extracting private fields using reflection
ivard Oct 8, 2020
0452d41
refactor: rename GetSessionStatus server function to SessionStatus
sietseringers Oct 9, 2020
b784f64
Updated CHANGELOG
ivard Oct 14, 2020
c976ada
Fixed handleBinding wrapping a SessionError in a SessionError
ivard Oct 23, 2020
f44f557
Refactor: rename binding to pairing
ivard Nov 5, 2020
74bcf91
Added missing Validate function for OptionsRequest
ivard Nov 13, 2020
1d6db3d
Introduce PairingRecommended field in Qr
ivard Dec 3, 2020
4adabfc
Shorten pairing recommended json tag and omit when false
ivard Dec 10, 2020
4e5639e
Updated CHANGELOG
ivard Dec 10, 2020
b8f5a11
Remove pointer to bool in Qr struct
ivard Dec 11, 2020
451c612
Improved CHANGELOG
ivard Dec 15, 2020
761a547
refactor: decrease indentation level in wait_status.go
sietseringers Mar 19, 2021
c211db0
refactor: decrease indentation level in irmaserver.session.onUpdate()
sietseringers Mar 19, 2021
e861fc7
feat: add new status endpoint for frontend
sietseringers Mar 22, 2021
e12a297
feat: also add new statusevents endpoint for frontend
sietseringers Mar 22, 2021
a8bd786
refactor: rename OptionsRequest to FrontendOptionsRequest
sietseringers Mar 22, 2021
ebf3ec5
feat: StartSession function and endpoint now return frontend-specific…
sietseringers Mar 23, 2021
0318100
feat: make chained sessions use the same frontend authorization token
sietseringers Mar 23, 2021
08ae605
refactor: rename ClientRequest to ClientSessionRequest
sietseringers Mar 25, 2021
70713d0
fix: incorrect early return in SSE event handler
sietseringers Mar 25, 2021
c85ea36
feat: clarify FrontendOptionsRequest Validate error message
sietseringers Mar 25, 2021
4f8737c
feat: assign protocol version 2.8 to pairing
sietseringers Mar 25, 2021
2b248d7
feat: always allow pairing when using chained sessions
sietseringers Mar 25, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.0] - 2021-03-17
### Added
* Support for device pairing to prevent shoulder surfing (i.e. make it impossible for someone in close physical proximity to a user to scan the QR code that was meant for the user)
* Introduced new frontend endpoints to manage device pairing
* The API of the `irmaserver` package has two new functions `SetFrontendOptions` and `PairingCompleted`
* A new server status `"PAIRING"` is introduced
* A new function `SessionStatus` is available in the API of the `irmaserver` to get a channel with status updates of an IRMA session

### Changes
* The `server.SessionPackage` struct now contains an extra field `FrontendAuth`
* The `irma.Qr` struct now contains an optional field `PairingRecommended` (named `pairingHint` when being marshalled to JSON) that is set to true when pairing is recommended for that session, as indication to the frontend
* The `StartSession` function from the API of the `irmaserver` package now returns three values: the session pointer (type *irma.QR), the requestor token (type irma.RequestorToken) and the frontend authorization token (type irma.FrontendAuthorization)
* The `token` parameter, as used by most functions in the API of the `irmaserver` package, now has the type `irma.RequestorToken`
* The `server.Status` type has been moved to `irma.ServerStatus`; the related constants are also moved, e.g. from `server.StatusInitialized` to `irma.ServerStatusInitialized`

ivard marked this conversation as resolved.
Show resolved Hide resolved
## [0.7.0] - 2021-03-17
### Fixed
* Bug causing scheme updating to fail if OS temp dir is on other file system than the schemes
Expand Down Expand Up @@ -155,6 +170,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Combined issuance-disclosure requests with two schemes one of which has a keyshare server now work as expected
- Various other bugfixes

[0.8.0]: https://github.com/privacybydesign/irmago/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/privacybydesign/irmago/compare/v0.6.1...v0.7.0
[0.6.1]: https://github.com/privacybydesign/irmago/compare/v0.6.0...v0.6.1
[0.6.0]: https://github.com/privacybydesign/irmago/compare/v0.5.1...v0.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-retryablehttp v0.6.2
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jasonlvhit/gocron v0.0.0-20180312192515-54194c9749d4
github.com/jinzhu/gorm v1.9.12
github.com/lib/pq v1.3.0 // indirect
Expand All @@ -26,6 +27,7 @@ require (
github.com/onsi/ginkgo v1.12.0 // indirect
github.com/onsi/gomega v1.9.0 // indirect
github.com/privacybydesign/gabi v0.0.0-20210409092845-6113e0d3ec81
github.com/pelletier/go-toml v1.2.0 // indirect
github.com/sietseringers/cobra v1.0.1-0.20200909200314-c50c3838234b
github.com/sietseringers/go-sse v0.0.0-20200801161811-e2cf2c63ca50
github.com/sietseringers/pflag v1.0.4-0.20200909193609-0cde7e893819
Expand Down
11 changes: 11 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
Expand Down Expand Up @@ -274,8 +275,13 @@ github.com/spf13/afero v1.2.0 h1:O9FblXGxoTc51M+cqr74Bm2Tmt4PvkA5iu/j8HrkNuY=
github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
Expand All @@ -292,13 +298,15 @@ github.com/timshannon/bolthold v0.0.0-20180829183128-83840edea944/go.mod h1:jUig
github.com/timshannon/bolthold v0.0.0-20190812165541-a85bcc049a2e h1:FC5JjwU5y5ZBR/vH8LhmPman3k5dep45jRyCpR1VDVQ=
github.com/timshannon/bolthold v0.0.0-20190812165541-a85bcc049a2e/go.mod h1:jUigdmrbdCxcIDEFrq82t4X9805XZfwFZoYUap0ET/U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/x448/float16 v0.8.3/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.0/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
Expand Down Expand Up @@ -350,6 +358,7 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
Expand Down Expand Up @@ -425,6 +434,7 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand All @@ -440,6 +450,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
Expand Down
16 changes: 13 additions & 3 deletions internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ var ForceHTTPS = true
const (
sessionChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
sessionTokenLength = 20
pairingCodeChars = "0123456789"
pairingCodeLength = 4
)

// AssertPathExists returns nil only if it has been successfully
Expand Down Expand Up @@ -273,15 +275,23 @@ type SSECtx struct {
}

func NewSessionToken() string {
r := make([]byte, sessionTokenLength)
return newRandomString(sessionTokenLength, sessionChars)
}

func NewPairingCode() string {
return newRandomString(pairingCodeLength, pairingCodeChars)
}

func newRandomString(count int, characterSet string) string {
r := make([]byte, count)
_, err := rand.Read(r)
if err != nil {
panic(err)
}

b := make([]byte, sessionTokenLength)
b := make([]byte, count)
for i := range b {
b[i] = sessionChars[r[i]%byte(len(sessionChars))]
b[i] = characterSet[r[i]%byte(len(characterSet))]
}
return string(b)
}
Expand Down
16 changes: 14 additions & 2 deletions internal/sessiontest/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ type TestHandler struct {
expectedServerName *irma.RequestorInfo
wait time.Duration
result string
pairingCodeChan chan string
dismisser irmaclient.SessionDismisser
frontendTransport *irma.HTTPTransport
}

func (th TestHandler) KeyshareEnrollmentIncomplete(manager irma.SchemeManagerIdentifier) {
Expand All @@ -96,7 +99,7 @@ func (th TestHandler) KeyshareEnrollmentMissing(manager irma.SchemeManagerIdenti
func (th TestHandler) KeyshareEnrollmentDeleted(manager irma.SchemeManagerIdentifier) {
th.Failure(&irma.SessionError{Err: errors.Errorf("Keyshare enrollment deleted for %s", manager.String())})
}
func (th TestHandler) StatusUpdate(action irma.Action, status irma.Status) {}
func (th TestHandler) StatusUpdate(action irma.Action, status irma.ClientStatus) {}
func (th *TestHandler) Success(result string) {
th.result = result
th.c <- nil
Expand Down Expand Up @@ -150,6 +153,15 @@ func (th TestHandler) RequestSchemeManagerPermission(manager *irma.SchemeManager
func (th TestHandler) RequestPin(remainingAttempts int, callback irmaclient.PinHandler) {
callback(true, "12345")
}
func (th TestHandler) PairingRequired(pairingCode string) {
// Send pairing code via channel to calling test. This is done such that
// calling tests can detect it when this handler is skipped unexpectedly.
if th.pairingCodeChan != nil {
th.pairingCodeChan <- pairingCode
return
}
th.Failure(&irma.SessionError{ErrorType: irma.ErrorType("Pairing required")})
}

type SessionResult struct {
Err error
Expand Down Expand Up @@ -197,7 +209,7 @@ type ManualTestHandler struct {
action irma.Action
}

func (th *ManualTestHandler) StatusUpdate(action irma.Action, status irma.Status) {
func (th *ManualTestHandler) StatusUpdate(action irma.Action, status irma.ClientStatus) {
th.action = action
}

Expand Down
36 changes: 36 additions & 0 deletions internal/sessiontest/legacy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,39 @@ func TestSessionUsingLegacyStorage(t *testing.T) {
// Test whether credential is still there after the storage has been reloaded
sessionHelper(t, getDisclosureRequest(idRoot), "verification", client)
}

func TestWithoutPairingSupport(t *testing.T) {
defaultMaxVersion := maxClientVersion
defer func() {
maxClientVersion = defaultMaxVersion
}()
maxClientVersion = &irma.ProtocolVersion{Major: 2, Minor: 7}

t.Run("TestSigningSession", TestSigningSession)
t.Run("TestDisclosureSession", TestDisclosureSession)
t.Run("TestNoAttributeDisclosureSession", TestNoAttributeDisclosureSession)
t.Run("TestEmptyDisclosure", TestEmptyDisclosure)
t.Run("TestIssuanceSession", TestIssuanceSession)
t.Run("TestMultipleIssuanceSession", TestMultipleIssuanceSession)
t.Run("TestDefaultCredentialValidity", TestDefaultCredentialValidity)
t.Run("TestIssuanceDisclosureEmptyAttributes", TestIssuanceDisclosureEmptyAttributes)
t.Run("TestIssuanceOptionalZeroLengthAttributes", TestIssuanceOptionalZeroLengthAttributes)
t.Run("TestIssuanceOptionalSetAttributes", TestIssuanceOptionalSetAttributes)
t.Run("TestIssuanceSameAttributesNotSingleton", TestIssuanceSameAttributesNotSingleton)
t.Run("TestIssuancePairing", TestIssuancePairing)
t.Run("TestLargeAttribute", TestLargeAttribute)
t.Run("TestIssuanceSingletonCredential", TestIssuanceSingletonCredential)
t.Run("TestUnsatisfiableDisclosureSession", TestUnsatisfiableDisclosureSession)
t.Run("TestAttributeByteEncoding", TestAttributeByteEncoding)
t.Run("TestOutdatedClientIrmaConfiguration", TestOutdatedClientIrmaConfiguration)
t.Run("TestDisclosureNewAttributeUpdateSchemeManager", TestDisclosureNewAttributeUpdateSchemeManager)
t.Run("TestIssueNewAttributeUpdateSchemeManager", TestIssueNewAttributeUpdateSchemeManager)
t.Run("TestIssueOptionalAttributeUpdateSchemeManager", TestIssueOptionalAttributeUpdateSchemeManager)
t.Run("TestIssueNewCredTypeUpdateSchemeManager", TestIssueNewCredTypeUpdateSchemeManager)
t.Run("TestDisclosureNewCredTypeUpdateSchemeManager", TestDisclosureNewCredTypeUpdateSchemeManager)
t.Run("TestDisclosureNonexistingCredTypeUpdateSchemeManager", TestDisclosureNonexistingCredTypeUpdateSchemeManager)
t.Run("TestStaticQRSession", TestStaticQRSession)
t.Run("TestIssuedCredentialIsStored", TestIssuedCredentialIsStored)
t.Run("TestPOSTSizeLimit", TestPOSTSizeLimit)
t.Run("TestDisablePairing", TestDisablePairing)
}
77 changes: 70 additions & 7 deletions internal/sessiontest/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
"time"
"unsafe"

jwt "github.com/dgrijalva/jwt-go"
irma "github.com/privacybydesign/irmago"
Expand All @@ -18,6 +20,9 @@ import (
"github.com/stretchr/testify/require"
)

// Defines the maximum protocol version of an irmaclient in tests
var maxClientVersion = &irma.ProtocolVersion{Major: 2, Minor: 8}

func TestMain(m *testing.M) {
// Create HTTP server for scheme managers
test.StartSchemeManagerHttpServer()
Expand All @@ -44,6 +49,12 @@ func parseExistingStorage(t *testing.T, storage string) (*irmaclient.Client, *Te
handler,
)
require.NoError(t, err)

// Set max version we want to test on
version := extractClientMaxVersion(client)
version.Major = maxClientVersion.Major
version.Minor = maxClientVersion.Minor

client.SetPreferences(irmaclient.Preferences{DeveloperMode: true})
return client, handler
}
Expand Down Expand Up @@ -120,7 +131,7 @@ func getMultipleIssuanceRequest() *irma.IssuanceRequest {

var TestType = "irmaserver-jwt"

func startSession(t *testing.T, request irma.SessionRequest, sessiontype string) *server.SessionPackage {
func startSession(t *testing.T, request irma.SessionRequest, sessiontype string) (*server.SessionPackage, *irma.FrontendSessionRequest) {
var (
sesPkg server.SessionPackage
err error
Expand All @@ -141,7 +152,7 @@ func startSession(t *testing.T, request irma.SessionRequest, sessiontype string)
}

require.NoError(t, err)
return &sesPkg
return &sesPkg, sesPkg.FrontendRequest
}

func getJwt(t *testing.T, request irma.SessionRequest, sessiontype string, alg jwt.SigningMethod) string {
Expand Down Expand Up @@ -189,7 +200,14 @@ func getJwt(t *testing.T, request irma.SessionRequest, sessiontype string, alg j
return j
}

func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client) string {
func sessionHelperWithFrontendOptions(
t *testing.T,
request irma.SessionRequest,
sessiontype string,
client *irmaclient.Client,
frontendOptionsHandler func(handler *TestHandler),
pairingHandler func(handler *TestHandler),
) string {
if client == nil {
var handler *TestClientHandler
client, handler = parseStorage(t)
Expand All @@ -201,25 +219,70 @@ func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string
defer StopRequestorServer()
}

sesPkg := startSession(t, request, sessiontype)
sesPkg, frontendRequest := startSession(t, request, sessiontype)

c := make(chan *SessionResult)
h := &TestHandler{t: t, c: c, client: client, expectedServerName: expectedRequestorInfo(t, client.Configuration)}
h := &TestHandler{
t: t,
c: c,
client: client,
expectedServerName: expectedRequestorInfo(t, client.Configuration),
}

if frontendOptionsHandler != nil || pairingHandler != nil {
h.pairingCodeChan = make(chan string)
h.frontendTransport = irma.NewHTTPTransport(sesPkg.SessionPtr.URL, false)
h.frontendTransport.SetHeader(irma.AuthorizationHeader, string(frontendRequest.Authorization))
}
if frontendOptionsHandler != nil {
frontendOptionsHandler(h)
}

qrjson, err := json.Marshal(sesPkg.SessionPtr)
require.NoError(t, err)
client.NewSession(string(qrjson), h)
h.dismisser = client.NewSession(string(qrjson), h)

if pairingHandler != nil {
pairingHandler(h)
}

if result := <-c; result != nil {
require.NoError(t, result.Err)
}

var resJwt string
err = irma.NewHTTPTransport("http://localhost:48682/session/"+sesPkg.Token, false).Get("result-jwt", &resJwt)
err = irma.NewHTTPTransport("http://localhost:48682/session/"+string(sesPkg.Token), false).Get("result-jwt", &resJwt)
require.NoError(t, err)

return resJwt
}

func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client) string {
return sessionHelperWithFrontendOptions(t, request, sessiontype, client, nil, nil)
}

func extractClientTransport(dismisser irmaclient.SessionDismisser) *irma.HTTPTransport {
return extractPrivateField(dismisser, "transport").(*irma.HTTPTransport)
}

func extractClientMaxVersion(client *irmaclient.Client) *irma.ProtocolVersion {
return extractPrivateField(client, "maxVersion").(*irma.ProtocolVersion)
}

func extractPrivateField(i interface{}, field string) interface{} {
rct := reflect.ValueOf(i).Elem().FieldByName(field)
return reflect.NewAt(rct.Type(), unsafe.Pointer(rct.UnsafeAddr())).Elem().Interface()
}

func setPairingMethod(method irma.PairingMethod, handler *TestHandler) string {
optionsRequest := irma.NewFrontendOptionsRequest()
optionsRequest.PairingMethod = method
options := &irma.SessionOptions{}
err := handler.frontendTransport.Post("frontend/options", options, optionsRequest)
require.NoError(handler.t, err)
return options.PairingCode
}

func expectedRequestorInfo(t *testing.T, conf *irma.Configuration) *irma.RequestorInfo {
if common.ForceHTTPS {
return irma.NewRequestorInfo("localhost")
Expand Down
Loading