diff --git a/.sqlx/query-1e7d0d2dd54b60b2d71c25fdeae16890d776a1f9120384769d72781f3d857b63.json b/.sqlx/query-1e7d0d2dd54b60b2d71c25fdeae16890d776a1f9120384769d72781f3d857b63.json new file mode 100644 index 0000000..1b34544 --- /dev/null +++ b/.sqlx/query-1e7d0d2dd54b60b2d71c25fdeae16890d776a1f9120384769d72781f3d857b63.json @@ -0,0 +1,16 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO application_refresh_tokens (refresh_token_hash, session_id, issued_at_utc, expires_at_utc)\n VALUES ($1, $2, NOW(), $3)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Bytea", + "Int4", + "Timestamp" + ] + }, + "nullable": [] + }, + "hash": "1e7d0d2dd54b60b2d71c25fdeae16890d776a1f9120384769d72781f3d857b63" +} diff --git a/src/store.rs b/src/store.rs index 7faa391..0a11630 100644 --- a/src/store.rs +++ b/src/store.rs @@ -166,6 +166,26 @@ impl<'a, 'txn> IdCoopStoreTxn<'a, 'txn> { Ok(()) } + pub async fn issue_refresh_token( + &mut self, + refresh_token_hash: &[u8], + session_id: i32, + expires_at: DateTime, + ) -> eyre::Result<()> { + let expires_at = expires_at.naive_utc(); + sqlx::query!( + " + INSERT INTO application_refresh_tokens (refresh_token_hash, session_id, issued_at_utc, expires_at_utc) + VALUES ($1, $2, NOW(), $3) + ", + refresh_token_hash, session_id, expires_at + ) + .execute(&mut **self.txn) + .await + .context("failed to issue access token")?; + Ok(()) + } + /// Creates a user and returns the user ID. pub async fn create_user(&mut self, cu: CreateUser) -> eyre::Result { let r = sqlx::query!( diff --git a/src/web/oauth_openid/token.rs b/src/web/oauth_openid/token.rs index a5f2473..15df95f 100644 --- a/src/web/oauth_openid/token.rs +++ b/src/web/oauth_openid/token.rs @@ -302,6 +302,14 @@ pub async fn oidc_token( ) .await .context("issue_access_token")?; + txn.issue_refresh_token( + &refresh_token_hash, + session_id, + // TODO Support custom expiry, not 100 years + Utc::now() + Duration::days(365 * 100), + ) + .await + .context("issue_refresh_token")?; Ok(Ok(session_id)) })