Commit d883a3e2 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Use issuer name as server name in (single-issuer) issuance requests

parent ce7ba3d0
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/privacybydesign/irmago" "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/irmaclient" "github.com/privacybydesign/irmago/irmaclient"
"github.com/stretchr/testify/require"
) )
type TestClientHandler struct { type TestClientHandler struct {
...@@ -60,9 +61,10 @@ func (i *TestClientHandler) ChangePinBlocked(manager irma.SchemeManagerIdentifie ...@@ -60,9 +61,10 @@ func (i *TestClientHandler) ChangePinBlocked(manager irma.SchemeManagerIdentifie
} }
type TestHandler struct { type TestHandler struct {
t *testing.T t *testing.T
c chan *SessionResult c chan *SessionResult
client *irmaclient.Client client *irmaclient.Client
expectedServerName irma.TranslatedString
} }
func (th TestHandler) KeyshareEnrollmentIncomplete(manager irma.SchemeManagerIdentifier) { func (th TestHandler) KeyshareEnrollmentIncomplete(manager irma.SchemeManagerIdentifier) {
...@@ -109,6 +111,9 @@ func (th TestHandler) RequestVerificationPermission(request irma.DisclosureReque ...@@ -109,6 +111,9 @@ func (th TestHandler) RequestVerificationPermission(request irma.DisclosureReque
} }
choice.Attributes = append(choice.Attributes, candidates[0]) choice.Attributes = append(choice.Attributes, candidates[0])
} }
if len(th.expectedServerName) != 0 {
require.Equal(th.t, th.expectedServerName, ServerName)
}
callback(true, choice) callback(true, choice)
} }
func (th TestHandler) RequestIssuancePermission(request irma.IssuanceRequest, ServerName irma.TranslatedString, callback irmaclient.PermissionHandler) { func (th TestHandler) RequestIssuancePermission(request irma.IssuanceRequest, ServerName irma.TranslatedString, callback irmaclient.PermissionHandler) {
......
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"testing" "testing"
"time" "time"
...@@ -90,12 +91,6 @@ func getIssuanceRequest(defaultValidity bool) *irma.IssuanceRequest { ...@@ -90,12 +91,6 @@ func getIssuanceRequest(defaultValidity bool) *irma.IssuanceRequest {
"studentID": "s1234567", "studentID": "s1234567",
"level": "42", "level": "42",
}, },
}, {
Validity: expiry,
CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.root"),
Attributes: map[string]string{
"BSN": "299792458",
},
}, },
}, },
} }
...@@ -136,6 +131,18 @@ func getCombinedIssuanceRequest(id irma.AttributeTypeIdentifier) *irma.IssuanceR ...@@ -136,6 +131,18 @@ func getCombinedIssuanceRequest(id irma.AttributeTypeIdentifier) *irma.IssuanceR
return request return request
} }
func getMultipleIssuanceRequest() *irma.IssuanceRequest {
request := getIssuanceRequest(false)
request.Credentials = append(request.Credentials, &irma.CredentialRequest{
Validity: request.Credentials[0].Validity,
CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.root"),
Attributes: map[string]string{
"BSN": "299792458",
},
})
return request
}
var TestType = "irmaserver-jwt" var TestType = "irmaserver-jwt"
func startSession(t *testing.T, request irma.SessionRequest, sessiontype string) *irma.Qr { func startSession(t *testing.T, request irma.SessionRequest, sessiontype string) *irma.Qr {
...@@ -229,7 +236,7 @@ func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string ...@@ -229,7 +236,7 @@ func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string
qr := startSession(t, request, sessiontype) qr := startSession(t, request, sessiontype)
c := make(chan *SessionResult) c := make(chan *SessionResult)
h := TestHandler{t, c, client} h := TestHandler{t, c, client, expectedServerName(t, request, client.Configuration)}
qrjson, err := json.Marshal(qr) qrjson, err := json.Marshal(qr)
require.NoError(t, err) require.NoError(t, err)
client.NewSession(string(qrjson), h) client.NewSession(string(qrjson), h)
...@@ -238,3 +245,30 @@ func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string ...@@ -238,3 +245,30 @@ func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string
require.NoError(t, result.Err) require.NoError(t, result.Err)
} }
} }
func expectedServerName(t *testing.T, request irma.SessionRequest, conf *irma.Configuration) irma.TranslatedString {
localhost := "localhost"
host := irma.NewTranslatedString(&localhost)
ir, ok := request.(*irma.IssuanceRequest)
if !ok {
return host
}
// In issuance sessions, the server name is expected to be:
// - the name of the issuer, if there is just one issuer
// - the hostname as usual otherwise
var name irma.TranslatedString
for _, credreq := range ir.Credentials {
n := conf.Issuers[credreq.CredentialTypeID.IssuerIdentifier()].Name
if !reflect.DeepEqual(name, n) {
if len(name) != 0 {
return host
}
name = n
}
}
return name
}
...@@ -117,7 +117,7 @@ func TestManualSessionMultiProof(t *testing.T) { ...@@ -117,7 +117,7 @@ func TestManualSessionMultiProof(t *testing.T) {
defer test.ClearTestStorage(t) defer test.ClearTestStorage(t)
// First, we need to issue an extra credential (BSN) // First, we need to issue an extra credential (BSN)
sessionHelper(t, getIssuanceRequest(true), "issue", client) sessionHelper(t, getMultipleIssuanceRequest(), "issue", client)
// Request to sign with both BSN and StudentID // Request to sign with both BSN and StudentID
request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]},{\"label\":\"BSN\",\"attributes\":[\"irma-demo.MijnOverheid.root.BSN\"]}]}" request := "{\"nonce\": 0, \"context\": 0, \"type\": \"signing\", \"message\":\"I owe you everything\",\"content\":[{\"label\":\"Student number (RU)\",\"attributes\":[\"irma-demo.RU.studentCard.studentID\"]},{\"label\":\"BSN\",\"attributes\":[\"irma-demo.MijnOverheid.root.BSN\"]}]}"
......
...@@ -25,7 +25,7 @@ func requestorSessionHelper(t *testing.T, request irma.SessionRequest) *server.S ...@@ -25,7 +25,7 @@ func requestorSessionHelper(t *testing.T, request irma.SessionRequest) *server.S
}) })
require.NoError(t, err) require.NoError(t, err)
h := TestHandler{t, clientChan, client} h := TestHandler{t, clientChan, client, nil}
j, err := json.Marshal(qr) j, err := json.Marshal(qr)
require.NoError(t, err) require.NoError(t, err)
client.NewSession(string(j), h) client.NewSession(string(j), h)
......
...@@ -34,6 +34,11 @@ func TestIssuanceSession(t *testing.T) { ...@@ -34,6 +34,11 @@ func TestIssuanceSession(t *testing.T) {
sessionHelper(t, request, "issue", nil) sessionHelper(t, request, "issue", nil)
} }
func TestMultipleIssuanceSession(t *testing.T) {
request := getMultipleIssuanceRequest()
sessionHelper(t, request, "issue", nil)
}
func TestDefaultCredentialValidity(t *testing.T) { func TestDefaultCredentialValidity(t *testing.T) {
client := parseStorage(t) client := parseStorage(t)
request := getIssuanceRequest(true) request := getIssuanceRequest(true)
...@@ -74,7 +79,7 @@ func TestIssuanceSingletonCredential(t *testing.T) { ...@@ -74,7 +79,7 @@ func TestIssuanceSingletonCredential(t *testing.T) {
client := parseStorage(t) client := parseStorage(t)
defer test.ClearTestStorage(t) defer test.ClearTestStorage(t)
request := getIssuanceRequest(true) request := getMultipleIssuanceRequest()
credid := irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.root") credid := irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.root")
require.Nil(t, client.Attributes(credid, 0)) require.Nil(t, client.Attributes(credid, 0))
...@@ -234,7 +239,7 @@ func TestDownloadSchemeManager(t *testing.T) { ...@@ -234,7 +239,7 @@ func TestDownloadSchemeManager(t *testing.T) {
URL: "http://localhost:48681/irma_configuration/irma-demo", URL: "http://localhost:48681/irma_configuration/irma-demo",
}) })
require.NoError(t, err) require.NoError(t, err)
client.NewSession(string(qr), TestHandler{t, c, client}) client.NewSession(string(qr), TestHandler{t, c, client, nil})
if result := <-c; result != nil { if result := <-c; result != nil {
require.NoError(t, result.Err) require.NoError(t, result.Err)
} }
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"reflect"
"strings" "strings"
"github.com/go-errors/errors" "github.com/go-errors/errors"
...@@ -53,7 +54,7 @@ type session struct { ...@@ -53,7 +54,7 @@ type session struct {
Action irma.Action Action irma.Action
Handler Handler Handler Handler
Version *irma.ProtocolVersion Version *irma.ProtocolVersion
ServerName string ServerName irma.TranslatedString
choice *irma.DisclosureChoice choice *irma.DisclosureChoice
attrIndices irma.DisclosedAttributeIndices attrIndices irma.DisclosedAttributeIndices
...@@ -66,6 +67,7 @@ type session struct { ...@@ -66,6 +67,7 @@ type session struct {
builders gabi.ProofBuilderList builders gabi.ProofBuilderList
// These are empty on manual sessions // These are empty on manual sessions
Hostname string
ServerURL string ServerURL string
transport *irma.HTTPTransport transport *irma.HTTPTransport
} }
...@@ -114,12 +116,11 @@ func (client *Client) NewSession(sessionrequest string, handler Handler) Session ...@@ -114,12 +116,11 @@ func (client *Client) NewSession(sessionrequest string, handler Handler) Session
// newManualSession starts a manual session, given a signature request in JSON and a handler to pass messages to // newManualSession starts a manual session, given a signature request in JSON and a handler to pass messages to
func (client *Client) newManualSession(request irma.SessionRequest, handler Handler, action irma.Action) SessionDismisser { func (client *Client) newManualSession(request irma.SessionRequest, handler Handler, action irma.Action) SessionDismisser {
session := &session{ session := &session{
Action: action, Action: action,
Handler: handler, Handler: handler,
client: client, client: client,
Version: minVersion, Version: minVersion,
ServerName: "", request: request,
request: request,
} }
session.Handler.StatusUpdate(session.Action, irma.StatusManualStarted) session.Handler.StatusUpdate(session.Action, irma.StatusManualStarted)
...@@ -145,12 +146,12 @@ func (client *Client) newSchemeSession(qr *irma.SchemeManagerRequest, handler Ha ...@@ -145,12 +146,12 @@ func (client *Client) newSchemeSession(qr *irma.SchemeManagerRequest, handler Ha
func (client *Client) newQrSession(qr *irma.Qr, handler Handler) SessionDismisser { func (client *Client) newQrSession(qr *irma.Qr, handler Handler) SessionDismisser {
u, _ := url.ParseRequestURI(qr.URL) // Qr validator already checked this for errors u, _ := url.ParseRequestURI(qr.URL) // Qr validator already checked this for errors
session := &session{ session := &session{
ServerURL: qr.URL, ServerURL: qr.URL,
ServerName: u.Hostname(), Hostname: u.Hostname(),
transport: irma.NewHTTPTransport(qr.URL), transport: irma.NewHTTPTransport(qr.URL),
Action: irma.Action(qr.Type), Action: irma.Action(qr.Type),
Handler: handler, Handler: handler,
client: client, client: client,
} }
session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating) session.Handler.StatusUpdate(session.Action, irma.StatusCommunicating)
...@@ -197,6 +198,29 @@ func (session *session) getSessionInfo() { ...@@ -197,6 +198,29 @@ func (session *session) getSessionInfo() {
session.processSessionInfo() session.processSessionInfo()
} }
func serverName(hostname string, request irma.SessionRequest, conf *irma.Configuration) irma.TranslatedString {
sn := irma.NewTranslatedString(&hostname)
if ir, ok := request.(*irma.IssuanceRequest); ok {
// If there is only one issuer in the current request, use its name as ServerName
var iss irma.TranslatedString
for _, credreq := range ir.Credentials {
credIssuer := conf.Issuers[credreq.CredentialTypeID.IssuerIdentifier()].Name
if !reflect.DeepEqual(credIssuer, iss) { // Can't just test pointer equality: credIssuer != iss
if len(iss) != 0 {
return sn
}
iss = credIssuer
}
}
if len(iss) != 0 {
return iss
}
}
return sn
}
// processSessionInfo continues the session after all session state has been received: // processSessionInfo continues the session after all session state has been received:
// it checks if the session can be performed and asks the user for consent. // it checks if the session can be performed and asks the user for consent.
func (session *session) processSessionInfo() { func (session *session) processSessionInfo() {
...@@ -214,6 +238,8 @@ func (session *session) processSessionInfo() { ...@@ -214,6 +238,8 @@ func (session *session) processSessionInfo() {
session.request.SetVersion(session.Version) session.request.SetVersion(session.Version)
} }
session.ServerName = serverName(session.Hostname, session.request, session.client.Configuration)
if session.Action == irma.ActionIssuing { if session.Action == irma.ActionIssuing {
ir := session.request.(*irma.IssuanceRequest) ir := session.request.(*irma.IssuanceRequest)
_, err := ir.GetCredentialInfoList(session.client.Configuration, session.Version) _, err := ir.GetCredentialInfoList(session.client.Configuration, session.Version)
...@@ -232,10 +258,9 @@ func (session *session) processSessionInfo() { ...@@ -232,10 +258,9 @@ func (session *session) processSessionInfo() {
} }
} }
serverName := irma.NewTranslatedString(&session.ServerName)
candidates, missing := session.client.CheckSatisfiability(session.request.ToDisclose()) candidates, missing := session.client.CheckSatisfiability(session.request.ToDisclose())
if len(missing) > 0 { if len(missing) > 0 {
session.Handler.UnsatisfiableRequest(serverName, missing) session.Handler.UnsatisfiableRequest(session.ServerName, missing)
return return
} }
session.request.SetCandidates(candidates) session.request.SetCandidates(candidates)
...@@ -250,13 +275,13 @@ func (session *session) processSessionInfo() { ...@@ -250,13 +275,13 @@ func (session *session) processSessionInfo() {
switch session.Action { switch session.Action {
case irma.ActionDisclosing: case irma.ActionDisclosing:
session.Handler.RequestVerificationPermission( session.Handler.RequestVerificationPermission(
*session.request.(*irma.DisclosureRequest), serverName, callback) *session.request.(*irma.DisclosureRequest), session.ServerName, callback)
case irma.ActionSigning: case irma.ActionSigning:
session.Handler.RequestSignaturePermission( session.Handler.RequestSignaturePermission(
*session.request.(*irma.SignatureRequest), serverName, callback) *session.request.(*irma.SignatureRequest), session.ServerName, callback)
case irma.ActionIssuing: case irma.ActionIssuing:
session.Handler.RequestIssuancePermission( session.Handler.RequestIssuancePermission(
*session.request.(*irma.IssuanceRequest), serverName, callback) *session.request.(*irma.IssuanceRequest), session.ServerName, callback)
default: default:
panic("Invalid session type") // does not happen, session.Action has been checked earlier panic("Invalid session type") // does not happen, session.Action has been checked earlier
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment