summaryrefslogtreecommitdiff
path: root/server/src/auth.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-10-08 10:30:15 -0400
committerKjetil Orbekk <kj@orbekk.com>2022-10-08 10:30:15 -0400
commit1cbf881835fc33859a31645f886c5d3787ed48f8 (patch)
treeeb7a8ac803e33283ea0efffa015c8bd96ca40c29 /server/src/auth.rs
parentb727db0d64f4250742b0ebaac0149c1224a0d040 (diff)
Add access token validation
Diffstat (limited to 'server/src/auth.rs')
-rw-r--r--server/src/auth.rs60
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()))
}
}