@@ -7,64 +7,83 @@ use axum::{
7
7
routing:: { get, post} ,
8
8
Form , Json , Router ,
9
9
} ;
10
+ use identity_credential:: credential:: Credential ;
10
11
use oid4vci:: {
11
- credential_issuer_metadata:: CredentialsSupportedObject ,
12
+ authorization_server_metadata:: AuthorizationServerMetadata ,
13
+ credential_definition:: CredentialDefinition ,
14
+ credential_issuer:: { self , CredentialIssuer , MemStorage , Storage } ,
15
+ credential_issuer_metadata:: CredentialIssuerMetadata ,
12
16
credential_offer:: { AuthorizationCode , CredentialOffer , CredentialOfferQuery , Grants , PreAuthorizedCode } ,
13
17
credential_request:: CredentialRequest ,
14
18
credential_response:: CredentialResponse ,
15
19
token_request:: TokenRequest ,
16
20
token_response:: TokenResponse ,
21
+ CredentialFormat , JwtVcJson , JwtVcJsonParameters ,
17
22
} ;
18
- use oid4vp:: ClaimFormatDesignation ;
23
+ use oid4vp:: { token, ClaimFormatDesignation } ;
24
+ use reqwest:: Url ;
19
25
use std:: {
20
26
net:: TcpListener ,
21
27
sync:: { Arc , Mutex } ,
22
28
} ;
23
29
24
- pub struct Server {
30
+ pub struct Server < S : Storage > {
25
31
pub listener : TcpListener ,
26
- pub credential_types : Arc < Mutex < Vec < String > > > ,
27
- pub credentials_supported : Arc < Mutex < CredentialsSupportedObject > > ,
28
- pub authorization_code : Arc < Mutex < Option < AuthorizationCode > > > ,
29
- pub pre_authorized_code : Arc < Mutex < Option < PreAuthorizedCode > > > ,
32
+ pub credential_issuer : Arc < Mutex < CredentialIssuer < S > > > ,
33
+ pub credential_types : Arc < Mutex < Vec < serde_json:: Value > > > ,
30
34
pub nonce : Arc < Mutex < Option < String > > > ,
31
35
pub access_token : Arc < Mutex < Option < String > > > ,
32
36
}
33
37
34
38
#[ derive( Debug , Clone ) ]
35
- pub struct ServerState {
36
- pub credential_types : Arc < Mutex < Vec < String > > > ,
37
- pub credentials_supported : Arc < Mutex < CredentialsSupportedObject > > ,
38
- pub authorization_code : Arc < Mutex < Option < AuthorizationCode > > > ,
39
- pub pre_authorized_code : Arc < Mutex < Option < PreAuthorizedCode > > > ,
39
+ pub struct ServerState < S : Storage > {
40
+ pub credential_issuer : Arc < Mutex < CredentialIssuer < S > > > ,
41
+ pub credential_types : Arc < Mutex < Vec < serde_json:: Value > > > ,
40
42
pub nonce : Arc < Mutex < Option < String > > > ,
41
43
pub access_token : Arc < Mutex < Option < String > > > ,
42
44
}
43
45
44
- impl Server {
45
- pub fn new ( credentials_supported : CredentialsSupportedObject , listener : Option < TcpListener > ) -> Result < Self > {
46
- let listener = listener. unwrap_or_else ( || TcpListener :: bind ( "0.0.0.0:0" ) . unwrap ( ) ) ;
46
+ impl < S : Storage + Clone > Server < S > {
47
+ pub fn new (
48
+ mut credential_issuer_metadata : CredentialIssuerMetadata ,
49
+ listener : Option < TcpListener > ,
50
+ storage : S ,
51
+ ) -> Result < Self > {
52
+ let listener = listener. unwrap_or_else ( || TcpListener :: bind ( "127.0.0.1:0" ) . unwrap ( ) ) ;
53
+ let issuer_url: Url = format ! ( "http://{:?}" , listener. local_addr( ) ?) . parse ( ) ?;
54
+ credential_issuer_metadata. credential_issuer = issuer_url. clone ( ) ;
55
+ credential_issuer_metadata. credential_endpoint = format ! ( "{issuer_url}credential" ) . parse ( ) ?;
47
56
Ok ( Self {
48
57
listener,
49
- credential_types : Arc :: new ( Mutex :: new ( vec ! [ "UniversityDegree_JWT" . to_string( ) ] ) ) ,
50
- credentials_supported : Arc :: new ( Mutex :: new ( credentials_supported) ) ,
51
- authorization_code : Arc :: new ( Mutex :: new ( None ) ) ,
52
- pre_authorized_code : Arc :: new ( Mutex :: new ( Some ( PreAuthorizedCode {
53
- pre_authorized_code : generate_authorization_code ( 10 ) ,
54
- user_pin_required : true ,
55
- interval : 5 ,
56
- } ) ) ) ,
58
+ credential_issuer : Arc :: new ( Mutex :: new ( CredentialIssuer {
59
+ metadata : credential_issuer_metadata. clone ( ) ,
60
+ authorization_server_metadata : AuthorizationServerMetadata {
61
+ issuer : issuer_url. clone ( ) ,
62
+ authorization_endpoint : format ! ( "{issuer_url}authorize" ) . parse ( ) ?,
63
+ token_endpoint : format ! ( "{issuer_url}token" ) . parse ( ) ?,
64
+ ..Default :: default ( )
65
+ } ,
66
+ storage,
67
+ } ) ) ,
68
+ credential_types : Arc :: new ( Mutex :: new ( vec ! [ serde_json:: to_value( CredentialFormat {
69
+ format: JwtVcJson ,
70
+ parameters: JwtVcJsonParameters {
71
+ credential_definition: CredentialDefinition {
72
+ type_: vec![ "VerifiableCredential" . into( ) , "UniversityDegreeCredential" . into( ) ] ,
73
+ credential_subject: None ,
74
+ } ,
75
+ } ,
76
+ } )
77
+ . unwrap( ) ] ) ) ,
57
78
nonce : Arc :: new ( Mutex :: new ( None ) ) ,
58
79
access_token : Arc :: new ( Mutex :: new ( None ) ) ,
59
80
} )
60
81
}
61
82
62
83
pub async fn start ( & self ) {
63
84
let router = self . router ( ServerState {
85
+ credential_issuer : self . credential_issuer . clone ( ) ,
64
86
credential_types : self . credential_types . clone ( ) ,
65
- credentials_supported : self . credentials_supported . clone ( ) ,
66
- authorization_code : self . authorization_code . clone ( ) ,
67
- pre_authorized_code : self . pre_authorized_code . clone ( ) ,
68
87
nonce : self . nonce . clone ( ) ,
69
88
access_token : self . access_token . clone ( ) ,
70
89
} ) ;
@@ -79,58 +98,77 @@ impl Server {
79
98
} ) ;
80
99
}
81
100
82
- pub fn uri ( & self ) -> String {
83
- format ! ( "http://{}" , self . listener. local_addr( ) . unwrap( ) )
84
- }
85
-
86
101
pub fn credential_offer_uri ( & self ) -> String {
102
+ let credential_issuer = self
103
+ . credential_issuer
104
+ . lock ( )
105
+ . unwrap ( )
106
+ . metadata
107
+ . credential_issuer
108
+ . clone ( ) ;
109
+
110
+ let credentials = self . credential_types . lock ( ) . unwrap ( ) . clone ( ) ;
111
+ let authorization_code = self . credential_issuer . lock ( ) . unwrap ( ) . storage . get_authorization_code ( ) ;
112
+ let pre_authorized_code = self . credential_issuer . lock ( ) . unwrap ( ) . storage . get_pre_authorized_code ( ) ;
113
+
87
114
// TODO: dynamically create this.
88
115
CredentialOfferQuery :: CredentialOffer ( CredentialOffer {
89
- credential_issuer : self . uri ( ) ,
90
- credentials : self . credential_types . lock ( ) . unwrap ( ) . clone ( ) ,
116
+ credential_issuer,
117
+ credentials,
91
118
grants : Some ( Grants {
92
- authorization_code : self . authorization_code . lock ( ) . unwrap ( ) . clone ( ) ,
93
- pre_authorized_code : self . pre_authorized_code . lock ( ) . unwrap ( ) . clone ( ) ,
119
+ authorization_code,
120
+ pre_authorized_code,
94
121
} ) ,
95
122
} )
96
123
. to_string ( )
97
124
}
98
125
99
- fn router ( & self , server_state : ServerState ) -> Router {
126
+ fn router ( & self , server_state : ServerState < S > ) -> Router {
100
127
Router :: new ( )
128
+ . route (
129
+ "/.well-known/oauth-authorization-server" ,
130
+ get ( |State ( server_state) : State < ServerState < S > > | async move {
131
+ (
132
+ StatusCode :: OK ,
133
+ Json (
134
+ server_state
135
+ . credential_issuer
136
+ . lock ( )
137
+ . unwrap ( )
138
+ . authorization_server_metadata
139
+ . clone ( ) ,
140
+ ) ,
141
+ )
142
+ } ) ,
143
+ )
101
144
. route (
102
145
"/.well-known/openid-credential-issuer" ,
103
- get ( |State ( server_state) : State < ServerState > | async move {
146
+ get ( |State ( server_state) : State < ServerState < S > > | async move {
104
147
(
105
148
StatusCode :: OK ,
106
- Json ( server_state. credentials_supported . lock ( ) . unwrap ( ) . clone ( ) ) ,
149
+ Json ( server_state. credential_issuer . lock ( ) . unwrap ( ) . metadata . clone ( ) ) ,
107
150
)
108
151
} ) ,
109
152
)
110
153
. route (
111
154
"/token" ,
112
155
post (
113
- |State ( server_state) : State < ServerState > , Form ( token_request) : Form < TokenRequest > | async move {
114
- match server_state. pre_authorized_code . lock ( ) . unwrap ( ) . take ( ) {
115
- Some ( pre_authorized_code)
116
- if pre_authorized_code. pre_authorized_code == token_request. pre_authorized_code =>
117
- {
118
- (
119
- StatusCode :: OK ,
120
- AppendHeaders ( [ ( "Cache-Control" , "no-store" ) ] ) ,
121
- Json ( TokenResponse {
122
- // TODO: dynamically create this.
123
- access_token : "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ" . to_string ( ) ,
124
- token_type : "bearer" . to_string ( ) ,
125
- expires_in : Some ( 86400 ) ,
126
- refresh_token : None ,
127
- scope : None ,
128
- c_nonce : Some ( generate_nonce ( 16 ) ) ,
129
- c_nonce_expires_in : Some ( 86400 ) ,
130
- } ) ,
131
- )
132
- . into_response ( )
133
- }
156
+ |State ( server_state) : State < ServerState < S > > , Form ( token_request) : Form < TokenRequest > | async move {
157
+ match server_state
158
+ . credential_issuer
159
+ . lock ( )
160
+ . unwrap ( )
161
+ . storage
162
+ . get_token_response ( token_request. pre_authorized_code )
163
+ . take ( )
164
+ {
165
+ Some ( token_response) => (
166
+ StatusCode :: OK ,
167
+ AppendHeaders ( [ ( "Cache-Control" , "no-store" ) ] ) ,
168
+ Json ( token_response) ,
169
+ )
170
+ . into_response ( ) ,
171
+
134
172
// TODO: handle error response
135
173
_ => (
136
174
StatusCode :: BAD_REQUEST ,
@@ -144,19 +182,24 @@ impl Server {
144
182
)
145
183
. route (
146
184
"/credential" ,
147
- post ( |Json ( _credential_request) : Json < CredentialRequest > | async move {
148
- (
149
- StatusCode :: OK ,
150
- AppendHeaders ( [ ( "Cache-Control" , "no-store" ) ] ) ,
151
- Json ( CredentialResponse {
152
- format : ClaimFormatDesignation :: JwtVcJson ,
153
- credential : Some ( serde_json:: json!( "\" LUpixVCWJk0eOt4CXQe1NXK....WZwmhmn9OQp6YxX0a2L\" " ) ) ,
154
- transaction_id : None ,
155
- c_nonce : Some ( generate_nonce ( 16 ) ) ,
156
- c_nonce_expires_in : Some ( 86400 ) ,
157
- } ) ,
158
- )
159
- } ) ,
185
+ post (
186
+ |Json ( credential_request) : Json < CredentialRequest < JwtVcJson > > | async move {
187
+ dbg ! ( & credential_request) ;
188
+ (
189
+ StatusCode :: OK ,
190
+ AppendHeaders ( [ ( "Cache-Control" , "no-store" ) ] ) ,
191
+ Json ( CredentialResponse {
192
+ format : ClaimFormatDesignation :: JwtVcJson ,
193
+ credential : Some ( serde_json:: json!(
194
+ "\" LUpixVCWJk0eOt4CXQe1NXK....WZwmhmn9OQp6YxX0a2L\" "
195
+ ) ) ,
196
+ transaction_id : None ,
197
+ c_nonce : Some ( generate_nonce ( 16 ) ) ,
198
+ c_nonce_expires_in : Some ( 86400 ) ,
199
+ } ) ,
200
+ )
201
+ } ,
202
+ ) ,
160
203
)
161
204
. with_state ( server_state)
162
205
}
0 commit comments