Skip to content

Commit a952330

Browse files
authored
Merge pull request #78 from FIWARE/feat/update-qr-ui
Update QR v2 interface
2 parents c83db0f + 17a1c47 commit a952330

File tree

16 files changed

+363
-287
lines changed

16 files changed

+363
-287
lines changed

common/cache.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Cache interface {
1212
Add(k string, x interface{}, d time.Duration) error
1313
Get(k string) (interface{}, bool)
1414
Set(k string, x interface{}, d time.Duration)
15+
GetWithExpiration(k string) (interface{}, time.Time, bool)
1516
Delete(k string)
1617
}
1718

openapi/api_api_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ type mockVerifier struct {
4646
func (mV *mockVerifier) ReturnLoginQR(host string, protocol string, callback string, sessionId string, clientId string, nonce string, requestType string) (qr string, err error) {
4747
return mV.mockQR, mV.mockError
4848
}
49-
func (mV *mockVerifier) ReturnLoginQRV2(host string, protocol string, callback string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qr string, err error) {
50-
return mV.mockQR, mV.mockError
49+
func (mV *mockVerifier) ReturnLoginQRV2(host string, protocol string, callback string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qrInfo verifier.QRLoginInfo, err error) {
50+
return verifier.QRLoginInfo{QR: mV.mockQR}, mV.mockError
5151
}
5252
func (mV *mockVerifier) StartSiopFlow(host string, protocol string, callback string, sessionId string, clientId string, nonce string, requestType string) (connectionString string, err error) {
5353
return mV.mockConnectionString, mV.mockError

openapi/api_frontend.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package openapi
1111

1212
import (
13+
"html/template"
1314
"net/http"
1415
"slices"
1516

@@ -141,13 +142,19 @@ func VerifierLoginQr(c *gin.Context) {
141142
requestMode = DEFAULT_REQUEST_MODE
142143
}
143144

144-
qr, err := getFrontendVerifier().ReturnLoginQRV2(c.Request.Host, "https", redirectUri, state, clientId, scope, nonce, requestMode)
145+
qrInfo, err := getFrontendVerifier().ReturnLoginQRV2(c.Request.Host, "https", redirectUri, state, clientId, scope, nonce, requestMode)
145146
if err != nil {
146147
c.AbortWithStatusJSON(500, ErrorMessage{"qr_generation_error", err.Error()})
147148
return
148149
}
149150

150-
c.HTML(http.StatusOK, "verifier_present_qr_v2", gin.H{"qrcode": qr, "wsUrl": getFrontendVerifier().GetHost() + "/ws?state=" + state})
151+
c.HTML(http.StatusOK, "verifier_present_qr_v2", gin.H{
152+
"qrcode": template.URL(qrInfo.QR),
153+
"wsUrl": getFrontendVerifier().GetHost() + "/ws?state=" + state,
154+
"qrExpireAt": qrInfo.ExpireAt.UnixMilli(),
155+
"qrDuration": qrInfo.TotalDuration,
156+
"authRequest": template.URL(qrInfo.AuthenticationRequest),
157+
})
151158
}
152159

153160
// VerifierPageLoginExpired - Presents a page when the login session is expired

tir/tirClient_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ func (mc mockCache) Add(k string, x interface{}, d time.Duration) error { return
4040
func (mc mockCache) Set(k string, x interface{}, d time.Duration) {}
4141
func (mc mockCache) Get(k string) (interface{}, bool) { return nil, false }
4242
func (mc mockCache) Delete(k string) {}
43+
func (mc mockCache) GetWithExpiration(k string) (interface{}, time.Time, bool) {
44+
return nil, time.Now(), false
45+
}
4346

4447
func TestIsTrustedParticipant(t *testing.T) {
4548
type test struct {
@@ -126,7 +129,7 @@ func getNotFoundResponse() *http.Response {
126129
return &http.Response{StatusCode: 404}
127130
}
128131
func getUnparsableResponse() *http.Response {
129-
issuer := io.NopCloser(strings.NewReader(fmt.Sprintf("did-i-dachs")))
132+
issuer := io.NopCloser(strings.NewReader("did-i-dachs"))
130133
response := http.Response{
131134
StatusCode: 200,
132135
Body: issuer,

verifier/verifier.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,18 @@ var ErrorInvalidNonce = errors.New("invalid_nonce")
7878

7979
// Actual implementation of the verfifier functionality
8080

81+
// Verifier QR Information
82+
type QRLoginInfo struct {
83+
QR string
84+
ExpireAt time.Time
85+
TotalDuration int
86+
AuthenticationRequest string
87+
}
88+
8189
// verifier interface
8290
type Verifier interface {
8391
ReturnLoginQR(host string, protocol string, callback string, sessionId string, clientId string, nonce string, requestMode string) (qr string, err error)
84-
ReturnLoginQRV2(host string, protocol string, callback string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qr string, err error)
92+
ReturnLoginQRV2(host string, protocol string, callback string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qrLoginInfo QRLoginInfo, err error)
8593
StartSiopFlow(host string, protocol string, callback string, state string, clientId string, nonce string, requestMode string) (connectionString string, err error)
8694
StartSameDeviceFlow(host string, protocol string, sessionId string, redirectPath string, clientId string, nonce string, requestMode string, scope string, requestProtocol string) (authenticationRequest string, err error)
8795
GetToken(authorizationCode string, redirectUri string, validated bool) (jwtString string, expiration int64, err error)
@@ -136,6 +144,8 @@ type CredentialVerifier struct {
136144
verifierConfig configModel.Verifier
137145
// JWT token expiration time in minutes
138146
jwtExpiration time.Duration
147+
// Session duration in seconds
148+
sessionDuration time.Duration
139149
}
140150

141151
// allow singleton access to the verifier
@@ -358,6 +368,7 @@ func InitVerifier(config *configModel.Configuration) (err error) {
358368
verifierConfig.ClientIdentification,
359369
*verifierConfig,
360370
time.Duration(verifierConfig.JwtExpiration) * time.Minute,
371+
time.Duration(verifierConfig.SessionExpiry),
361372
}
362373

363374
logging.Log().Debug("Successfully initalized the verifier")
@@ -395,29 +406,36 @@ func (v *CredentialVerifier) ReturnLoginQR(host string, protocol string, callbac
395406
/**
396407
* Initializes the cross-device login flow and returns all neccessary information as a qr-code
397408
**/
398-
func (v *CredentialVerifier) ReturnLoginQRV2(host string, protocol string, redircetUri string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qr string, err error) {
409+
func (v *CredentialVerifier) ReturnLoginQRV2(host string, protocol string, redircetUri string, sessionId string, clientId string, scope string, nonce string, requestMode string) (qrInfo QRLoginInfo, err error) {
399410

400411
for _, v := range v.supportedRequestModes {
401412
logging.Log().Warnf("Supported: %s", v)
402413
}
403414

404415
if !slices.Contains(v.supportedRequestModes, requestMode) {
405416
logging.Log().Infof("QR with mode %s was requested, but only %v is supported.", requestMode, v.supportedRequestModes)
406-
return qr, ErrorUnsupportedRequestMode
417+
return qrInfo, ErrorUnsupportedRequestMode
407418
}
408419

409420
logging.Log().Debugf("Generate a login qr for %s.", redircetUri)
410421
authenticationRequest, err := v.initOid4VPCrossDevice(host, protocol, redircetUri, sessionId, clientId, scope, nonce, requestMode)
411422

412423
if err != nil {
413-
return qr, err
424+
return qrInfo, err
414425
}
415426

416427
png, err := qrcode.Encode(authenticationRequest, qrcode.Medium, 256)
417428
base64Img := base64.StdEncoding.EncodeToString(png)
418429
base64Img = "data:image/png;base64," + base64Img
419430

420-
return base64Img, err
431+
_, expireAt, _ := v.sessionCache.GetWithExpiration(sessionId)
432+
qrInfo = QRLoginInfo{
433+
QR: base64Img,
434+
ExpireAt: expireAt,
435+
TotalDuration: int(v.sessionDuration),
436+
AuthenticationRequest: authenticationRequest,
437+
}
438+
return qrInfo, err
421439
}
422440

423441
/**

verifier/verifier_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@ func (msc *mockSessionCache) Delete(k string) {
249249
delete(msc.sessions, k)
250250
}
251251

252+
func (msc *mockSessionCache) GetWithExpiration(k string) (interface{}, time.Time, bool) {
253+
v, found := msc.sessions[k]
254+
return v, <-time.After(5 * time.Second), found
255+
}
256+
252257
func (mtc *mockTokenCache) Add(k string, x interface{}, d time.Duration) error {
253258
if mtc.errorToThrow != nil {
254259
return mtc.errorToThrow
@@ -270,6 +275,11 @@ func (mtc *mockTokenCache) Delete(k string) {
270275
delete(mtc.tokens, k)
271276
}
272277

278+
func (mtc *mockTokenCache) GetWithExpiration(k string) (interface{}, time.Time, bool) {
279+
v, found := mtc.tokens[k]
280+
return v, <-time.After(5 * time.Second), found
281+
}
282+
273283
type siopInitTest struct {
274284
testName string
275285
testHost string

views/static/css/main.min.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

views/static/img/evidencesmall.png

-2.38 KB
Binary file not shown.

views/static/img/favicon.ico

15 KB
Binary file not shown.

0 commit comments

Comments
 (0)