@@ -34,7 +34,7 @@ Or add the following line to your Cargo.toml:
3434casdoor-sdk-rust = " 1"
3535```
3636
37- ## Example
37+ ## Example init Casdoor config
3838
3939``` rust
4040#[cfg(test)]
@@ -86,3 +86,103 @@ nCCJHBcAyFnm1hdvdwEdH33jDBjNB6ciotJZrf/3VYaIWSalADosHAgMWfXuWP+h
8686 }
8787}
8888```
89+
90+ ## Example with ` actix_web_httpauth ` and ` actix_web `
91+
92+ ``` rust
93+ use actix_web :: {error, post, HttpResponse , web :: {Bytes , Data }, dev :: ServiceRequest , HttpServer , App };
94+ use actix_web_httpauth :: {middleware :: HttpAuthentication , extractors :: bearer :: BearerAuth };
95+ use casdoor_sdk_rust :: {AuthSdk , BasicTokenType , Config };
96+ use oauth2 :: {TokenIntrospectionResponse , TokenResponse };
97+ use serde :: {Deserialize , Serialize };
98+
99+ #[derive(Serialize , Deserialize )]
100+ struct NewToken {
101+ access_token : String ,
102+ token_type : BasicTokenType ,
103+ expires_in : Option <u64 >,
104+ refresh_token : String ,
105+ scopes : String ,
106+ // This field is not implementing in OAuth2, thats it's an extra field
107+ // and its only use in OpenID Connect
108+ id_token : String
109+ }
110+
111+ async fn validation (
112+ req : ServiceRequest ,
113+ credentials : Option <BearerAuth >
114+ ) -> Result <ServiceRequest , (error :: Error , ServiceRequest )> {
115+ match credentials {
116+ Some (token ) => {
117+ let auth_sdk = req . app_data :: <Data <AuthSdk >>(). unwrap ();
118+
119+ let bearer_token = auth_sdk . parse_jwt_token (token . token ());
120+
121+ match bearer_token {
122+ Ok (tk ) => {
123+ println! (" request from: {:?}" , tk . user);
124+ // https://datatracker.ietf.org/doc/html/rfc7662#section-2.2
125+ // if token is not active it's not valid
126+ let flag = auth_sdk . introspect_access_token (token . token (). to_string ()). await . unwrap ();
127+
128+ if flag . active () {
129+ Ok (req )
130+ } else {
131+ Err ((error :: ErrorUnauthorized (" token must be active, refresh it" ), req ))
132+ }
133+ }
134+ Err (e ) => {
135+ Err ((error :: ErrorUnauthorized (format! (" bad bearer: {}" , e . to_string ())), req ))
136+ }
137+ }
138+ },
139+ None => {
140+ Err ((error :: ErrorBadRequest (" request is not valid" ), req ))
141+ }
142+ }
143+ }
144+
145+ #[post(" /refresh_token" )]
146+ pub async fn refresh_token (bytes : Bytes , csd : Data <AuthSdk >) -> HttpResponse {
147+ match String :: from_utf8 (bytes . to_vec ()) {
148+ Ok (token_string ) => {
149+ let tk = csd . refresh_oauth_token (token_string ). await . unwrap ();
150+ let tk_struct = NewToken {
151+ access_token : tk . access_token (). secret (). to_owned (),
152+ token_type : tk . token_type (). to_owned (),
153+ expires_in : Some (tk . expires_in (). unwrap (). as_secs ()),
154+ refresh_token : tk . refresh_token (). unwrap (). secret (). to_owned (),
155+ scopes : tk . scopes (). unwrap ()[0 ]. to_string (),
156+ id_token : tk . extra_fields (). id_token. to_string (),
157+ };
158+
159+ let tk_answer_json = serde_json :: to_string (& tk_struct ). unwrap ();
160+ HttpResponse :: Ok (). body (tk_answer_json )
161+ }
162+ Err (e ) => {
163+ HttpResponse :: BadRequest (). body (e . to_string ())
164+ }
165+ }
166+ }
167+
168+ fn init_casdoor () -> AuthSdk {
169+ let app = Config :: from_toml (" ./casdoor.toml" ). unwrap ();
170+ app . into_sdk (). authn ()
171+ }
172+
173+ #[actix_web:: main]
174+ async fn main () -> std :: io :: Result <()> {
175+ HttpServer :: new (move || {
176+ let auth = HttpAuthentication :: with_fn (validation );
177+ let auth_sdk = init_casdoor ();
178+
179+ App :: new ()
180+ . service (refresh_token )
181+ . app_data (auth_sdk )
182+ . wrap (auth )
183+ })
184+ . bind ((" 127.0.0.1" , 8080 ))?
185+ . run ()
186+ . await
187+ }
188+ ```
0 commit comments