-
Notifications
You must be signed in to change notification settings - Fork 2
/
ResponseDispatcher.kt
172 lines (158 loc) · 7.2 KB
/
ResponseDispatcher.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
* Copyright (c) 2023 European Commission
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package eu.europa.ec.eudi.openid4vp
import eu.europa.ec.eudi.openid4vp.ResolvedRequestObject.*
import eu.europa.ec.eudi.prex.PresentationSubmission
import java.io.Serializable
import java.net.URI
/**
* Representation of holder's consensus to
* a [ResolvedRequestObject]
*/
sealed interface Consensus : Serializable {
/**
* No consensus. Holder decided to reject
* the request
*/
data object NegativeConsensus : Consensus {
private fun readResolve(): Any = NegativeConsensus
}
/**
* Positive consensus. Holder decided to
* respond to the request
*/
sealed interface PositiveConsensus : Consensus {
/**
* In response to a [SiopAuthentication]
* Holder/Wallet provides a [idToken] JWT
*
* @param idToken The id_token produced by the wallet
*/
data class IdTokenConsensus(
val idToken: Jwt,
) : PositiveConsensus
/**
* In response to a [OpenId4VPAuthorization] where the
* wallet has claims that fulfill Verifier's presentation definition
* and holder has chosen the claims to include
* @param vpToken the vp_token to be included in the authorization response
* @param presentationSubmission the presentation submission to be included in the authorization response
*/
data class VPTokenConsensus(
val vpToken: VpToken,
val presentationSubmission: PresentationSubmission,
) : PositiveConsensus
/**
* In response to a [SiopOpenId4VPAuthentication]
*
* @param idToken The id_token produced by the wallet
* @param vpToken the vp_token to be included in the authorization response
* @param presentationSubmission the presentation submission to be included in the authorization response
*/
data class IdAndVPTokenConsensus(
val idToken: Jwt,
val vpToken: VpToken,
val presentationSubmission: PresentationSubmission,
) : PositiveConsensus
}
}
/**
* The outcome of dispatching an [Consensus] to
* verifier/RP.
*/
sealed interface DispatchOutcome : Serializable {
/**
* In case verifier requested response to be redirected to a URI,
* this class contains this URI with the response encoded to it
*/
data class RedirectURI(val value: URI) : DispatchOutcome
/**
* In case verifier requested that response should be posted (direct post or direct post jwt)
* this class contains the response of the verifier after receiving the authorization response
*/
sealed interface VerifierResponse : DispatchOutcome {
/**
* When verifier/RP acknowledged the direct post
*/
data class Accepted(val redirectURI: URI?) : VerifierResponse
/**
* When verifier/RP reject the direct post
*/
data object Rejected : VerifierResponse {
private fun readResolve(): Any = Rejected
}
}
}
/**
* This interface assembles an appropriate authorization response given a [request][ResolvedRequestObject]
* and holder's [consensus][Consensus] and then dispatches it to the verifier
*/
interface Dispatcher {
/**
* Assembles an appropriate authorization response given a [request][request]
* and holder's [consensus][Consensus] and then dispatches it to the verifier.
*
* If [ResolvedRequestObject.responseMode] is
* [ResponseMode.Query], [ResponseMode.QueryJwt], [ResponseMode.Fragment] or [ResponseMode.FragmentJwt]
* dispatching takes the form of a [redirect URI][DispatchOutcome.RedirectURI] having the response
* encoded. Wallet should redirect to this URI
*
* If [ResolvedRequestObject.responseMode] is [ResponseMode.DirectPost] or [ResponseMode.DirectPostJwt]
* then dispatching takes the form of an actual post. The returned [DispatchOutcome.VerifierResponse]
* contains the verifier's reply after receiving the post.
*
* @param request The request to reply to
* @param consensus Holder's consensus (positive or negative) to this request
* @return the dispatch outcome as described above
*/
suspend fun dispatch(request: ResolvedRequestObject, consensus: Consensus): DispatchOutcome =
when (request.responseMode) {
is ResponseMode.DirectPost -> post(request, consensus)
is ResponseMode.DirectPostJwt -> post(request, consensus)
is ResponseMode.Query -> encodeRedirectURI(request, consensus)
is ResponseMode.QueryJwt -> encodeRedirectURI(request, consensus)
is ResponseMode.Fragment -> encodeRedirectURI(request, consensus)
is ResponseMode.FragmentJwt -> encodeRedirectURI(request, consensus)
}
/**
* Method forms a suitable authorization response, based on the [request] and the provided [consensus], then
* post it to the Verifier's end-point and returns his response.
*
* This method is applicable when the [request] contains a [ResolvedRequestObject.responseMode] which is either
* [ResponseMode.DirectPost] or [ResponseMode.DirectPostJwt].
*
* @param request The request to reply to. It must contain a [ResolvedRequestObject.responseMode] which is either
* [ResponseMode.DirectPost] or [ResponseMode.DirectPostJwt]
* @param consensus Holder's consensus (positive or negative) to this request
* @return the verifier's response after receiving the authorization response.
*/
suspend fun post(request: ResolvedRequestObject, consensus: Consensus): DispatchOutcome.VerifierResponse
/**
* Method forms a suitable authorization response, based on the [request] and the provided [consensus], and then
* encodes this response to a URI.
* To this URI, the wallet (caller) must redirect its authorization response
*
* This method is applicable when [request] contains a [ResolvedRequestObject.responseMode] which is one of
* [ResponseMode.Query], [ResponseMode.QueryJwt], [ResponseMode.Fragment] or [ResponseMode.FragmentJwt]
*
* @param request The request to reply to. It must contain a [ResolvedRequestObject.responseMode] which is one of
* [ResponseMode.Query], [ResponseMode.QueryJwt], [ResponseMode.Fragment] or [ResponseMode.FragmentJwt]
* @param consensus Holder's consensus (positive or negative) to this request
* @return a URI pointing to the verifier to which the wallet(caller) must redirect its response. This URI carries
* the authorization response
*/
suspend fun encodeRedirectURI(request: ResolvedRequestObject, consensus: Consensus): DispatchOutcome.RedirectURI
}