diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-10-08 10:30:15 -0400 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-10-08 10:30:15 -0400 |
commit | 1cbf881835fc33859a31645f886c5d3787ed48f8 (patch) | |
tree | eb7a8ac803e33283ea0efffa015c8bd96ca40c29 /server/src/auth.rs | |
parent | b727db0d64f4250742b0ebaac0149c1224a0d040 (diff) |
Add access token validation
Diffstat (limited to 'server/src/auth.rs')
-rw-r--r-- | server/src/auth.rs | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/server/src/auth.rs b/server/src/auth.rs index c5f9e64..01ee467 100644 --- a/server/src/auth.rs +++ b/server/src/auth.rs @@ -1,9 +1,12 @@ use std::{ + collections::HashMap, env, num::NonZeroUsize, - sync::{Arc, Mutex}, collections::HashMap, + sync::{Arc, Mutex}, }; +use crate::error::BridgeError; +use chrono::Utc; use lru::LruCache; use openidconnect::{ core::{CoreClient, CoreProviderMetadata, CoreResponseType}, @@ -12,9 +15,9 @@ use openidconnect::{ AccessTokenHash, AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, }; +use serde::{Deserialize, Serialize}; use tracing::info; use uuid::Uuid; -use serde::{Deserialize, Serialize}; pub struct LoginState { csrf_token: CsrfToken, @@ -91,15 +94,58 @@ impl Authenticator { .url(); let user_id = EndUserId::new(); self.login_cache - .lock().unwrap() + .lock() + .unwrap() .put(user_id.clone(), LoginState { csrf_token, nonce }); (user_id, auth_url) } - pub async fn authenticate(&self, user_id: EndUserId, auth_params: HashMap<String, String>) { - let state = self.login_cache.lock().unwrap().pop(&user_id).unwrap(); - info!("state: {:?}, {:?}", state.csrf_token.secret(), state.nonce.secret()); + pub async fn authenticate( + &self, + user_id: EndUserId, + auth_params: HashMap<String, String>, + ) -> Result<(), BridgeError> { + // TODO: If the token is missing from the cache, client should retry logging in. + let state = self + .login_cache + .lock() + .unwrap() + .pop(&user_id) + .ok_or(BridgeError::InvalidRequest("token missing".to_string()))?; + info!( + "state: {:?}, {:?}", + state.csrf_token.secret(), + state.nonce.secret() + ); + if Some(state.csrf_token.secret()) != auth_params.get("state") { + return Err(BridgeError::InvalidRequest( + "token validation failed".to_string(), + )); + } + let authorization_code = AuthorizationCode::new( + auth_params + .get("code") + .ok_or(BridgeError::InvalidRequest( + "missing 'code' param".to_string(), + ))? + .to_string(), + ); + + let token = self + .client + .exchange_code(authorization_code) + .request_async(async_http_client) + .await?; + info!("Got token {token:#?}"); + + let id_token = token + .id_token() + .ok_or(BridgeError::InvalidRequest("Server did not return an IdToken".to_string()))?; + let claims = id_token.claims(&self.client.id_token_verifier(), &state.nonce)?; + + info!("Got claims {claims:#?}"); - // params: {"session_state": "909b9959-041b-4a98-84d0-5f978bc8a679", "code": "2b4e95d1-0000-4b28-b49d-7a9de731e82b.909b9959-041b-4a98-84d0-5f978bc8a679.a382d869-4e34-42f1-a64d-24a224b9d338", "state": "a7Hff_hF_FOCqPCxmA1ZXg + // params: {"session_state": "909b9959-041b-4a98-84d0-5f978bc8a679", "code": "2b4e95d1-0000-4b28-b49d-7a9de731e82b.909b9959-041b-4a98-84d0-5f978bc8a679.a382d869-4e34-42f1-a64d-24a224b9d338", "state": "a7Hff_hF_FOCqPCxmA1ZXg + Err(BridgeError::Internal("todo".to_string())) } } |