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

Disclosing, test api client, session test

parent 75c9bfb3
......@@ -248,7 +248,7 @@ func (cm *CredentialManager) CheckSatisfiability(disjunctions DisjunctionListCon
return missing
}
func (cm *CredentialManager) groupCredentials(choice DisclosureChoice) (map[CredentialIdentifier][]int, error) {
func (cm *CredentialManager) groupCredentials(choice *DisclosureChoice) (map[CredentialIdentifier][]int, error) {
grouped := make(map[CredentialIdentifier][]int)
for _, attribute := range choice.Attributes {
......@@ -285,7 +285,7 @@ type SessionRequest interface {
GetContext() *big.Int
}
func (cm *CredentialManager) Proofs(choice DisclosureChoice, message *string) (gabi.ProofList, error) {
func (cm *CredentialManager) Proofs(choice *DisclosureChoice, message *string) (gabi.ProofList, error) {
todisclose, err := cm.groupCredentials(choice)
if err != nil {
return nil, err
......
......@@ -42,11 +42,20 @@ const (
// Protocol errors
const (
// Protocol version not supported
ErrorProtocolVersionNotSupported = SessionError("versionNotSupported")
ErrorInvalidURL = SessionError("invalidUrl")
ErrorTransport = SessionError("httpError")
ErrorInvalidJWT = SessionError("invalidJwt")
ErrorUnknownAction = SessionError("unknownAction")
// Server URL invalid
ErrorInvalidURL = SessionError("invalidUrl")
// Error in HTTP communication
ErrorTransport = SessionError("httpError")
// Invalid client JWT in first IRMA message
ErrorInvalidJWT = SessionError("invalidJwt")
// Unkown session type (not disclosing, signing, or issuing)
ErrorUnknownAction = SessionError("unknownAction")
// Crypto error during calculation of our response (second IRMA message)
ErrorCrypto = SessionError("cryptoResponseError")
// Server rejected our response (second IRMA message)
ErrorRejected = SessionError("rejectedByServer")
)
// Qr contains the data of an IRMA session QR.
......
......@@ -3,6 +3,7 @@ package protocol
import (
"encoding/asn1"
"math/big"
"time"
"crypto/sha256"
......@@ -37,7 +38,7 @@ type CredentialRequest struct {
type ServerRequest struct {
ServerName string `json:"iss"`
IssuedAt *Timestamp `json:"iat"`
Type string `json:"subject"`
Type string `json:"sub"`
}
type IssuanceRequest struct {
......@@ -46,11 +47,27 @@ type IssuanceRequest struct {
Disclose irmago.AttributeDisjunctionList `json:"disclose"`
}
type DisclosureRequestContainer struct {
Request DisclosureRequest `json:"request"`
}
type ServiceProviderRequest struct {
ServerRequest
Request struct {
Request DisclosureRequest `json:"request"`
} `json:"sprequest"`
Request DisclosureRequestContainer `json:"sprequest"`
}
func NewServiceProviderRequest(servername string, dr DisclosureRequest) *ServiceProviderRequest {
now := Timestamp(time.Now())
return &ServiceProviderRequest{
ServerRequest: ServerRequest{
ServerName: servername,
IssuedAt: &now,
Type: "verification_request",
},
Request: DisclosureRequestContainer{
Request: dr,
},
}
}
type SignatureServerRequest struct {
......
package protocol
func StartSession(request interface{}, url string) (*Qr, error) {
server := NewHTTPTransport(url)
var response Qr
err := server.Post("", &response, request)
if err != nil {
return nil, err
}
return &response, nil
}
......@@ -2,10 +2,12 @@ package protocol
import (
"encoding/json"
"errors"
"math/big"
"strings"
"github.com/credentials/irmago"
"github.com/mhe/gabi"
)
type PermissionHandler func(proceed bool, choice *irmago.DisclosureChoice)
......@@ -31,13 +33,17 @@ type Session struct {
Handler Handler
request irmago.DisjunctionListContainer
spRequest *ServiceProviderRequest
ipRequest *IdentityProviderRequest
ssRequest *SignatureServerRequest
transport *HTTPTransport
nonce *big.Int
context *big.Int
}
// NewSession creates and starts a new IRMA session.
func NewSession(qr Qr, handler Handler) *Session {
func NewSession(qr *Qr, handler Handler) *Session {
if qr.ProtocolVersion != "2.1" && qr.ProtocolVersion != "2.2" { // TODO version negotiation
handler.Failure(ActionUnknown, ErrorProtocolVersionNotSupported, qr.ProtocolVersion)
return nil
......@@ -100,11 +106,14 @@ func (session *Session) start() {
switch session.Action {
case ActionDisclosing:
session.request = &ServiceProviderRequest{}
session.spRequest = &ServiceProviderRequest{}
session.request = session.spRequest
case ActionSigning:
session.request = &SignatureServerRequest{}
session.ssRequest = &SignatureServerRequest{}
session.request = session.ssRequest
case ActionIssuing:
session.request = &IdentityProviderRequest{}
session.ipRequest = &IdentityProviderRequest{}
session.request = session.ipRequest
default:
panic("Invalid session type") // does not happen, session.Action has been checked earlier
}
......@@ -129,11 +138,11 @@ func (session *Session) start() {
session.Handler.StatusUpdate(session.Action, StatusConnected)
switch session.Action {
case ActionDisclosing:
session.Handler.AskVerificationPermission(session.request.(*ServiceProviderRequest).Request.Request, header.Server, callback)
session.Handler.AskVerificationPermission(session.spRequest.Request.Request, header.Server, callback)
case ActionSigning:
session.Handler.AskSignaturePermission(session.request.(*SignatureServerRequest).Request.Request, header.Server, callback)
session.Handler.AskSignaturePermission(session.ssRequest.Request.Request, header.Server, callback)
case ActionIssuing:
session.Handler.AskIssuancePermission(session.request.(*IdentityProviderRequest).Request.Request, header.Server, callback)
session.Handler.AskIssuancePermission(session.ipRequest.Request.Request, header.Server, callback)
default:
panic("Invalid session type") // does not happen, session.Action has been checked earlier
}
......@@ -144,6 +153,29 @@ func (session *Session) do(proceed bool, choice *irmago.DisclosureChoice) {
session.Handler.Cancelled(session.Action)
return
}
session.Handler.StatusUpdate(session.Action, StatusCommunicating)
var proofs gabi.ProofList
var err error
switch session.Action {
case ActionSigning:
proofs, err = irmago.Manager.Proofs(choice, &session.ssRequest.Request.Request.Message)
case ActionDisclosing:
proofs, err = irmago.Manager.Proofs(choice, nil)
case ActionIssuing:
err = errors.New("Issuing not yet implemented")
}
if err != nil {
session.Handler.Failure(session.Action, ErrorCrypto, err.Error())
return
}
var response string
session.transport.Post("proofs", &response, proofs)
if response != "VALID" {
session.Handler.Failure(session.Action, ErrorRejected, response)
return
}
session.Handler.Success(session.Action)
}
package protocol
import (
"encoding/json"
"testing"
"encoding/base64"
"github.com/credentials/irmago"
"github.com/stretchr/testify/require"
)
type TestHandler struct {
t *testing.T
}
func (th TestHandler) StatusUpdate(action Action, status Status) {}
func (th TestHandler) Success(action Action) {}
func (th TestHandler) Cancelled(action Action) {
th.t.FailNow()
}
func (th TestHandler) Failure(action Action, err SessionError, info string) {
th.t.Fatal(string(err), info)
}
func (th TestHandler) UnsatisfiableRequest(action Action, missing irmago.AttributeDisjunctionList) {
th.t.FailNow()
}
func (th TestHandler) AskIssuancePermission(request IssuanceRequest, ServerName string, choice PermissionHandler) {
}
func (th TestHandler) AskVerificationPermission(request DisclosureRequest, ServerName string, callback PermissionHandler) {
choice := &irmago.DisclosureChoice{
Attributes: []*irmago.AttributeIdentifier{},
}
var candidates []*irmago.AttributeIdentifier
for _, disjunction := range request.Content {
candidates = irmago.Manager.Candidates(disjunction)
require.NotNil(th.t, candidates)
require.NotEmpty(th.t, candidates, 1)
choice.Attributes = append(choice.Attributes, candidates[0])
}
callback(true, choice)
}
func (th TestHandler) AskSignaturePermission(request SignatureRequest, ServerName string, choice PermissionHandler) {
}
func TestSession(t *testing.T) {
id := irmago.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentNumber")
url := "https://demo.irmacard.org/tomcat/irma_api_server/api/v2"
name := "testsp"
spRequest := NewServiceProviderRequest(name, DisclosureRequest{
Content: irmago.AttributeDisjunctionList([]*irmago.AttributeDisjunction{
&irmago.AttributeDisjunction{
Label: "foo",
Attributes: []irmago.AttributeTypeIdentifier{id},
},
}),
})
headerbytes, err := json.Marshal(&map[string]string{"alg": "none", "typ": "JWT"})
require.NoError(t, err)
bodybytes, err := json.Marshal(spRequest)
require.NoError(t, err)
jwt := base64.StdEncoding.EncodeToString(headerbytes) + "." + base64.StdEncoding.EncodeToString(bodybytes) + "."
qr, err := StartSession(jwt, url)
require.NoError(t, err)
NewSession(qr, TestHandler{t})
}
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