Skip to content

Commit

Permalink
Merge branch 'master' into db-errors
Browse files Browse the repository at this point in the history
  • Loading branch information
ivard authored Sep 27, 2023
2 parents 9f050a1 + b12ef55 commit 063e77e
Show file tree
Hide file tree
Showing 21 changed files with 498 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ runs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ^1.18
go-version: ^1.21

- name: Determine artifact output filename
id: artifact-name-generator
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/status-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ^1.18
go-version-file: go.mod

- name: Run gofmt
# gofmt does not return non-zero exit codes on failure, so we have to check that there are no issues using grep.
Expand Down Expand Up @@ -145,6 +145,11 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: go.mod

- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
Expand Down
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,47 @@ 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).

## Unreleased
### Added
- Option `skipExpiryCheck` in disclosure requests to allow disclosure of expired credentials (e.g. `"skipExpiryCheck": ["irma-demo.sidn-pbdf.email"]`)
- Option `host` in session request to overrule host name in IRMA QR if permission has been granted (see below)
```
{
"@context": "https://irma.app/ld/request/disclosure/v2",
"host": "irma.example.com",
"disclose": ...
}
```
This leads to the following session package:
```
{
"token":"KzxuWKwL5KGLKr4uerws",
"sessionPtr": {"u":"https://irma.example.com/irma/session/ysDohpoySavbHAUDjmpz","irmaqr":"disclosing"},
"frontendRequest": {
"authorization":"qGrMmL8UZwZ88Sq8gobV",
"minProtocolVersion": "1.0",
"maxProtocolVersion": "1.1"
}
}
```
- Permission option `host_perms` in the requestor configuration to specify which values a requestor may use for the `host` option in session requests
```
{
"requestors": {
"myapp": {
"disclose_perms": [ "irma-demo.MijnOverheid.ageLower.over18" ],
"sign_perms": [ "irma-demo.MijnOverheid.ageLower.*" ],
"issue_perms": [ "irma-demo.MijnOverheid.ageLower" ],
"host_perms": ["*.example.com"]
"auth_method": "token",
"key": "eGE2PSomOT84amVVdTU"
}
}
}
```
- Renewal endpoint for keyshare attribute in the keyshare server (`/users/renewKeyshareAttribute`)

### Changed
- `KeyshareVerifyPin` function in irmaclient ensures the keyshare attribute is valid

### Changed
- Sending the account expiry email is done when user has only valid e-mail addresses
Expand Down
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/privacybydesign/irmago

go 1.18
go 1.21

toolchain go1.21.1

require (
github.com/alexandrevicenzi/go-sse v1.6.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
Expand Down Expand Up @@ -172,6 +173,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
Expand Down Expand Up @@ -283,10 +285,12 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
Expand Down
9 changes: 9 additions & 0 deletions internal/sessiontest/helper_servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,23 @@ func RequestorServerAuthConfiguration() *requestorserver.Configuration {
"requestor1": {
AuthenticationMethod: requestorserver.AuthenticationMethodPublicKey,
AuthenticationKeyFile: filepath.Join(testdata, "jwtkeys", "requestor1.pem"),
Permissions: requestorserver.Permissions{
Hosts: []string{"localhost:48682"},
},
},
"requestor2": {
AuthenticationMethod: requestorserver.AuthenticationMethodToken,
AuthenticationKey: TokenAuthenticationKey,
Permissions: requestorserver.Permissions{
Hosts: []string{"localhost:48682"},
},
},
"requestor3": {
AuthenticationMethod: requestorserver.AuthenticationMethodHmac,
AuthenticationKey: HmacAuthenticationKey,
Permissions: requestorserver.Permissions{
Hosts: []string{"localhost:48682"},
},
},
}
return conf
Expand Down
41 changes: 41 additions & 0 deletions internal/sessiontest/keyshare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package sessiontest

import (
"testing"
"time"

irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/test"
"github.com/privacybydesign/irmago/internal/testkeyshare"
"github.com/privacybydesign/irmago/irmaclient"
"github.com/privacybydesign/irmago/server/irmaserver"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -50,6 +52,45 @@ func TestKeyshareRegister(t *testing.T) {
keyshareSessions(t, client, irmaServer)
}

func TestKeyshareAttributeRenewal(t *testing.T) {
keyshareServer := testkeyshare.StartKeyshareServer(t, logger, irma.NewSchemeManagerIdentifier("test"))
defer keyshareServer.Stop()

client, handler := parseStorage(t)
defer test.ClearTestStorage(t, client, handler.storage)

irmaServer := StartIrmaServer(t, nil)
defer irmaServer.Stop()

irmaserver.AllowIssuingExpiredCredentials = true
defer func() {
irmaserver.AllowIssuingExpiredCredentials = false
}()

// Make keyshare attribute invalid.
invalidValidity := irma.Timestamp(time.Now())
issuanceRequest := irma.NewIssuanceRequest([]*irma.CredentialRequest{
{
Validity: &invalidValidity,
CredentialTypeID: irma.NewCredentialTypeIdentifier("test.test.mijnirma"),
Attributes: map[string]string{"email": "testusername"},
},
})
doSession(t, issuanceRequest, client, irmaServer, nil, nil, nil)

// Validate that keyshare attribute is invalid.
disclosureRequest := getDisclosureRequest(irma.NewAttributeTypeIdentifier("test.test.mijnirma.email"))
doSession(t, disclosureRequest, client, irmaServer, nil, nil, nil, optionUnsatisfiableRequest)

// Do a PIN verification. This should detect the invalid keyshare attribute and renew it.
valid, _, _, err := client.KeyshareVerifyPin("12345", irma.NewSchemeManagerIdentifier("test"))
require.NoError(t, err)
require.True(t, valid)

// Keyshare attribute should be valid again.
doSession(t, disclosureRequest, client, irmaServer, nil, nil, nil)
}

// Use the existing keyshare enrollment and credentials
// in a keyshare session of each session type.
func TestKeyshareSessions(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion internal/sessiontest/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func TestRedisRedundancy(t *testing.T) {

for i, port := range ports {
c := redisRequestorConfigDecorator(mr, cert, "", RequestorServerAuthConfiguration)()
c.Configuration.URL = fmt.Sprintf("http://localhost:%d/irma", port)
c.Configuration.URL = fmt.Sprintf("http://localhost:%d/irma", requestorServerPort)
c.Port = port
rs := StartRequestorServer(t, c)
servers[i] = rs
Expand Down
90 changes: 90 additions & 0 deletions internal/sessiontest/session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import (
"testing"
"time"

"github.com/golang-jwt/jwt/v4"
"github.com/privacybydesign/gabi/big"
irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/internal/common"
"github.com/privacybydesign/irmago/internal/test"
"github.com/privacybydesign/irmago/irmaclient"
"github.com/privacybydesign/irmago/server"
"github.com/privacybydesign/irmago/server/irmaserver"
sseclient "github.com/sietseringers/go-sse"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -1263,3 +1265,91 @@ func TestIssueExpiredKey(t *testing.T) {
_, _, _, err := irmaServer.irma.StartSession(getIssuanceRequest(true), nil)
require.Error(t, err)
}

func TestExpiredCredential(t *testing.T) {
irmaserver.AllowIssuingExpiredCredentials = true
defer func() {
irmaserver.AllowIssuingExpiredCredentials = false
}()

client, handler := parseStorage(t)
defer test.ClearTestStorage(t, client, handler.storage)

irmaServer := StartIrmaServer(t, nil)
defer irmaServer.Stop()

// Issue an expired credential
invalidValidity := irma.Timestamp(time.Now())
value := "13371337"
issuanceRequest := irma.NewIssuanceRequest([]*irma.CredentialRequest{
{
Validity: &invalidValidity,
CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.RU.studentCard"),
Attributes: map[string]string{
"university": "Radboud",
"studentCardNumber": value,
"studentID": "s1234567",
"level": "42",
},
},
})
doSession(t, issuanceRequest, client, irmaServer, nil, nil, nil)

// Try to disclose it and check that it fails.
disclosureRequest := irma.NewDisclosureRequest()
disclosureRequest.AddSingle(irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentCardNumber"), &value, nil)
doSession(t, disclosureRequest, client, irmaServer, nil, nil, nil, optionUnsatisfiableRequest)

// Try to disclose it when allowing expired credentials and check that it succeeds.
disclosureRequest.SkipExpiryCheck = []irma.CredentialTypeIdentifier{issuanceRequest.Credentials[0].CredentialTypeID}
doSession(t, disclosureRequest, client, irmaServer, nil, nil, nil)
}

func TestRequestorHostPermissions(t *testing.T) {
client, handler := parseStorage(t)
defer test.ClearTestStorage(t, client, handler.storage)
rs := StartRequestorServer(t, RequestorServerAuthConfiguration())
defer rs.Stop()

// Check that a requestor can use a host that is allowed.
id := irma.NewAttributeTypeIdentifier("irma-demo.RU.studentCard.studentID")
request := getDisclosureRequest(id)
sesPkg := &server.SessionPackage{}

// Check that a requestor can't use a host that is not allowed.
request.Base().Host = "127.0.0.1:48682"
err := irma.NewHTTPTransport(requestorServerURL, false).Post("session", &server.SessionPackage{}, signSessionRequest(t, request))
require.Error(t, err)
require.Contains(t, err.Error(), "requestor not allowed to use the requested host")

// Start a new session using the allowed host.
request.Base().Host = "localhost:48682"
err = irma.NewHTTPTransport(requestorServerURL, false).Post("session", sesPkg, signSessionRequest(t, request))
require.NoError(t, err)
realURL := sesPkg.SessionPtr.URL

// Check that a client can't use another host than the requestor wanted.
sesPkg.SessionPtr.URL = strings.Replace(sesPkg.SessionPtr.URL, "localhost", "127.0.0.1", 1)
sessionHandler, resultChan := createSessionHandler(t, optionIgnoreError, client, sesPkg, nil, nil)
startSessionAtClient(t, sesPkg, client, sessionHandler)
result := <-resultChan
require.Error(t, result.Err)
require.Contains(t, result.Err.Error(), "Host mismatch")

// Check that a client can use the host the requestor wanted.
sesPkg.SessionPtr.URL = realURL
sessionHandler, resultChan = createSessionHandler(t, 0, client, sesPkg, nil, nil)
startSessionAtClient(t, sesPkg, client, sessionHandler)
result = <-resultChan
require.Nil(t, result)
}

func signSessionRequest(t *testing.T, req irma.SessionRequest) string {
skbts, err := os.ReadFile(filepath.Join(testdata, "jwtkeys", "requestor1-sk.pem"))
require.NoError(t, err)
sk, err := jwt.ParseRSAPrivateKeyFromPEM(skbts)
require.NoError(t, err)
j, err := irma.SignSessionRequest(req, jwt.SigningMethodRS256, sk, "requestor1")
require.NoError(t, err)
return j
}
Loading

0 comments on commit 063e77e

Please sign in to comment.